2021-06-09 07:33:54 +08:00
// Copyright 2021 The Gitea Authors. All rights reserved.
2022-11-27 13:20:29 -05:00
// SPDX-License-Identifier: MIT
2021-06-09 07:33:54 +08:00
package explore
import (
"bytes"
"net/http"
2021-09-24 19:32:56 +08:00
"code.gitea.io/gitea/models/db"
2021-11-24 17:49:20 +08:00
user_model "code.gitea.io/gitea/models/user"
2021-06-09 07:33:54 +08:00
"code.gitea.io/gitea/modules/base"
2024-02-27 17:10:51 +08:00
"code.gitea.io/gitea/modules/container"
2022-06-25 19:06:01 +02:00
"code.gitea.io/gitea/modules/log"
2024-02-29 19:52:49 +01:00
"code.gitea.io/gitea/modules/optional"
2021-06-09 07:33:54 +08:00
"code.gitea.io/gitea/modules/setting"
2022-06-25 19:06:01 +02:00
"code.gitea.io/gitea/modules/sitemap"
2021-06-09 07:33:54 +08:00
"code.gitea.io/gitea/modules/structs"
2024-02-27 15:12:22 +08:00
"code.gitea.io/gitea/services/context"
2021-06-09 07:33:54 +08:00
)
const (
// tplExploreUsers explore users page template
tplExploreUsers base . TplName = "explore/users"
)
2022-01-20 18:46:10 +01:00
var nullByte = [ ] byte { 0x00 }
2021-06-09 07:33:54 +08:00
func isKeywordValid ( keyword string ) bool {
return ! bytes . Contains ( [ ] byte ( keyword ) , nullByte )
}
// RenderUserSearch render user search page
2021-11-24 17:49:20 +08:00
func RenderUserSearch ( ctx * context . Context , opts * user_model . SearchUserOptions , tplName base . TplName ) {
2022-06-25 19:06:01 +02:00
// Sitemap index for sitemap paths
2024-06-19 06:32:45 +08:00
opts . Page = int ( ctx . PathParamInt64 ( "idx" ) )
isSitemap := ctx . PathParam ( "idx" ) != ""
2022-06-25 19:06:01 +02:00
if opts . Page <= 1 {
opts . Page = ctx . FormInt ( "page" )
}
2021-06-09 07:33:54 +08:00
if opts . Page <= 1 {
opts . Page = 1
}
2022-06-25 19:06:01 +02:00
if isSitemap {
opts . PageSize = setting . UI . SitemapPagingNum
}
2021-06-09 07:33:54 +08:00
var (
2021-11-24 17:49:20 +08:00
users [ ] * user_model . User
2021-06-09 07:33:54 +08:00
count int64
err error
2021-11-24 17:49:20 +08:00
orderBy db . SearchOrderBy
2021-06-09 07:33:54 +08:00
)
2021-10-13 02:11:35 +08:00
// 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
2023-05-06 10:04:55 -04:00
2023-11-09 11:11:45 +01:00
sortOrder := ctx . FormString ( "sort" )
if sortOrder == "" {
sortOrder = setting . UI . ExploreDefaultSort
}
ctx . Data [ "SortType" ] = sortOrder
switch sortOrder {
2021-06-09 07:33:54 +08:00
case "newest" :
2021-10-13 02:11:35 +08:00
orderBy = "`user`.id DESC"
2021-06-09 07:33:54 +08:00
case "oldest" :
2021-10-13 02:11:35 +08:00
orderBy = "`user`.id ASC"
2021-06-09 07:33:54 +08:00
case "leastupdate" :
2021-10-13 02:11:35 +08:00
orderBy = "`user`.updated_unix ASC"
2021-06-09 07:33:54 +08:00
case "reversealphabetically" :
2021-10-13 02:11:35 +08:00
orderBy = "`user`.name DESC"
2022-12-12 01:00:17 +01:00
case "lastlogin" :
orderBy = "`user`.last_login_unix ASC"
case "reverselastlogin" :
orderBy = "`user`.last_login_unix DESC"
2023-05-06 10:04:55 -04:00
case "alphabetically" :
2021-10-13 02:11:35 +08:00
orderBy = "`user`.name ASC"
2023-05-06 10:04:55 -04:00
case "recentupdate" :
fallthrough
default :
// in case the sortType is not valid, we set it to recentupdate
2024-02-27 17:10:51 +08:00
sortOrder = "recentupdate"
2023-05-06 10:04:55 -04:00
ctx . Data [ "SortType" ] = "recentupdate"
orderBy = "`user`.updated_unix DESC"
2021-06-09 07:33:54 +08:00
}
2024-02-27 17:10:51 +08:00
if opts . SupportedSortOrders != nil && ! opts . SupportedSortOrders . Contains ( sortOrder ) {
ctx . NotFound ( "unsupported sort order" , nil )
return
}
2021-08-11 17:08:52 +02:00
opts . Keyword = ctx . FormTrim ( "q" )
2021-06-09 07:33:54 +08:00
opts . OrderBy = orderBy
if len ( opts . Keyword ) == 0 || isKeywordValid ( opts . Keyword ) {
2023-09-14 19:09:32 +02:00
users , count , err = user_model . SearchUsers ( ctx , opts )
2021-06-09 07:33:54 +08:00
if err != nil {
ctx . ServerError ( "SearchUsers" , err )
return
}
}
2022-06-25 19:06:01 +02:00
if isSitemap {
m := sitemap . NewSitemap ( )
for _ , item := range users {
m . Add ( sitemap . URL { URL : item . HTMLURL ( ) , LastMod : item . UpdatedUnix . AsTimePtr ( ) } )
}
ctx . Resp . Header ( ) . Set ( "Content-Type" , "text/xml" )
if _ , err := m . WriteTo ( ctx . Resp ) ; err != nil {
log . Error ( "Failed writing sitemap: %v" , err )
}
return
}
2021-06-09 07:33:54 +08:00
ctx . Data [ "Keyword" ] = opts . Keyword
ctx . Data [ "Total" ] = count
ctx . Data [ "Users" ] = users
2023-09-14 19:09:32 +02:00
ctx . Data [ "UsersTwoFaStatus" ] = user_model . UserList ( users ) . GetTwoFaStatus ( ctx )
2021-06-09 07:33:54 +08:00
ctx . Data [ "ShowUserEmail" ] = setting . UI . ShowUserEmail
ctx . Data [ "IsRepoIndexerEnabled" ] = setting . Indexer . RepoIndexerEnabled
pager := context . NewPagination ( int ( count ) , opts . PageSize , opts . Page , 5 )
pager . SetDefaultParams ( ctx )
2022-03-02 23:30:14 +08:00
for paramKey , paramVal := range opts . ExtraParamStrings {
pager . AddParamString ( paramKey , paramVal )
}
2021-06-09 07:33:54 +08:00
ctx . Data [ "Page" ] = pager
ctx . HTML ( http . StatusOK , tplName )
}
// Users render explore users page
func Users ( ctx * context . Context ) {
if setting . Service . Explore . DisableUsersPage {
ctx . Redirect ( setting . AppSubURL + "/explore/repos" )
return
}
ctx . Data [ "Title" ] = ctx . Tr ( "explore" )
ctx . Data [ "PageIsExplore" ] = true
ctx . Data [ "PageIsExploreUsers" ] = true
ctx . Data [ "IsRepoIndexerEnabled" ] = setting . Indexer . RepoIndexerEnabled
2024-02-27 17:10:51 +08:00
supportedSortOrders := container . SetOf (
"newest" ,
"oldest" ,
"alphabetically" ,
"reversealphabetically" ,
)
sortOrder := ctx . FormString ( "sort" )
if sortOrder == "" {
sortOrder = "newest"
ctx . SetFormString ( "sort" , sortOrder )
2023-05-06 10:04:55 -04:00
}
2021-11-24 17:49:20 +08:00
RenderUserSearch ( ctx , & user_model . SearchUserOptions {
2022-03-22 08:03:22 +01:00
Actor : ctx . Doer ,
2021-11-24 17:49:20 +08:00
Type : user_model . UserTypeIndividual ,
2021-09-24 19:32:56 +08:00
ListOptions : db . ListOptions { PageSize : setting . UI . ExplorePagingNum } ,
2024-02-29 19:52:49 +01:00
IsActive : optional . Some ( true ) ,
2021-06-09 07:33:54 +08:00
Visible : [ ] structs . VisibleType { structs . VisibleTypePublic , structs . VisibleTypeLimited , structs . VisibleTypePrivate } ,
2024-02-27 17:10:51 +08:00
SupportedSortOrders : supportedSortOrders ,
2021-06-09 07:33:54 +08:00
} , tplExploreUsers )
}