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.

home.go 9.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360
  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. }