A fork of Gitea (see branch `mj`) adding Majority Judgment Polls 𐄷 over Issues and Merge Requests. https://git.mieuxvoter.fr
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.

279 lines
8.3 KiB

Add configurable Trust Models (#11712) * Add configurable Trust Models Gitea's default signature verification model differs from GitHub. GitHub uses signatures to verify that the committer is who they say they are - meaning that when GitHub makes a signed commit it must be the committer. The GitHub model prevents re-publishing of commits after revocation of a key and prevents re-signing of other people's commits to create a completely trusted repository signed by one key or a set of trusted keys. The default behaviour of Gitea in contrast is to always display the avatar and information related to a signature. This allows signatures to be decoupled from the committer. That being said, allowing arbitary users to present other peoples commits as theirs is not necessarily desired therefore we have a trust model whereby signatures from collaborators are marked trusted, signatures matching the commit line are marked untrusted and signatures that match a user in the db but not the committer line are marked unmatched. The problem with this model is that this conflicts with Github therefore we need to provide an option to allow users to choose the Github model should they wish to. Signed-off-by: Andrew Thornton <art27@cantab.net> * Adjust locale strings Signed-off-by: Andrew Thornton <art27@cantab.net> * as per @6543 Co-authored-by: 6543 <6543@obermui.de> * Update models/gpg_key.go * Add migration for repository Signed-off-by: Andrew Thornton <art27@cantab.net> Co-authored-by: 6543 <6543@obermui.de> Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
2 years ago
Adopt repositories (#12920) * Don't automatically delete repository files if they are present Prior to this PR Gitea would delete any repository files if they are present during creation or migration. This can in certain circumstances lead to data-loss and is slightly unpleasant. This PR provides a mechanism for Gitea to adopt repositories on creation and otherwise requires an explicit flag for deletion. PushCreate is slightly different - the create will cause adoption if that is allowed otherwise it will delete the data if that is allowed. Signed-off-by: Andrew Thornton <art27@cantab.net> * Update swagger Signed-off-by: Andrew Thornton <art27@cantab.net> * Fix tests and migrate overwrite Signed-off-by: Andrew Thornton <art27@cantab.net> * as per @lunny Only offer to adopt or overwrite if the user can do that. Allow the site administrator to adopt or overwrite in all circumstances Signed-off-by: Andrew Thornton <art27@cantab.net> * Use setting.Repository.DefaultBranch for the default branch Signed-off-by: Andrew Thornton <art27@cantab.net> * Always set setting.Repository.DefaultBranch Signed-off-by: Andrew Thornton <art27@cantab.net> * update swagger Signed-off-by: Andrew Thornton <art27@cantab.net> * update templates Signed-off-by: Andrew Thornton <art27@cantab.net> * ensure repo closed Signed-off-by: Andrew Thornton <art27@cantab.net> * Rewrite of adoption as per @6543 and @lunny Signed-off-by: Andrew Thornton <art27@cantab.net> * Apply suggestions from code review * update swagger Signed-off-by: Andrew Thornton <art27@cantab.net> * missing not Signed-off-by: Andrew Thornton <art27@cantab.net> * add modals and flash reporting Signed-off-by: Andrew Thornton <art27@cantab.net> * Make the unadopted page searchable Signed-off-by: Andrew Thornton <art27@cantab.net> * Add API Signed-off-by: Andrew Thornton <art27@cantab.net> * Fix swagger Signed-off-by: Andrew Thornton <art27@cantab.net> * fix swagger Signed-off-by: Andrew Thornton <art27@cantab.net> * Handle empty and non-master branched repositories Signed-off-by: Andrew Thornton <art27@cantab.net> * placate lint Signed-off-by: Andrew Thornton <art27@cantab.net> * remove commented out code Signed-off-by: Andrew Thornton <art27@cantab.net> Co-authored-by: techknowlogick <techknowlogick@gitea.io>
2 years ago
Adopt repositories (#12920) * Don't automatically delete repository files if they are present Prior to this PR Gitea would delete any repository files if they are present during creation or migration. This can in certain circumstances lead to data-loss and is slightly unpleasant. This PR provides a mechanism for Gitea to adopt repositories on creation and otherwise requires an explicit flag for deletion. PushCreate is slightly different - the create will cause adoption if that is allowed otherwise it will delete the data if that is allowed. Signed-off-by: Andrew Thornton <art27@cantab.net> * Update swagger Signed-off-by: Andrew Thornton <art27@cantab.net> * Fix tests and migrate overwrite Signed-off-by: Andrew Thornton <art27@cantab.net> * as per @lunny Only offer to adopt or overwrite if the user can do that. Allow the site administrator to adopt or overwrite in all circumstances Signed-off-by: Andrew Thornton <art27@cantab.net> * Use setting.Repository.DefaultBranch for the default branch Signed-off-by: Andrew Thornton <art27@cantab.net> * Always set setting.Repository.DefaultBranch Signed-off-by: Andrew Thornton <art27@cantab.net> * update swagger Signed-off-by: Andrew Thornton <art27@cantab.net> * update templates Signed-off-by: Andrew Thornton <art27@cantab.net> * ensure repo closed Signed-off-by: Andrew Thornton <art27@cantab.net> * Rewrite of adoption as per @6543 and @lunny Signed-off-by: Andrew Thornton <art27@cantab.net> * Apply suggestions from code review * update swagger Signed-off-by: Andrew Thornton <art27@cantab.net> * missing not Signed-off-by: Andrew Thornton <art27@cantab.net> * add modals and flash reporting Signed-off-by: Andrew Thornton <art27@cantab.net> * Make the unadopted page searchable Signed-off-by: Andrew Thornton <art27@cantab.net> * Add API Signed-off-by: Andrew Thornton <art27@cantab.net> * Fix swagger Signed-off-by: Andrew Thornton <art27@cantab.net> * fix swagger Signed-off-by: Andrew Thornton <art27@cantab.net> * Handle empty and non-master branched repositories Signed-off-by: Andrew Thornton <art27@cantab.net> * placate lint Signed-off-by: Andrew Thornton <art27@cantab.net> * remove commented out code Signed-off-by: Andrew Thornton <art27@cantab.net> Co-authored-by: techknowlogick <techknowlogick@gitea.io>
2 years ago
Adopt repositories (#12920) * Don't automatically delete repository files if they are present Prior to this PR Gitea would delete any repository files if they are present during creation or migration. This can in certain circumstances lead to data-loss and is slightly unpleasant. This PR provides a mechanism for Gitea to adopt repositories on creation and otherwise requires an explicit flag for deletion. PushCreate is slightly different - the create will cause adoption if that is allowed otherwise it will delete the data if that is allowed. Signed-off-by: Andrew Thornton <art27@cantab.net> * Update swagger Signed-off-by: Andrew Thornton <art27@cantab.net> * Fix tests and migrate overwrite Signed-off-by: Andrew Thornton <art27@cantab.net> * as per @lunny Only offer to adopt or overwrite if the user can do that. Allow the site administrator to adopt or overwrite in all circumstances Signed-off-by: Andrew Thornton <art27@cantab.net> * Use setting.Repository.DefaultBranch for the default branch Signed-off-by: Andrew Thornton <art27@cantab.net> * Always set setting.Repository.DefaultBranch Signed-off-by: Andrew Thornton <art27@cantab.net> * update swagger Signed-off-by: Andrew Thornton <art27@cantab.net> * update templates Signed-off-by: Andrew Thornton <art27@cantab.net> * ensure repo closed Signed-off-by: Andrew Thornton <art27@cantab.net> * Rewrite of adoption as per @6543 and @lunny Signed-off-by: Andrew Thornton <art27@cantab.net> * Apply suggestions from code review * update swagger Signed-off-by: Andrew Thornton <art27@cantab.net> * missing not Signed-off-by: Andrew Thornton <art27@cantab.net> * add modals and flash reporting Signed-off-by: Andrew Thornton <art27@cantab.net> * Make the unadopted page searchable Signed-off-by: Andrew Thornton <art27@cantab.net> * Add API Signed-off-by: Andrew Thornton <art27@cantab.net> * Fix swagger Signed-off-by: Andrew Thornton <art27@cantab.net> * fix swagger Signed-off-by: Andrew Thornton <art27@cantab.net> * Handle empty and non-master branched repositories Signed-off-by: Andrew Thornton <art27@cantab.net> * placate lint Signed-off-by: Andrew Thornton <art27@cantab.net> * remove commented out code Signed-off-by: Andrew Thornton <art27@cantab.net> Co-authored-by: techknowlogick <techknowlogick@gitea.io>
2 years ago
  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 repository
  5. import (
  6. "fmt"
  7. "io/ioutil"
  8. "os"
  9. "path"
  10. "path/filepath"
  11. "strings"
  12. "time"
  13. "code.gitea.io/gitea/models"
  14. "code.gitea.io/gitea/modules/git"
  15. "code.gitea.io/gitea/modules/log"
  16. "code.gitea.io/gitea/modules/util"
  17. "github.com/huandu/xstrings"
  18. )
  19. type transformer struct {
  20. Name string
  21. Transform func(string) string
  22. }
  23. type expansion struct {
  24. Name string
  25. Value string
  26. Transformers []transformer
  27. }
  28. var defaultTransformers = []transformer{
  29. {Name: "SNAKE", Transform: xstrings.ToSnakeCase},
  30. {Name: "KEBAB", Transform: xstrings.ToKebabCase},
  31. {Name: "CAMEL", Transform: func(str string) string {
  32. return xstrings.FirstRuneToLower(xstrings.ToCamelCase(str))
  33. }},
  34. {Name: "PASCAL", Transform: xstrings.ToCamelCase},
  35. {Name: "LOWER", Transform: strings.ToLower},
  36. {Name: "UPPER", Transform: strings.ToUpper},
  37. {Name: "TITLE", Transform: strings.Title},
  38. }
  39. func generateExpansion(src string, templateRepo, generateRepo *models.Repository) string {
  40. expansions := []expansion{
  41. {Name: "REPO_NAME", Value: generateRepo.Name, Transformers: defaultTransformers},
  42. {Name: "TEMPLATE_NAME", Value: templateRepo.Name, Transformers: defaultTransformers},
  43. {Name: "REPO_DESCRIPTION", Value: generateRepo.Description, Transformers: nil},
  44. {Name: "TEMPLATE_DESCRIPTION", Value: templateRepo.Description, Transformers: nil},
  45. {Name: "REPO_OWNER", Value: generateRepo.OwnerName, Transformers: defaultTransformers},
  46. {Name: "TEMPLATE_OWNER", Value: templateRepo.OwnerName, Transformers: defaultTransformers},
  47. {Name: "REPO_LINK", Value: generateRepo.Link(), Transformers: nil},
  48. {Name: "TEMPLATE_LINK", Value: templateRepo.Link(), Transformers: nil},
  49. {Name: "REPO_HTTPS_URL", Value: generateRepo.CloneLink().HTTPS, Transformers: nil},
  50. {Name: "TEMPLATE_HTTPS_URL", Value: templateRepo.CloneLink().HTTPS, Transformers: nil},
  51. {Name: "REPO_SSH_URL", Value: generateRepo.CloneLink().SSH, Transformers: nil},
  52. {Name: "TEMPLATE_SSH_URL", Value: templateRepo.CloneLink().SSH, Transformers: nil},
  53. }
  54. var expansionMap = make(map[string]string)
  55. for _, e := range expansions {
  56. expansionMap[e.Name] = e.Value
  57. for _, tr := range e.Transformers {
  58. expansionMap[fmt.Sprintf("%s_%s", e.Name, tr.Name)] = tr.Transform(e.Value)
  59. }
  60. }
  61. return os.Expand(src, func(key string) string {
  62. if expansion, ok := expansionMap[key]; ok {
  63. return expansion
  64. }
  65. return key
  66. })
  67. }
  68. func checkGiteaTemplate(tmpDir string) (*models.GiteaTemplate, error) {
  69. gtPath := filepath.Join(tmpDir, ".gitea", "template")
  70. if _, err := os.Stat(gtPath); os.IsNotExist(err) {
  71. return nil, nil
  72. } else if err != nil {
  73. return nil, err
  74. }
  75. content, err := ioutil.ReadFile(gtPath)
  76. if err != nil {
  77. return nil, err
  78. }
  79. gt := &models.GiteaTemplate{
  80. Path: gtPath,
  81. Content: content,
  82. }
  83. return gt, nil
  84. }
  85. func generateRepoCommit(repo, templateRepo, generateRepo *models.Repository, tmpDir string) error {
  86. commitTimeStr := time.Now().Format(time.RFC3339)
  87. authorSig := repo.Owner.NewGitSig()
  88. // Because this may call hooks we should pass in the environment
  89. env := append(os.Environ(),
  90. "GIT_AUTHOR_NAME="+authorSig.Name,
  91. "GIT_AUTHOR_EMAIL="+authorSig.Email,
  92. "GIT_AUTHOR_DATE="+commitTimeStr,
  93. "GIT_COMMITTER_NAME="+authorSig.Name,
  94. "GIT_COMMITTER_EMAIL="+authorSig.Email,
  95. "GIT_COMMITTER_DATE="+commitTimeStr,
  96. )
  97. // Clone to temporary path and do the init commit.
  98. templateRepoPath := templateRepo.RepoPath()
  99. if err := git.Clone(templateRepoPath, tmpDir, git.CloneRepoOptions{
  100. Depth: 1,
  101. Branch: templateRepo.DefaultBranch,
  102. }); err != nil {
  103. return fmt.Errorf("git clone: %v", err)
  104. }
  105. if err := util.RemoveAll(path.Join(tmpDir, ".git")); err != nil {
  106. return fmt.Errorf("remove git dir: %v", err)
  107. }
  108. // Variable expansion
  109. gt, err := checkGiteaTemplate(tmpDir)
  110. if err != nil {
  111. return fmt.Errorf("checkGiteaTemplate: %v", err)
  112. }
  113. if gt != nil {
  114. if err := util.Remove(gt.Path); err != nil {
  115. return fmt.Errorf("remove .giteatemplate: %v", err)
  116. }
  117. // Avoid walking tree if there are no globs
  118. if len(gt.Globs()) > 0 {
  119. tmpDirSlash := strings.TrimSuffix(filepath.ToSlash(tmpDir), "/") + "/"
  120. if err := filepath.Walk(tmpDirSlash, func(path string, info os.FileInfo, walkErr error) error {
  121. if walkErr != nil {
  122. return walkErr
  123. }
  124. if info.IsDir() {
  125. return nil
  126. }
  127. base := strings.TrimPrefix(filepath.ToSlash(path), tmpDirSlash)
  128. for _, g := range gt.Globs() {
  129. if g.Match(base) {
  130. content, err := ioutil.ReadFile(path)
  131. if err != nil {
  132. return err
  133. }
  134. if err := ioutil.WriteFile(path,
  135. []byte(generateExpansion(string(content), templateRepo, generateRepo)),
  136. 0644); err != nil {
  137. return err
  138. }
  139. break
  140. }
  141. }
  142. return nil
  143. }); err != nil {
  144. return err
  145. }
  146. }
  147. }
  148. if err := git.InitRepository(tmpDir, false); err != nil {
  149. return err
  150. }
  151. repoPath := repo.RepoPath()
  152. if stdout, err := git.NewCommand("remote", "add", "origin", repoPath).
  153. SetDescription(fmt.Sprintf("generateRepoCommit (git remote add): %s to %s", templateRepoPath, tmpDir)).
  154. RunInDirWithEnv(tmpDir, env); err != nil {
  155. log.Error("Unable to add %v as remote origin to temporary repo to %s: stdout %s\nError: %v", repo, tmpDir, stdout, err)
  156. return fmt.Errorf("git remote add: %v", err)
  157. }
  158. return initRepoCommit(tmpDir, repo, repo.Owner, templateRepo.DefaultBranch)
  159. }
  160. func generateGitContent(ctx models.DBContext, repo, templateRepo, generateRepo *models.Repository) (err error) {
  161. tmpDir, err := ioutil.TempDir(os.TempDir(), "gitea-"+repo.Name)
  162. if err != nil {
  163. return fmt.Errorf("Failed to create temp dir for repository %s: %v", repo.RepoPath(), err)
  164. }
  165. defer func() {
  166. if err := util.RemoveAll(tmpDir); err != nil {
  167. log.Error("RemoveAll: %v", err)
  168. }
  169. }()
  170. if err = generateRepoCommit(repo, templateRepo, generateRepo, tmpDir); err != nil {
  171. return fmt.Errorf("generateRepoCommit: %v", err)
  172. }
  173. // re-fetch repo
  174. if repo, err = models.GetRepositoryByIDCtx(ctx, repo.ID); err != nil {
  175. return fmt.Errorf("getRepositoryByID: %v", err)
  176. }
  177. repo.DefaultBranch = templateRepo.DefaultBranch
  178. gitRepo, err := git.OpenRepository(repo.RepoPath())
  179. if err != nil {
  180. return fmt.Errorf("openRepository: %v", err)
  181. }
  182. defer gitRepo.Close()
  183. if err = gitRepo.SetDefaultBranch(repo.DefaultBranch); err != nil {
  184. return fmt.Errorf("setDefaultBranch: %v", err)
  185. }
  186. if err = models.UpdateRepositoryCtx(ctx, repo, false); err != nil {
  187. return fmt.Errorf("updateRepository: %v", err)
  188. }
  189. return nil
  190. }
  191. // GenerateGitContent generates git content from a template repository
  192. func GenerateGitContent(ctx models.DBContext, templateRepo, generateRepo *models.Repository) error {
  193. if err := generateGitContent(ctx, generateRepo, templateRepo, generateRepo); err != nil {
  194. return err
  195. }
  196. if err := generateRepo.UpdateSize(ctx); err != nil {
  197. return fmt.Errorf("failed to update size for repository: %v", err)
  198. }
  199. if err := models.CopyLFS(ctx, generateRepo, templateRepo); err != nil {
  200. return fmt.Errorf("failed to copy LFS: %v", err)
  201. }
  202. return nil
  203. }
  204. // GenerateRepository generates a repository from a template
  205. func GenerateRepository(ctx models.DBContext, doer, owner *models.User, templateRepo *models.Repository, opts models.GenerateRepoOptions) (_ *models.Repository, err error) {
  206. generateRepo := &models.Repository{
  207. OwnerID: owner.ID,
  208. Owner: owner,
  209. OwnerName: owner.Name,
  210. Name: opts.Name,
  211. LowerName: strings.ToLower(opts.Name),
  212. Description: opts.Description,
  213. IsPrivate: opts.Private,
  214. IsEmpty: !opts.GitContent || templateRepo.IsEmpty,
  215. IsFsckEnabled: templateRepo.IsFsckEnabled,
  216. TemplateID: templateRepo.ID,
  217. TrustModel: templateRepo.TrustModel,
  218. }
  219. if err = models.CreateRepository(ctx, doer, owner, generateRepo, false); err != nil {
  220. return nil, err
  221. }
  222. repoPath := generateRepo.RepoPath()
  223. isExist, err := util.IsExist(repoPath)
  224. if err != nil {
  225. log.Error("Unable to check if %s exists. Error: %v", repoPath, err)
  226. return nil, err
  227. }
  228. if isExist {
  229. return nil, models.ErrRepoFilesAlreadyExist{
  230. Uname: generateRepo.OwnerName,
  231. Name: generateRepo.Name,
  232. }
  233. }
  234. if err = checkInitRepository(owner.Name, generateRepo.Name); err != nil {
  235. return generateRepo, err
  236. }
  237. return generateRepo, nil
  238. }