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.

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