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 10.0KB

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