You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

home.go 9.9 kB

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