gitea源码

user.go 4.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. // Copyright 2021 The Gitea Authors. All rights reserved.
  2. // SPDX-License-Identifier: MIT
  3. package explore
  4. import (
  5. "bytes"
  6. "net/http"
  7. "code.gitea.io/gitea/models/db"
  8. user_model "code.gitea.io/gitea/models/user"
  9. "code.gitea.io/gitea/modules/container"
  10. "code.gitea.io/gitea/modules/log"
  11. "code.gitea.io/gitea/modules/optional"
  12. "code.gitea.io/gitea/modules/setting"
  13. "code.gitea.io/gitea/modules/sitemap"
  14. "code.gitea.io/gitea/modules/structs"
  15. "code.gitea.io/gitea/modules/templates"
  16. "code.gitea.io/gitea/modules/util"
  17. "code.gitea.io/gitea/services/context"
  18. )
  19. const (
  20. // tplExploreUsers explore users page template
  21. tplExploreUsers templates.TplName = "explore/users"
  22. )
  23. var nullByte = []byte{0x00}
  24. func isKeywordValid(keyword string) bool {
  25. return !bytes.Contains([]byte(keyword), nullByte)
  26. }
  27. // RenderUserSearch render user search page
  28. func RenderUserSearch(ctx *context.Context, opts user_model.SearchUserOptions, tplName templates.TplName) {
  29. // Sitemap index for sitemap paths
  30. opts.Page = int(ctx.PathParamInt64("idx"))
  31. isSitemap := ctx.PathParam("idx") != ""
  32. if opts.Page <= 1 {
  33. opts.Page = ctx.FormInt("page")
  34. }
  35. if opts.Page <= 1 {
  36. opts.Page = 1
  37. }
  38. if isSitemap {
  39. opts.PageSize = setting.UI.SitemapPagingNum
  40. }
  41. var (
  42. users []*user_model.User
  43. count int64
  44. err error
  45. orderBy db.SearchOrderBy
  46. )
  47. // we can not set orderBy to `models.SearchOrderByXxx`, because there may be a JOIN in the statement, different tables may have the same name columns
  48. sortOrder := ctx.FormString("sort")
  49. if sortOrder == "" {
  50. sortOrder = setting.UI.ExploreDefaultSort
  51. }
  52. ctx.Data["SortType"] = sortOrder
  53. switch sortOrder {
  54. case "newest":
  55. orderBy = "`user`.id DESC"
  56. case "oldest":
  57. orderBy = "`user`.id ASC"
  58. case "leastupdate":
  59. orderBy = "`user`.updated_unix ASC"
  60. case "reversealphabetically":
  61. orderBy = "`user`.name DESC"
  62. case "lastlogin":
  63. orderBy = "`user`.last_login_unix ASC"
  64. case "reverselastlogin":
  65. orderBy = "`user`.last_login_unix DESC"
  66. case "alphabetically":
  67. orderBy = "`user`.name ASC"
  68. case "recentupdate":
  69. fallthrough
  70. default:
  71. // in case the sortType is not valid, we set it to recentupdate
  72. sortOrder = "recentupdate"
  73. ctx.Data["SortType"] = "recentupdate"
  74. orderBy = "`user`.updated_unix DESC"
  75. }
  76. if opts.SupportedSortOrders != nil && !opts.SupportedSortOrders.Contains(sortOrder) {
  77. ctx.NotFound(nil)
  78. return
  79. }
  80. opts.Keyword = ctx.FormTrim("q")
  81. opts.OrderBy = orderBy
  82. if len(opts.Keyword) == 0 || isKeywordValid(opts.Keyword) {
  83. users, count, err = user_model.SearchUsers(ctx, opts)
  84. if err != nil {
  85. ctx.ServerError("SearchUsers", err)
  86. return
  87. }
  88. }
  89. if isSitemap {
  90. m := sitemap.NewSitemap()
  91. for _, item := range users {
  92. m.Add(sitemap.URL{URL: item.HTMLURL(ctx), LastMod: item.UpdatedUnix.AsTimePtr()})
  93. }
  94. ctx.Resp.Header().Set("Content-Type", "text/xml")
  95. if _, err := m.WriteTo(ctx.Resp); err != nil {
  96. log.Error("Failed writing sitemap: %v", err)
  97. }
  98. return
  99. }
  100. ctx.Data["Keyword"] = opts.Keyword
  101. ctx.Data["Total"] = count
  102. ctx.Data["Users"] = users
  103. ctx.Data["UsersTwoFaStatus"] = user_model.UserList(users).GetTwoFaStatus(ctx)
  104. ctx.Data["ShowUserEmail"] = setting.UI.ShowUserEmail
  105. ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled
  106. pager := context.NewPagination(int(count), opts.PageSize, opts.Page, 5)
  107. pager.AddParamFromRequest(ctx.Req)
  108. ctx.Data["Page"] = pager
  109. ctx.HTML(http.StatusOK, tplName)
  110. }
  111. // Users render explore users page
  112. func Users(ctx *context.Context) {
  113. if setting.Service.Explore.DisableUsersPage {
  114. ctx.Redirect(setting.AppSubURL + "/explore")
  115. return
  116. }
  117. ctx.Data["OrganizationsPageIsDisabled"] = setting.Service.Explore.DisableOrganizationsPage
  118. ctx.Data["CodePageIsDisabled"] = setting.Service.Explore.DisableCodePage
  119. ctx.Data["Title"] = ctx.Tr("explore")
  120. ctx.Data["PageIsExplore"] = true
  121. ctx.Data["PageIsExploreUsers"] = true
  122. ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled
  123. supportedSortOrders := container.SetOf(
  124. "newest",
  125. "oldest",
  126. "alphabetically",
  127. "reversealphabetically",
  128. )
  129. sortOrder := ctx.FormString("sort")
  130. if sortOrder == "" {
  131. sortOrder = util.Iif(supportedSortOrders.Contains(setting.UI.ExploreDefaultSort), setting.UI.ExploreDefaultSort, "newest")
  132. ctx.SetFormString("sort", sortOrder)
  133. }
  134. RenderUserSearch(ctx, user_model.SearchUserOptions{
  135. Actor: ctx.Doer,
  136. Type: user_model.UserTypeIndividual,
  137. ListOptions: db.ListOptions{PageSize: setting.UI.ExplorePagingNum},
  138. IsActive: optional.Some(true),
  139. Visible: []structs.VisibleType{structs.VisibleTypePublic, structs.VisibleTypeLimited, structs.VisibleTypePrivate},
  140. SupportedSortOrders: supportedSortOrders,
  141. }, tplExploreUsers)
  142. }