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