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.

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