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