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.

354 lines
9.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
8 years ago
10 years ago
8 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 routers
  5. import (
  6. "bytes"
  7. "strings"
  8. "code.gitea.io/gitea/models"
  9. "code.gitea.io/gitea/modules/base"
  10. "code.gitea.io/gitea/modules/context"
  11. "code.gitea.io/gitea/modules/search"
  12. "code.gitea.io/gitea/modules/setting"
  13. "code.gitea.io/gitea/modules/util"
  14. "code.gitea.io/gitea/routers/user"
  15. "github.com/Unknwon/paginater"
  16. )
  17. const (
  18. // tplHome home page template
  19. tplHome base.TplName = "home"
  20. // tplExploreRepos explore repositories page template
  21. tplExploreRepos base.TplName = "explore/repos"
  22. // tplExploreUsers explore users page template
  23. tplExploreUsers base.TplName = "explore/users"
  24. // tplExploreOrganizations explore organizations page template
  25. tplExploreOrganizations base.TplName = "explore/organizations"
  26. // tplExploreCode explore code page template
  27. tplExploreCode base.TplName = "explore/code"
  28. )
  29. // Home render home page
  30. func Home(ctx *context.Context) {
  31. if ctx.IsSigned {
  32. if !ctx.User.IsActive && setting.Service.RegisterEmailConfirm {
  33. ctx.Data["Title"] = ctx.Tr("auth.active_your_account")
  34. ctx.HTML(200, user.TplActivate)
  35. } else {
  36. user.Dashboard(ctx)
  37. }
  38. return
  39. }
  40. // Check auto-login.
  41. uname := ctx.GetCookie(setting.CookieUserName)
  42. if len(uname) != 0 {
  43. ctx.Redirect(setting.AppSubURL + "/user/login")
  44. return
  45. }
  46. ctx.Data["PageIsHome"] = true
  47. ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled
  48. ctx.HTML(200, tplHome)
  49. }
  50. // RepoSearchOptions when calling search repositories
  51. type RepoSearchOptions struct {
  52. OwnerID int64
  53. Private bool
  54. PageSize int
  55. TplName base.TplName
  56. }
  57. var (
  58. nullByte = []byte{0x00}
  59. )
  60. func isKeywordValid(keyword string) bool {
  61. return !bytes.Contains([]byte(keyword), nullByte)
  62. }
  63. // RenderRepoSearch render repositories search page
  64. func RenderRepoSearch(ctx *context.Context, opts *RepoSearchOptions) {
  65. page := ctx.QueryInt("page")
  66. if page <= 0 {
  67. page = 1
  68. }
  69. var (
  70. repos []*models.Repository
  71. count int64
  72. err error
  73. orderBy models.SearchOrderBy
  74. )
  75. ctx.Data["SortType"] = ctx.Query("sort")
  76. switch ctx.Query("sort") {
  77. case "newest":
  78. orderBy = models.SearchOrderByNewest
  79. case "oldest":
  80. orderBy = models.SearchOrderByOldest
  81. case "recentupdate":
  82. orderBy = models.SearchOrderByRecentUpdated
  83. case "leastupdate":
  84. orderBy = models.SearchOrderByLeastUpdated
  85. case "reversealphabetically":
  86. orderBy = models.SearchOrderByAlphabeticallyReverse
  87. case "alphabetically":
  88. orderBy = models.SearchOrderByAlphabetically
  89. case "reversesize":
  90. orderBy = models.SearchOrderBySizeReverse
  91. case "size":
  92. orderBy = models.SearchOrderBySize
  93. case "moststars":
  94. orderBy = models.SearchOrderByStarsReverse
  95. case "feweststars":
  96. orderBy = models.SearchOrderByStars
  97. case "mostforks":
  98. orderBy = models.SearchOrderByForksReverse
  99. case "fewestforks":
  100. orderBy = models.SearchOrderByForks
  101. default:
  102. ctx.Data["SortType"] = "recentupdate"
  103. orderBy = models.SearchOrderByRecentUpdated
  104. }
  105. keyword := strings.Trim(ctx.Query("q"), " ")
  106. repos, count, err = models.SearchRepositoryByName(&models.SearchRepoOptions{
  107. Page: page,
  108. PageSize: opts.PageSize,
  109. OrderBy: orderBy,
  110. Private: opts.Private,
  111. Keyword: keyword,
  112. OwnerID: opts.OwnerID,
  113. AllPublic: true,
  114. })
  115. if err != nil {
  116. ctx.ServerError("SearchRepositoryByName", err)
  117. return
  118. }
  119. ctx.Data["Keyword"] = keyword
  120. ctx.Data["Total"] = count
  121. ctx.Data["Page"] = paginater.New(int(count), opts.PageSize, page, 5)
  122. ctx.Data["Repos"] = repos
  123. ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled
  124. ctx.HTML(200, opts.TplName)
  125. }
  126. // ExploreRepos render explore repositories page
  127. func ExploreRepos(ctx *context.Context) {
  128. ctx.Data["Title"] = ctx.Tr("explore")
  129. ctx.Data["PageIsExplore"] = true
  130. ctx.Data["PageIsExploreRepositories"] = true
  131. ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled
  132. var ownerID int64
  133. if ctx.User != nil && !ctx.User.IsAdmin {
  134. ownerID = ctx.User.ID
  135. }
  136. RenderRepoSearch(ctx, &RepoSearchOptions{
  137. PageSize: setting.UI.ExplorePagingNum,
  138. OwnerID: ownerID,
  139. Private: ctx.User != nil,
  140. TplName: tplExploreRepos,
  141. })
  142. }
  143. // RenderUserSearch render user search page
  144. func RenderUserSearch(ctx *context.Context, opts *models.SearchUserOptions, tplName base.TplName) {
  145. opts.Page = ctx.QueryInt("page")
  146. if opts.Page <= 1 {
  147. opts.Page = 1
  148. }
  149. var (
  150. users []*models.User
  151. count int64
  152. err error
  153. orderBy models.SearchOrderBy
  154. )
  155. ctx.Data["SortType"] = ctx.Query("sort")
  156. switch ctx.Query("sort") {
  157. case "newest":
  158. orderBy = models.SearchOrderByIDReverse
  159. case "oldest":
  160. orderBy = models.SearchOrderByID
  161. case "recentupdate":
  162. orderBy = models.SearchOrderByRecentUpdated
  163. case "leastupdate":
  164. orderBy = models.SearchOrderByLeastUpdated
  165. case "reversealphabetically":
  166. orderBy = models.SearchOrderByAlphabeticallyReverse
  167. case "alphabetically":
  168. orderBy = models.SearchOrderByAlphabetically
  169. default:
  170. ctx.Data["SortType"] = "alphabetically"
  171. orderBy = models.SearchOrderByAlphabetically
  172. }
  173. opts.Keyword = strings.Trim(ctx.Query("q"), " ")
  174. opts.OrderBy = orderBy
  175. if len(opts.Keyword) == 0 || isKeywordValid(opts.Keyword) {
  176. users, count, err = models.SearchUsers(opts)
  177. if err != nil {
  178. ctx.ServerError("SearchUsers", err)
  179. return
  180. }
  181. }
  182. ctx.Data["Keyword"] = opts.Keyword
  183. ctx.Data["Total"] = count
  184. ctx.Data["Page"] = paginater.New(int(count), opts.PageSize, opts.Page, 5)
  185. ctx.Data["Users"] = users
  186. ctx.Data["ShowUserEmail"] = setting.UI.ShowUserEmail
  187. ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled
  188. ctx.HTML(200, tplName)
  189. }
  190. // ExploreUsers render explore users page
  191. func ExploreUsers(ctx *context.Context) {
  192. ctx.Data["Title"] = ctx.Tr("explore")
  193. ctx.Data["PageIsExplore"] = true
  194. ctx.Data["PageIsExploreUsers"] = true
  195. ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled
  196. RenderUserSearch(ctx, &models.SearchUserOptions{
  197. Type: models.UserTypeIndividual,
  198. PageSize: setting.UI.ExplorePagingNum,
  199. IsActive: util.OptionalBoolTrue,
  200. }, tplExploreUsers)
  201. }
  202. // ExploreOrganizations render explore organizations page
  203. func ExploreOrganizations(ctx *context.Context) {
  204. ctx.Data["Title"] = ctx.Tr("explore")
  205. ctx.Data["PageIsExplore"] = true
  206. ctx.Data["PageIsExploreOrganizations"] = true
  207. ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled
  208. RenderUserSearch(ctx, &models.SearchUserOptions{
  209. Type: models.UserTypeOrganization,
  210. PageSize: setting.UI.ExplorePagingNum,
  211. }, tplExploreOrganizations)
  212. }
  213. // ExploreCode render explore code page
  214. func ExploreCode(ctx *context.Context) {
  215. if !setting.Indexer.RepoIndexerEnabled {
  216. ctx.Redirect("/explore", 302)
  217. return
  218. }
  219. ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled
  220. ctx.Data["Title"] = ctx.Tr("explore")
  221. ctx.Data["PageIsExplore"] = true
  222. ctx.Data["PageIsExploreCode"] = true
  223. keyword := strings.TrimSpace(ctx.Query("q"))
  224. page := ctx.QueryInt("page")
  225. if page <= 0 {
  226. page = 1
  227. }
  228. var (
  229. repoIDs []int64
  230. err error
  231. isAdmin bool
  232. userID int64
  233. )
  234. if ctx.User != nil {
  235. userID = ctx.User.ID
  236. isAdmin = ctx.User.IsAdmin
  237. }
  238. // guest user or non-admin user
  239. if ctx.User == nil || !isAdmin {
  240. repoIDs, err = models.FindUserAccessibleRepoIDs(userID)
  241. if err != nil {
  242. ctx.ServerError("SearchResults", err)
  243. return
  244. }
  245. }
  246. var (
  247. total int
  248. searchResults []*search.Result
  249. )
  250. // if non-admin login user, we need check UnitTypeCode at first
  251. if ctx.User != nil && len(repoIDs) > 0 {
  252. repoMaps, err := models.GetRepositoriesMapByIDs(repoIDs)
  253. if err != nil {
  254. ctx.ServerError("SearchResults", err)
  255. return
  256. }
  257. var rightRepoMap = make(map[int64]*models.Repository, len(repoMaps))
  258. repoIDs = make([]int64, 0, len(repoMaps))
  259. for id, repo := range repoMaps {
  260. if repo.CheckUnitUser(userID, isAdmin, models.UnitTypeCode) {
  261. rightRepoMap[id] = repo
  262. repoIDs = append(repoIDs, id)
  263. }
  264. }
  265. ctx.Data["RepoMaps"] = rightRepoMap
  266. total, searchResults, err = search.PerformSearch(repoIDs, keyword, page, setting.UI.RepoSearchPagingNum)
  267. if err != nil {
  268. ctx.ServerError("SearchResults", err)
  269. return
  270. }
  271. // if non-login user or isAdmin, no need to check UnitTypeCode
  272. } else if (ctx.User == nil && len(repoIDs) > 0) || isAdmin {
  273. total, searchResults, err = search.PerformSearch(repoIDs, keyword, page, setting.UI.RepoSearchPagingNum)
  274. if err != nil {
  275. ctx.ServerError("SearchResults", err)
  276. return
  277. }
  278. var loadRepoIDs = make([]int64, 0, len(searchResults))
  279. for _, result := range searchResults {
  280. var find bool
  281. for _, id := range loadRepoIDs {
  282. if id == result.RepoID {
  283. find = true
  284. break
  285. }
  286. }
  287. if !find {
  288. loadRepoIDs = append(loadRepoIDs, result.RepoID)
  289. }
  290. }
  291. repoMaps, err := models.GetRepositoriesMapByIDs(loadRepoIDs)
  292. if err != nil {
  293. ctx.ServerError("SearchResults", err)
  294. return
  295. }
  296. ctx.Data["RepoMaps"] = repoMaps
  297. }
  298. ctx.Data["Keyword"] = keyword
  299. pager := paginater.New(total, setting.UI.RepoSearchPagingNum, page, 5)
  300. ctx.Data["Page"] = pager
  301. ctx.Data["SearchResults"] = searchResults
  302. ctx.Data["RequireHighlightJS"] = true
  303. ctx.Data["PageIsViewCode"] = true
  304. ctx.HTML(200, tplExploreCode)
  305. }
  306. // NotFound render 404 page
  307. func NotFound(ctx *context.Context) {
  308. ctx.Data["Title"] = "Page Not Found"
  309. ctx.NotFound("home.NotFound", nil)
  310. }