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.

320 lines
8.8 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
  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. var (
  19. validBranch bool // To valid brach name.
  20. displayBare bool // To display bare page if it is a bare repo.
  21. )
  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. } else if redirect {
  53. log.Error(4, "GetUserByName", err)
  54. ctx.Redirect(setting.AppSubUrl + "/")
  55. } else {
  56. ctx.Handle(500, "GetUserByName", err)
  57. }
  58. return
  59. }
  60. } else {
  61. u = ctx.User
  62. }
  63. if u == nil {
  64. if redirect {
  65. ctx.Redirect(setting.AppSubUrl + "/")
  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(setting.AppSubUrl + "/")
  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 {
  94. if repo.OwnerId == ctx.User.Id {
  95. ctx.Repo.IsOwner = true
  96. }
  97. // Check if current user has admin permission to repository.
  98. if u.IsOrganization() {
  99. auth, err := models.GetHighestAuthorize(u.Id, ctx.User.Id, repo.Id, 0)
  100. if err != nil {
  101. ctx.Handle(500, "GetHighestAuthorize", err)
  102. return
  103. }
  104. if auth == models.ORG_ADMIN {
  105. ctx.Repo.IsOwner = true
  106. ctx.Repo.IsAdmin = true
  107. }
  108. }
  109. }
  110. // Check access.
  111. if repo.IsPrivate && !ctx.Repo.IsOwner {
  112. if ctx.User == nil {
  113. ctx.Handle(404, "HasAccess", nil)
  114. return
  115. }
  116. hasAccess, err := models.HasAccess(ctx.User.Name, ctx.Repo.Owner.Name+"/"+repo.Name, models.READABLE)
  117. if err != nil {
  118. ctx.Handle(500, "HasAccess", err)
  119. return
  120. } else if !hasAccess {
  121. ctx.Handle(404, "HasAccess", nil)
  122. return
  123. }
  124. }
  125. ctx.Repo.HasAccess = true
  126. ctx.Data["HasAccess"] = true
  127. if repo.IsMirror {
  128. ctx.Repo.Mirror, err = models.GetMirror(repo.Id)
  129. if err != nil {
  130. ctx.Handle(500, "GetMirror", err)
  131. return
  132. }
  133. ctx.Data["MirrorInterval"] = ctx.Repo.Mirror.Interval
  134. }
  135. repo.NumOpenIssues = repo.NumIssues - repo.NumClosedIssues
  136. repo.NumOpenMilestones = repo.NumMilestones - repo.NumClosedMilestones
  137. ctx.Repo.Repository = repo
  138. ctx.Data["IsBareRepo"] = ctx.Repo.Repository.IsBare
  139. gitRepo, err := git.OpenRepository(models.RepoPath(userName, repoName))
  140. if err != nil {
  141. ctx.Handle(500, "RepoAssignment Invalid repo "+models.RepoPath(userName, repoName), err)
  142. return
  143. }
  144. ctx.Repo.GitRepo = gitRepo
  145. ctx.Repo.RepoLink = setting.AppSubUrl + "/" + u.Name + "/" + repo.Name
  146. ctx.Data["RepoLink"] = ctx.Repo.RepoLink
  147. tags, err := ctx.Repo.GitRepo.GetTags()
  148. if err != nil {
  149. ctx.Handle(500, "GetTags", err)
  150. return
  151. }
  152. ctx.Data["Tags"] = tags
  153. ctx.Repo.Repository.NumTags = len(tags)
  154. ctx.Data["Title"] = u.Name + "/" + repo.Name
  155. ctx.Data["Repository"] = repo
  156. ctx.Data["Owner"] = ctx.Repo.Repository.Owner
  157. ctx.Data["IsRepositoryOwner"] = ctx.Repo.IsOwner
  158. ctx.Data["IsRepositoryTrueOwner"] = ctx.Repo.IsTrueOwner
  159. if setting.SshPort != 22 {
  160. ctx.Repo.CloneLink.SSH = fmt.Sprintf("ssh://%s@%s:%d/%s/%s.git", setting.RunUser, setting.Domain, setting.SshPort, u.LowerName, repo.LowerName)
  161. } else {
  162. ctx.Repo.CloneLink.SSH = fmt.Sprintf("%s@%s:%s/%s.git", setting.RunUser, setting.Domain, u.LowerName, repo.LowerName)
  163. }
  164. ctx.Repo.CloneLink.HTTPS = fmt.Sprintf("%s%s/%s.git", setting.AppUrl, u.LowerName, repo.LowerName)
  165. ctx.Data["CloneLink"] = ctx.Repo.CloneLink
  166. if ctx.Repo.Repository.IsGoget {
  167. ctx.Data["GoGetLink"] = fmt.Sprintf("%s%s/%s", setting.AppUrl, u.LowerName, repo.LowerName)
  168. ctx.Data["GoGetImport"] = fmt.Sprintf("%s/%s/%s", setting.Domain, u.LowerName, repo.LowerName)
  169. }
  170. // when repo is bare, not valid branch
  171. if !ctx.Repo.Repository.IsBare && validBranch {
  172. detect:
  173. if len(refName) > 0 {
  174. if gitRepo.IsBranchExist(refName) {
  175. ctx.Repo.IsBranch = true
  176. ctx.Repo.BranchName = refName
  177. ctx.Repo.Commit, err = gitRepo.GetCommitOfBranch(refName)
  178. if err != nil {
  179. ctx.Handle(500, "RepoAssignment invalid branch", err)
  180. return
  181. }
  182. ctx.Repo.CommitId = ctx.Repo.Commit.Id.String()
  183. } else if gitRepo.IsTagExist(refName) {
  184. ctx.Repo.IsTag = true
  185. ctx.Repo.BranchName = refName
  186. ctx.Repo.Commit, err = ctx.Repo.GitRepo.GetCommitOfTag(refName)
  187. if err != nil {
  188. ctx.Handle(500, "Fail to get tag commit", err)
  189. return
  190. }
  191. ctx.Repo.CommitId = ctx.Repo.Commit.Id.String()
  192. } else if len(refName) == 40 {
  193. ctx.Repo.IsCommit = true
  194. ctx.Repo.CommitId = refName
  195. ctx.Repo.BranchName = refName
  196. ctx.Repo.Commit, err = gitRepo.GetCommit(refName)
  197. if err != nil {
  198. ctx.Handle(404, "RepoAssignment invalid commit", nil)
  199. return
  200. }
  201. } else {
  202. ctx.Handle(404, "RepoAssignment invalid repo", fmt.Errorf("branch or tag not exist: %s", refName))
  203. return
  204. }
  205. } else {
  206. if len(refName) == 0 {
  207. if gitRepo.IsBranchExist(ctx.Repo.Repository.DefaultBranch) {
  208. refName = ctx.Repo.Repository.DefaultBranch
  209. } else {
  210. brs, err := gitRepo.GetBranches()
  211. if err != nil {
  212. ctx.Handle(500, "GetBranches", err)
  213. return
  214. }
  215. refName = brs[0]
  216. }
  217. }
  218. goto detect
  219. }
  220. ctx.Data["IsBranch"] = ctx.Repo.IsBranch
  221. ctx.Data["IsTag"] = ctx.Repo.IsTag
  222. ctx.Data["IsCommit"] = ctx.Repo.IsCommit
  223. ctx.Repo.CommitsCount, err = ctx.Repo.Commit.CommitsCount()
  224. if err != nil {
  225. ctx.Handle(500, "CommitsCount", err)
  226. return
  227. }
  228. ctx.Data["CommitsCount"] = ctx.Repo.CommitsCount
  229. }
  230. // repo is bare and display enable
  231. if ctx.Repo.Repository.IsBare {
  232. log.Debug("Bare repository: %s", ctx.Repo.RepoLink)
  233. if displayBare {
  234. ctx.HTML(200, "repo/bare")
  235. }
  236. return
  237. }
  238. if ctx.IsSigned {
  239. ctx.Data["IsWatchingRepo"] = models.IsWatching(ctx.User.Id, repo.Id)
  240. ctx.Data["IsStaringRepo"] = models.IsStaring(ctx.User.Id, repo.Id)
  241. }
  242. ctx.Data["TagName"] = ctx.Repo.TagName
  243. brs, err := ctx.Repo.GitRepo.GetBranches()
  244. if err != nil {
  245. ctx.Handle(500, "GetBranches", err)
  246. return
  247. }
  248. ctx.Data["Branches"] = brs
  249. ctx.Data["BrancheCount"] = len(brs)
  250. // If not branch selected, try default one.
  251. // If default branch doesn't exists, fall back to some other branch.
  252. if ctx.Repo.BranchName == "" {
  253. if ctx.Repo.Repository.DefaultBranch != "" && gitRepo.IsBranchExist(ctx.Repo.Repository.DefaultBranch) {
  254. ctx.Repo.BranchName = ctx.Repo.Repository.DefaultBranch
  255. } else if len(brs) > 0 {
  256. ctx.Repo.BranchName = brs[0]
  257. }
  258. }
  259. ctx.Data["BranchName"] = ctx.Repo.BranchName
  260. ctx.Data["CommitId"] = ctx.Repo.CommitId
  261. }
  262. }
  263. func RequireTrueOwner() macaron.Handler {
  264. return func(ctx *Context) {
  265. if !ctx.Repo.IsTrueOwner && !ctx.Repo.IsAdmin {
  266. if !ctx.IsSigned {
  267. ctx.SetCookie("redirect_to", "/"+url.QueryEscape(setting.AppSubUrl+ctx.Req.RequestURI), 0, setting.AppSubUrl)
  268. ctx.Redirect(setting.AppSubUrl + "/user/login")
  269. return
  270. }
  271. ctx.Handle(404, ctx.Req.RequestURI, nil)
  272. return
  273. }
  274. }
  275. }
  276. // GitHookService checks if repsitory Git hooks service has been enabled.
  277. func GitHookService() macaron.Handler {
  278. return func(ctx *Context) {
  279. if !setting.Service.EnableGitHooks {
  280. ctx.Handle(404, "GitHookService", nil)
  281. return
  282. }
  283. }
  284. }