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