本站源代码
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.

452 lines
12KB

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