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.

272 lines
7.2 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
  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/base"
  14. "github.com/gogits/gogs/modules/log"
  15. )
  16. func RepoAssignment(redirect bool, args ...bool) martini.Handler {
  17. return func(ctx *Context, params martini.Params) {
  18. log.Trace(fmt.Sprint(args))
  19. // valid brachname
  20. var validBranch bool
  21. // display bare quick start if it is a bare repo
  22. var displayBare bool
  23. if len(args) >= 1 {
  24. // Note: argument has wrong value in Go1.3 martini.
  25. // validBranch = args[0]
  26. validBranch = true
  27. }
  28. if len(args) >= 2 {
  29. // displayBare = args[1]
  30. displayBare = true
  31. }
  32. var (
  33. user *models.User
  34. err error
  35. isTrueOwner bool
  36. )
  37. userName := params["username"]
  38. repoName := params["reponame"]
  39. refName := params["branchname"]
  40. // Collaborators who have write access can be seen as owners.
  41. if ctx.IsSigned {
  42. ctx.Repo.IsOwner, err = models.HasAccess(ctx.User.Name, userName+"/"+repoName, models.AU_WRITABLE)
  43. if err != nil {
  44. ctx.Handle(500, "RepoAssignment(HasAccess)", err)
  45. return
  46. }
  47. isTrueOwner = ctx.User.LowerName == strings.ToLower(userName)
  48. }
  49. if !isTrueOwner {
  50. user, err = models.GetUserByName(userName)
  51. if err != nil {
  52. if err == models.ErrUserNotExist {
  53. ctx.Handle(404, "RepoAssignment(GetUserByName)", err)
  54. return
  55. } else if redirect {
  56. ctx.Redirect("/")
  57. return
  58. }
  59. ctx.Handle(500, "RepoAssignment(GetUserByName)", err)
  60. return
  61. }
  62. } else {
  63. user = ctx.User
  64. }
  65. if user == nil {
  66. if redirect {
  67. ctx.Redirect("/")
  68. return
  69. }
  70. ctx.Handle(403, "RepoAssignment", errors.New("invliad user account for single repository"))
  71. return
  72. }
  73. ctx.Repo.Owner = user
  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.AU_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["BranchName"] = ""
  139. if base.SshPort != 22 {
  140. ctx.Repo.CloneLink.SSH = fmt.Sprintf("ssh://%s@%s/%s/%s.git", base.RunUser, base.Domain, user.LowerName, repo.LowerName)
  141. } else {
  142. ctx.Repo.CloneLink.SSH = fmt.Sprintf("%s@%s:%s/%s.git", base.RunUser, base.Domain, user.LowerName, repo.LowerName)
  143. }
  144. ctx.Repo.CloneLink.HTTPS = fmt.Sprintf("%s%s/%s.git", base.AppUrl, user.LowerName, repo.LowerName)
  145. ctx.Data["CloneLink"] = ctx.Repo.CloneLink
  146. if ctx.Repo.Repository.IsGoget {
  147. ctx.Data["GoGetLink"] = fmt.Sprintf("%s%s/%s", base.AppUrl, user.LowerName, repo.LowerName)
  148. ctx.Data["GoGetImport"] = fmt.Sprintf("%s/%s/%s", base.Domain, user.LowerName, repo.LowerName)
  149. }
  150. // when repo is bare, not valid branch
  151. if !ctx.Repo.Repository.IsBare && validBranch {
  152. detect:
  153. if len(refName) > 0 {
  154. if gitRepo.IsBranchExist(refName) {
  155. ctx.Repo.IsBranch = true
  156. ctx.Repo.BranchName = refName
  157. ctx.Repo.Commit, err = gitRepo.GetCommitOfBranch(refName)
  158. if err != nil {
  159. ctx.Handle(404, "RepoAssignment invalid branch", nil)
  160. return
  161. }
  162. ctx.Repo.CommitId = ctx.Repo.Commit.Id.String()
  163. } else if gitRepo.IsTagExist(refName) {
  164. ctx.Repo.IsBranch = true
  165. ctx.Repo.BranchName = refName
  166. ctx.Repo.Commit, err = gitRepo.GetCommitOfTag(refName)
  167. if err != nil {
  168. ctx.Handle(404, "RepoAssignment invalid tag", nil)
  169. return
  170. }
  171. ctx.Repo.CommitId = ctx.Repo.Commit.Id.String()
  172. } else if len(refName) == 40 {
  173. ctx.Repo.IsCommit = true
  174. ctx.Repo.CommitId = refName
  175. ctx.Repo.BranchName = refName
  176. ctx.Repo.Commit, err = gitRepo.GetCommit(refName)
  177. if err != nil {
  178. ctx.Handle(404, "RepoAssignment invalid commit", nil)
  179. return
  180. }
  181. } else {
  182. ctx.Handle(404, "RepoAssignment invalid repo", nil)
  183. return
  184. }
  185. } else {
  186. if len(refName) == 0 {
  187. if gitRepo.IsBranchExist(ctx.Repo.Repository.DefaultBranch) {
  188. refName = ctx.Repo.Repository.DefaultBranch
  189. } else {
  190. brs, err := gitRepo.GetBranches()
  191. if err != nil {
  192. ctx.Handle(500, "RepoAssignment(GetBranches))", err)
  193. return
  194. }
  195. refName = brs[0]
  196. }
  197. }
  198. goto detect
  199. }
  200. ctx.Data["IsBranch"] = ctx.Repo.IsBranch
  201. ctx.Data["IsCommit"] = ctx.Repo.IsCommit
  202. }
  203. log.Debug("displayBare: %v; IsBare: %v", displayBare, ctx.Repo.Repository.IsBare)
  204. // repo is bare and display enable
  205. if displayBare && ctx.Repo.Repository.IsBare {
  206. log.Debug("Bare repository: %s", ctx.Repo.RepoLink)
  207. ctx.HTML(200, "repo/single_bare")
  208. return
  209. }
  210. if ctx.IsSigned {
  211. ctx.Repo.IsWatching = models.IsWatching(ctx.User.Id, repo.Id)
  212. }
  213. ctx.Data["BranchName"] = ctx.Repo.BranchName
  214. brs, err := ctx.Repo.GitRepo.GetBranches()
  215. if err != nil {
  216. log.Error("RepoAssignment(GetBranches): %v", err)
  217. }
  218. ctx.Data["Branches"] = brs
  219. ctx.Data["CommitId"] = ctx.Repo.CommitId
  220. ctx.Data["IsRepositoryWatching"] = ctx.Repo.IsWatching
  221. }
  222. }
  223. func RequireOwner() martini.Handler {
  224. return func(ctx *Context) {
  225. if !ctx.Repo.IsOwner {
  226. if !ctx.IsSigned {
  227. ctx.SetCookie("redirect_to", "/"+url.QueryEscape(ctx.Req.RequestURI))
  228. ctx.Redirect("/user/login")
  229. return
  230. }
  231. ctx.Handle(404, ctx.Req.RequestURI, nil)
  232. return
  233. }
  234. }
  235. }