gitea源码

public_access.go 4.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. // Copyright 2025 The Gitea Authors. All rights reserved.
  2. // SPDX-License-Identifier: MIT
  3. package setting
  4. import (
  5. "net/http"
  6. "slices"
  7. "strconv"
  8. "code.gitea.io/gitea/models/perm"
  9. "code.gitea.io/gitea/models/repo"
  10. "code.gitea.io/gitea/models/unit"
  11. "code.gitea.io/gitea/modules/setting"
  12. "code.gitea.io/gitea/modules/templates"
  13. "code.gitea.io/gitea/services/context"
  14. )
  15. const tplRepoSettingsPublicAccess templates.TplName = "repo/settings/public_access"
  16. func parsePublicAccessMode(permission string, allowed []string) (ret struct {
  17. AnonymousAccessMode, EveryoneAccessMode perm.AccessMode
  18. },
  19. ) {
  20. ret.AnonymousAccessMode = perm.AccessModeNone
  21. ret.EveryoneAccessMode = perm.AccessModeNone
  22. // if site admin forces repositories to be private, then do not allow any other access mode,
  23. // otherwise the "force private" setting would be bypassed
  24. if setting.Repository.ForcePrivate {
  25. return ret
  26. }
  27. if !slices.Contains(allowed, permission) {
  28. return ret
  29. }
  30. switch permission {
  31. case paAnonymousRead:
  32. ret.AnonymousAccessMode = perm.AccessModeRead
  33. case paEveryoneRead:
  34. ret.EveryoneAccessMode = perm.AccessModeRead
  35. case paEveryoneWrite:
  36. ret.EveryoneAccessMode = perm.AccessModeWrite
  37. }
  38. return ret
  39. }
  40. const (
  41. paNotSet = "not-set"
  42. paAnonymousRead = "anonymous-read"
  43. paEveryoneRead = "everyone-read"
  44. paEveryoneWrite = "everyone-write"
  45. )
  46. type repoUnitPublicAccess struct {
  47. UnitType unit.Type
  48. FormKey string
  49. DisplayName string
  50. PublicAccessTypes []string
  51. UnitPublicAccess string
  52. }
  53. func repoUnitPublicAccesses(ctx *context.Context) []*repoUnitPublicAccess {
  54. accesses := []*repoUnitPublicAccess{
  55. {
  56. UnitType: unit.TypeCode,
  57. DisplayName: ctx.Locale.TrString("repo.code"),
  58. PublicAccessTypes: []string{paAnonymousRead, paEveryoneRead},
  59. },
  60. {
  61. UnitType: unit.TypeIssues,
  62. DisplayName: ctx.Locale.TrString("issues"),
  63. PublicAccessTypes: []string{paAnonymousRead, paEveryoneRead},
  64. },
  65. {
  66. UnitType: unit.TypePullRequests,
  67. DisplayName: ctx.Locale.TrString("pull_requests"),
  68. PublicAccessTypes: []string{paAnonymousRead, paEveryoneRead},
  69. },
  70. {
  71. UnitType: unit.TypeReleases,
  72. DisplayName: ctx.Locale.TrString("repo.releases"),
  73. PublicAccessTypes: []string{paAnonymousRead, paEveryoneRead},
  74. },
  75. {
  76. UnitType: unit.TypeWiki,
  77. DisplayName: ctx.Locale.TrString("repo.wiki"),
  78. PublicAccessTypes: []string{paAnonymousRead, paEveryoneRead, paEveryoneWrite},
  79. },
  80. {
  81. UnitType: unit.TypeProjects,
  82. DisplayName: ctx.Locale.TrString("repo.projects"),
  83. PublicAccessTypes: []string{paAnonymousRead, paEveryoneRead},
  84. },
  85. {
  86. UnitType: unit.TypePackages,
  87. DisplayName: ctx.Locale.TrString("repo.packages"),
  88. PublicAccessTypes: []string{paAnonymousRead, paEveryoneRead},
  89. },
  90. {
  91. UnitType: unit.TypeActions,
  92. DisplayName: ctx.Locale.TrString("repo.actions"),
  93. PublicAccessTypes: []string{paAnonymousRead, paEveryoneRead},
  94. },
  95. }
  96. for _, ua := range accesses {
  97. ua.FormKey = "repo-unit-access-" + strconv.Itoa(int(ua.UnitType))
  98. for _, u := range ctx.Repo.Repository.Units {
  99. if u.Type == ua.UnitType {
  100. ua.UnitPublicAccess = paNotSet
  101. switch {
  102. case u.EveryoneAccessMode == perm.AccessModeWrite:
  103. ua.UnitPublicAccess = paEveryoneWrite
  104. case u.EveryoneAccessMode == perm.AccessModeRead:
  105. ua.UnitPublicAccess = paEveryoneRead
  106. case u.AnonymousAccessMode == perm.AccessModeRead:
  107. ua.UnitPublicAccess = paAnonymousRead
  108. }
  109. break
  110. }
  111. }
  112. }
  113. return slices.DeleteFunc(accesses, func(ua *repoUnitPublicAccess) bool {
  114. return ua.UnitPublicAccess == ""
  115. })
  116. }
  117. func PublicAccess(ctx *context.Context) {
  118. ctx.Data["PageIsSettingsPublicAccess"] = true
  119. ctx.Data["RepoUnitPublicAccesses"] = repoUnitPublicAccesses(ctx)
  120. ctx.Data["GlobalForcePrivate"] = setting.Repository.ForcePrivate
  121. if setting.Repository.ForcePrivate {
  122. ctx.Flash.Error(ctx.Tr("form.repository_force_private"), true)
  123. }
  124. ctx.HTML(http.StatusOK, tplRepoSettingsPublicAccess)
  125. }
  126. func PublicAccessPost(ctx *context.Context) {
  127. accesses := repoUnitPublicAccesses(ctx)
  128. for _, ua := range accesses {
  129. formVal := ctx.FormString(ua.FormKey)
  130. parsed := parsePublicAccessMode(formVal, ua.PublicAccessTypes)
  131. err := repo.UpdateRepoUnitPublicAccess(ctx, &repo.RepoUnit{
  132. RepoID: ctx.Repo.Repository.ID,
  133. Type: ua.UnitType,
  134. AnonymousAccessMode: parsed.AnonymousAccessMode,
  135. EveryoneAccessMode: parsed.EveryoneAccessMode,
  136. })
  137. if err != nil {
  138. ctx.ServerError("UpdateRepoUnitPublicAccess", err)
  139. return
  140. }
  141. }
  142. ctx.Flash.Success(ctx.Tr("repo.settings.update_settings_success"))
  143. ctx.Redirect(ctx.Repo.Repository.Link() + "/settings/public_access")
  144. }