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 10 kB

11 years ago
11 years ago
11 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
10 years ago
10 years ago
8 years ago
10 years ago
8 years ago
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. }