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.

297 lines
8.0 KiB

10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
  1. // Copyright 2014 The Gogs 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 middleware
  5. import (
  6. "errors"
  7. "fmt"
  8. "net/url"
  9. "strings"
  10. "github.com/Unknwon/macaron"
  11. "github.com/gogits/gogs/models"
  12. "github.com/gogits/gogs/modules/git"
  13. "github.com/gogits/gogs/modules/log"
  14. "github.com/gogits/gogs/modules/setting"
  15. )
  16. func RepoAssignment(redirect bool, args ...bool) macaron.Handler {
  17. return func(ctx *Context) {
  18. // To valid brach name.
  19. var validBranch bool
  20. // To display bare quick start if it is a bare repo.
  21. var displayBare bool
  22. if len(args) >= 1 {
  23. validBranch = args[0]
  24. }
  25. if len(args) >= 2 {
  26. displayBare = args[1]
  27. }
  28. var (
  29. u *models.User
  30. err error
  31. )
  32. userName := ctx.Params(":username")
  33. repoName := ctx.Params(":reponame")
  34. refName := ctx.Params(":branchname")
  35. if len(refName) == 0 {
  36. refName = ctx.Params(":path")
  37. }
  38. // Collaborators who have write access can be seen as owners.
  39. if ctx.IsSigned {
  40. ctx.Repo.IsOwner, err = models.HasAccess(ctx.User.Name, userName+"/"+repoName, models.WRITABLE)
  41. if err != nil {
  42. ctx.Handle(500, "HasAccess", err)
  43. return
  44. }
  45. ctx.Repo.IsTrueOwner = ctx.User.LowerName == strings.ToLower(userName)
  46. }
  47. if !ctx.Repo.IsTrueOwner {
  48. u, err = models.GetUserByName(userName)
  49. if err != nil {
  50. if err == models.ErrUserNotExist {
  51. ctx.Handle(404, "GetUserByName", err)
  52. return
  53. } else if redirect {
  54. ctx.Redirect("/")
  55. return
  56. }
  57. ctx.Handle(500, "GetUserByName", err)
  58. return
  59. }
  60. } else {
  61. u = ctx.User
  62. }
  63. if u == nil {
  64. if redirect {
  65. ctx.Redirect("/")
  66. return
  67. }
  68. ctx.Handle(404, "RepoAssignment", errors.New("invliad user account for single repository"))
  69. return
  70. }
  71. ctx.Repo.Owner = u
  72. // Organization owner team members are true owners as well.
  73. if ctx.IsSigned && ctx.Repo.Owner.IsOrganization() && ctx.Repo.Owner.IsOrgOwner(ctx.User.Id) {
  74. ctx.Repo.IsTrueOwner = true
  75. }
  76. // get repository
  77. repo, err := models.GetRepositoryByName(u.Id, repoName)
  78. if err != nil {
  79. if err == models.ErrRepoNotExist {
  80. ctx.Handle(404, "GetRepositoryByName", err)
  81. return
  82. } else if redirect {
  83. ctx.Redirect("/")
  84. return
  85. }
  86. ctx.Handle(500, "GetRepositoryByName", err)
  87. return
  88. } else if err = repo.GetOwner(); err != nil {
  89. ctx.Handle(500, "GetOwner", err)
  90. return
  91. }
  92. // Check if the mirror repository owner(mirror repository doesn't have access).
  93. if ctx.IsSigned && !ctx.Repo.IsOwner && repo.OwnerId == ctx.User.Id {
  94. ctx.Repo.IsOwner = true
  95. }
  96. // Check access.
  97. if repo.IsPrivate && !ctx.Repo.IsOwner {
  98. if ctx.User == nil {
  99. ctx.Handle(404, "HasAccess", nil)
  100. return
  101. }
  102. hasAccess, err := models.HasAccess(ctx.User.Name, ctx.Repo.Owner.Name+"/"+repo.Name, models.READABLE)
  103. if err != nil {
  104. ctx.Handle(500, "HasAccess", err)
  105. return
  106. } else if !hasAccess {
  107. ctx.Handle(404, "HasAccess", nil)
  108. return
  109. }
  110. }
  111. ctx.Repo.HasAccess = true
  112. ctx.Data["HasAccess"] = true
  113. if repo.IsMirror {
  114. ctx.Repo.Mirror, err = models.GetMirror(repo.Id)
  115. if err != nil {
  116. ctx.Handle(500, "GetMirror", err)
  117. return
  118. }
  119. ctx.Data["MirrorInterval"] = ctx.Repo.Mirror.Interval
  120. }
  121. repo.NumOpenIssues = repo.NumIssues - repo.NumClosedIssues
  122. repo.NumOpenMilestones = repo.NumMilestones - repo.NumClosedMilestones
  123. ctx.Repo.Repository = repo
  124. ctx.Data["IsBareRepo"] = ctx.Repo.Repository.IsBare
  125. gitRepo, err := git.OpenRepository(models.RepoPath(userName, repoName))
  126. if err != nil {
  127. ctx.Handle(500, "RepoAssignment Invalid repo "+models.RepoPath(userName, repoName), err)
  128. return
  129. }
  130. ctx.Repo.GitRepo = gitRepo
  131. ctx.Repo.RepoLink = "/" + u.Name + "/" + repo.Name
  132. tags, err := ctx.Repo.GitRepo.GetTags()
  133. if err != nil {
  134. ctx.Handle(500, "GetTags", err)
  135. return
  136. }
  137. ctx.Repo.Repository.NumTags = len(tags)
  138. ctx.Data["Title"] = u.Name + "/" + repo.Name
  139. ctx.Data["Repository"] = repo
  140. ctx.Data["Owner"] = ctx.Repo.Repository.Owner
  141. ctx.Data["RepoLink"] = ctx.Repo.RepoLink
  142. ctx.Data["IsRepositoryOwner"] = ctx.Repo.IsOwner
  143. ctx.Data["IsRepositoryTrueOwner"] = ctx.Repo.IsTrueOwner
  144. if setting.SshPort != 22 {
  145. ctx.Repo.CloneLink.SSH = fmt.Sprintf("ssh://%s@%s:%d/%s/%s.git", setting.RunUser, setting.Domain, setting.SshPort, u.LowerName, repo.LowerName)
  146. } else {
  147. ctx.Repo.CloneLink.SSH = fmt.Sprintf("%s@%s:%s/%s.git", setting.RunUser, setting.Domain, u.LowerName, repo.LowerName)
  148. }
  149. ctx.Repo.CloneLink.HTTPS = fmt.Sprintf("%s%s/%s.git", setting.AppUrl, u.LowerName, repo.LowerName)
  150. ctx.Data["CloneLink"] = ctx.Repo.CloneLink
  151. if ctx.Repo.Repository.IsGoget {
  152. ctx.Data["GoGetLink"] = fmt.Sprintf("%s%s/%s", setting.AppUrl, u.LowerName, repo.LowerName)
  153. ctx.Data["GoGetImport"] = fmt.Sprintf("%s/%s/%s", setting.Domain, u.LowerName, repo.LowerName)
  154. }
  155. // when repo is bare, not valid branch
  156. if !ctx.Repo.Repository.IsBare && validBranch {
  157. detect:
  158. if len(refName) > 0 {
  159. if gitRepo.IsBranchExist(refName) {
  160. ctx.Repo.IsBranch = true
  161. ctx.Repo.BranchName = refName
  162. ctx.Repo.Commit, err = gitRepo.GetCommitOfBranch(refName)
  163. if err != nil {
  164. ctx.Handle(404, "RepoAssignment invalid branch", nil)
  165. return
  166. }
  167. ctx.Repo.CommitId = ctx.Repo.Commit.Id.String()
  168. } else if gitRepo.IsTagExist(refName) {
  169. ctx.Repo.IsTag = true
  170. ctx.Repo.BranchName = refName
  171. ctx.Repo.Tag, err = gitRepo.GetTag(refName)
  172. if err != nil {
  173. ctx.Handle(404, "RepoAssignment invalid tag", nil)
  174. return
  175. }
  176. ctx.Repo.Commit, _ = ctx.Repo.Tag.Commit()
  177. ctx.Repo.CommitId = ctx.Repo.Commit.Id.String()
  178. } else if len(refName) == 40 {
  179. ctx.Repo.IsCommit = true
  180. ctx.Repo.CommitId = refName
  181. ctx.Repo.BranchName = refName
  182. ctx.Repo.Commit, err = gitRepo.GetCommit(refName)
  183. if err != nil {
  184. ctx.Handle(404, "RepoAssignment invalid commit", nil)
  185. return
  186. }
  187. } else {
  188. ctx.Handle(404, "RepoAssignment invalid repo", errors.New("branch or tag not exist"))
  189. return
  190. }
  191. } else {
  192. if len(refName) == 0 {
  193. if gitRepo.IsBranchExist(ctx.Repo.Repository.DefaultBranch) {
  194. refName = ctx.Repo.Repository.DefaultBranch
  195. } else {
  196. brs, err := gitRepo.GetBranches()
  197. if err != nil {
  198. ctx.Handle(500, "GetBranches", err)
  199. return
  200. }
  201. refName = brs[0]
  202. }
  203. }
  204. goto detect
  205. }
  206. ctx.Data["IsBranch"] = ctx.Repo.IsBranch
  207. ctx.Data["IsCommit"] = ctx.Repo.IsCommit
  208. ctx.Repo.CommitsCount, err = ctx.Repo.Commit.CommitsCount()
  209. if err != nil {
  210. ctx.Handle(500, "CommitsCount", err)
  211. return
  212. }
  213. ctx.Data["CommitsCount"] = ctx.Repo.CommitsCount
  214. }
  215. log.Debug("displayBare: %v; IsBare: %v", displayBare, ctx.Repo.Repository.IsBare)
  216. // repo is bare and display enable
  217. if displayBare && ctx.Repo.Repository.IsBare {
  218. log.Debug("Bare repository: %s", ctx.Repo.RepoLink)
  219. ctx.HTML(200, "repo/bare")
  220. return
  221. }
  222. if ctx.IsSigned {
  223. ctx.Repo.IsWatching = models.IsWatching(ctx.User.Id, repo.Id)
  224. }
  225. ctx.Data["TagName"] = ctx.Repo.TagName
  226. brs, err := ctx.Repo.GitRepo.GetBranches()
  227. if err != nil {
  228. log.Error(4, "GetBranches: %v", err)
  229. }
  230. ctx.Data["Branches"] = brs
  231. ctx.Data["BrancheCount"] = len(brs)
  232. // If not branch selected, try default one.
  233. // If default branch doesn't exists, fall back to some other branch.
  234. if ctx.Repo.BranchName == "" {
  235. if ctx.Repo.Repository.DefaultBranch != "" && gitRepo.IsBranchExist(ctx.Repo.Repository.DefaultBranch) {
  236. ctx.Repo.BranchName = ctx.Repo.Repository.DefaultBranch
  237. } else if len(brs) > 0 {
  238. ctx.Repo.BranchName = brs[0]
  239. }
  240. }
  241. ctx.Data["BranchName"] = ctx.Repo.BranchName
  242. ctx.Data["CommitId"] = ctx.Repo.CommitId
  243. ctx.Data["IsWatchingRepo"] = ctx.Repo.IsWatching
  244. }
  245. }
  246. func RequireTrueOwner() macaron.Handler {
  247. return func(ctx *Context) {
  248. if !ctx.Repo.IsTrueOwner {
  249. if !ctx.IsSigned {
  250. ctx.SetCookie("redirect_to", "/"+url.QueryEscape(ctx.Req.RequestURI))
  251. ctx.Redirect("/user/login")
  252. return
  253. }
  254. ctx.Handle(404, ctx.Req.RequestURI, nil)
  255. return
  256. }
  257. }
  258. }