|
- // Copyright 2014 The Gogs Authors. All rights reserved.
- // Copyright 2019 The Gitea Authors. All rights reserved.
- // Use of this source code is governed by a MIT-style
- // license that can be found in the LICENSE file.
-
- package routers
-
- import (
- "bytes"
- "net/http"
- "strings"
-
- "code.gitea.io/gitea/services/repository"
-
- "code.gitea.io/gitea/models"
- "code.gitea.io/gitea/modules/base"
- "code.gitea.io/gitea/modules/context"
- code_indexer "code.gitea.io/gitea/modules/indexer/code"
- "code.gitea.io/gitea/modules/log"
- "code.gitea.io/gitea/modules/setting"
- "code.gitea.io/gitea/modules/structs"
- "code.gitea.io/gitea/modules/util"
- "code.gitea.io/gitea/routers/user"
- )
-
- const (
- // tplHome home page template
- tplHome base.TplName = "home"
- // tplExploreRepos explore repositories page template
- tplExploreRepos base.TplName = "explore/repos"
- // tplExploreDataset explore datasets page template
- tplExploreDataset base.TplName = "explore/datasets"
- // tplExploreUsers explore users page template
- tplExploreUsers base.TplName = "explore/users"
- // tplExploreOrganizations explore organizations page template
- tplExploreOrganizations base.TplName = "explore/organizations"
- // tplExploreCode explore code page template
- tplExploreCode base.TplName = "explore/code"
- tplExploreImages base.TplName = "explore/images"
- tplExploreExploreDataAnalysis base.TplName = "explore/data_analysis"
- )
-
- // Home render home page
- func Home(ctx *context.Context) {
- ctx.Data["PageIsHome"] = true
- ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled
- setRecommendURL(ctx)
- ctx.HTML(200, tplHome)
- }
-
- func setRecommendURL(ctx *context.Context) {
- addr := setting.RecommentRepoAddr[10:]
- start := strings.Index(addr, "/")
- end := strings.Index(addr, "raw")
- if start != -1 && end != -1 {
- ctx.Data["RecommendURL"] = addr[start:end]
- } else {
- ctx.Data["RecommendURL"] = setting.RecommentRepoAddr
- }
-
- ctx.Data["page_title"] = ctx.Tr("home.page_title")
- ctx.Data["page_small_title"] = ctx.Tr("home.page_small_title")
- ctx.Data["page_description"] = ctx.Tr("home.page_description")
- ctx.Data["page_use"] = ctx.Tr("home.page_use")
- ctx.Data["page_only_dynamic"] = ctx.Tr("home.page_only_dynamic")
- ctx.Data["page_recommend_org"] = ctx.Tr("home.page_recommend_org")
- ctx.Data["page_recommend_org_desc"] = ctx.Tr("home.page_recommend_org_desc")
- ctx.Data["page_recommend_org_commit"] = ctx.Tr("home.page_recommend_org_commit")
- ctx.Data["page_recommend_org_more"] = ctx.Tr("home.page_recommend_org_more")
- ctx.Data["page_recommend_repo"] = ctx.Tr("home.page_recommend_repo")
- ctx.Data["page_recommend_repo_desc"] = ctx.Tr("home.page_recommend_repo_desc")
- ctx.Data["page_recommend_repo_commit"] = ctx.Tr("home.page_recommend_repo_commit")
- ctx.Data["page_recommend_repo_go"] = ctx.Tr("home.page_recommend_repo_go")
- ctx.Data["page_recommend_repo_more"] = ctx.Tr("home.page_recommend_repo_more")
- ctx.Data["page_dev_env"] = ctx.Tr("home.page_dev_env")
- ctx.Data["page_dev_env_desc"] = ctx.Tr("home.page_dev_env_desc")
- ctx.Data["page_dev_env_desc_title"] = ctx.Tr("home.page_dev_env_desc_title")
- ctx.Data["page_dev_env_desc_desc"] = ctx.Tr("home.page_dev_env_desc_desc")
- ctx.Data["page_dev_env_desc1_title"] = ctx.Tr("home.page_dev_env_desc1_title")
- ctx.Data["page_dev_env_desc1_desc"] = ctx.Tr("home.page_dev_env_desc1_desc")
- ctx.Data["page_dev_env_desc2_title"] = ctx.Tr("home.page_dev_env_desc2_title")
- ctx.Data["page_dev_env_desc2_desc"] = ctx.Tr("home.page_dev_env_desc2_desc")
- ctx.Data["page_dev_env_desc3_title"] = ctx.Tr("home.page_dev_env_desc3_title")
- ctx.Data["page_dev_env_desc3_desc"] = ctx.Tr("home.page_dev_env_desc3_desc")
- ctx.Data["page_dev_yunlao"] = ctx.Tr("home.page_dev_yunlao")
- ctx.Data["page_dev_yunlao_desc1"] = ctx.Tr("home.page_dev_yunlao_desc1")
- ctx.Data["page_dev_yunlao_desc2"] = ctx.Tr("home.page_dev_yunlao_desc2")
- ctx.Data["page_dev_yunlao_desc3"] = ctx.Tr("home.page_dev_yunlao_desc3")
- ctx.Data["page_dev_yunlao_desc4"] = ctx.Tr("home.page_dev_yunlao_desc4")
- ctx.Data["page_dev_yunlao_apply"] = ctx.Tr("home.page_dev_yunlao_apply")
- }
-
- func Dashboard(ctx *context.Context) {
- if ctx.IsSigned {
- if !ctx.User.IsActive && setting.Service.RegisterEmailConfirm {
- ctx.Data["Title"] = ctx.Tr("auth.active_your_account")
- ctx.HTML(200, user.TplActivate)
- } else if !ctx.User.IsActive || ctx.User.ProhibitLogin {
- log.Info("Failed authentication attempt for %s from %s", ctx.User.Name, ctx.RemoteAddr())
- ctx.Data["Title"] = ctx.Tr("auth.prohibit_login")
- ctx.HTML(200, "user/auth/prohibit_login")
- } else if ctx.User.MustChangePassword {
- ctx.Data["Title"] = ctx.Tr("auth.must_change_password")
- ctx.Data["ChangePasscodeLink"] = setting.AppSubURL + "/user/change_password"
- ctx.SetCookie("redirect_to", setting.AppSubURL+ctx.Req.URL.RequestURI(), 0, setting.AppSubURL)
- ctx.Redirect(setting.AppSubURL + "/user/settings/change_password")
- } else {
- user.Dashboard(ctx)
- }
- return
- // Check non-logged users landing page.
- } else if setting.LandingPageURL != setting.LandingPageHome {
- ctx.Redirect(setting.AppSubURL + string(setting.LandingPageURL))
- return
- }
-
- // Check auto-login.
- uname := ctx.GetCookie(setting.CookieUserName)
- if len(uname) != 0 {
- ctx.Redirect(setting.AppSubURL + "/user/login")
- return
- }
- setRecommendURL(ctx)
- ctx.Data["PageIsHome"] = true
- ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled
- ctx.HTML(200, tplHome)
- }
-
- // RepoSearchOptions when calling search repositories
- type RepoSearchOptions struct {
- OwnerID int64
- Private bool
- Restricted bool
- PageSize int
- TplName base.TplName
- Course util.OptionalBool
- }
-
- var (
- nullByte = []byte{0x00}
- )
-
- func isKeywordValid(keyword string) bool {
- return !bytes.Contains([]byte(keyword), nullByte)
- }
-
- // RenderRepoSearch render repositories search page
- func RenderRepoSearch(ctx *context.Context, opts *RepoSearchOptions) {
- page := ctx.QueryInt("page")
- if page <= 0 {
- page = 1
- }
-
- var (
- repos []*models.Repository
- count int64
- err error
- orderBy models.SearchOrderBy
- )
-
- ctx.Data["SortType"] = ctx.Query("sort")
- switch ctx.Query("sort") {
- case "newest":
- orderBy = models.SearchOrderByNewest
- case "oldest":
- orderBy = models.SearchOrderByOldest
- case "recentupdate":
- orderBy = models.SearchOrderByRecentUpdated
- case "leastupdate":
- orderBy = models.SearchOrderByLeastUpdated
- case "reversealphabetically":
- orderBy = models.SearchOrderByAlphabeticallyReverse
- case "alphabetically":
- orderBy = models.SearchOrderByAlphabetically
- case "reversesize":
- orderBy = models.SearchOrderBySizeReverse
- case "size":
- orderBy = models.SearchOrderBySize
- case "moststars":
- orderBy = models.SearchOrderByStarsReverse
- case "feweststars":
- orderBy = models.SearchOrderByStars
- case "mostforks":
- orderBy = models.SearchOrderByForksReverse
- case "fewestforks":
- orderBy = models.SearchOrderByForks
- case "hot":
- orderBy = models.SearchOrderByHot
- case "active":
- orderBy = models.SearchOrderByActive
-
- default:
- ctx.Data["SortType"] = "hot"
- orderBy = models.SearchOrderByHot
- }
- orderBy = orderBy + ",id"
- //todo:support other topics
- keyword := strings.Trim(ctx.Query("q"), " ")
- topic := strings.Trim(ctx.Query("topic"), " ")
-
- repos, count, err = models.SearchRepository(&models.SearchRepoOptions{
- ListOptions: models.ListOptions{
- Page: page,
- PageSize: opts.PageSize,
- },
- Actor: ctx.User,
- OrderBy: orderBy,
- Private: opts.Private,
- Keyword: keyword,
- OwnerID: opts.OwnerID,
- AllPublic: true,
- AllLimited: true,
- TopicName: topic,
- IncludeDescription: setting.UI.SearchRepoDescription,
- Course: opts.Course,
- })
- if err != nil {
- ctx.ServerError("SearchRepository", err)
- return
- }
-
- for _, repo := range repos {
- repo.Hot = int64(repo.NumWatches) + int64(repo.NumStars) + int64(repo.NumForks) + int64(repo.CloneCnt)
- repo.Active = int64(repo.NumIssues) + int64(repo.NumPulls) + int64(repo.NumCommit)
- }
- ctx.Data["Keyword"] = keyword
- ctx.Data["Topic"] = topic
-
- ctx.Data["Total"] = count
- ctx.Data["Repos"] = repos
- ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled
-
- pager := context.NewPagination(int(count), opts.PageSize, page, 5)
- pager.SetDefaultParams(ctx)
- pager.AddParam(ctx, "topic", "TopicOnly")
- ctx.Data["Page"] = pager
-
- recommendOrgs, err := models.GetRecommendOrgInfos()
- if err != nil {
- log.Error("GetRecommendOrgInfos failed:%v", err.Error(), ctx.Data["MsgID"])
- ctx.ServerError("GetRecommendOrgInfos", err)
- return
- }
- ctx.Data["RecommendOrgs"] = recommendOrgs
-
- ctx.HTML(http.StatusOK, opts.TplName)
- }
-
- // ExploreRepos render explore repositories page
- func ExploreRepos(ctx *context.Context) {
- ctx.Data["Title"] = ctx.Tr("explore")
- ctx.Data["PageIsExplore"] = true
- ctx.Data["PageIsExploreRepositories"] = true
- ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled
-
- var ownerID int64
- if ctx.User != nil && !ctx.User.IsAdmin {
- ownerID = ctx.User.ID
- }
-
- RenderRepoSearch(ctx, &RepoSearchOptions{
- PageSize: setting.UI.ExplorePagingNum,
- OwnerID: ownerID,
- Private: ctx.User != nil,
- TplName: tplExploreRepos,
- })
- }
-
- func ExploreDatasets(ctx *context.Context) {
- ctx.Data["Title"] = ctx.Tr("explore")
- ctx.Data["PageIsExplore"] = true
- ctx.Data["PageIsExploreDatasets"] = true
- // ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled
-
- var (
- datasets []*models.Dataset
- count int64
- err error
- orderBy models.SearchOrderBy
- )
- page := ctx.QueryInt("page")
- if page <= 0 {
- page = 1
- }
- ctx.Data["SortType"] = ctx.Query("sort")
- switch ctx.Query("sort") {
- case "newest":
- orderBy = models.SearchOrderByNewest
- case "oldest":
- orderBy = models.SearchOrderByOldest
- case "recentupdate":
- orderBy = models.SearchOrderByRecentUpdated
- case "leastupdate":
- orderBy = models.SearchOrderByLeastUpdated
- case "reversealphabetically":
- orderBy = models.SearchOrderByAlphabeticallyReverse
- case "alphabetically":
- orderBy = models.SearchOrderByAlphabetically
- case "reversesize":
- orderBy = models.SearchOrderBySizeReverse
- case "downloadtimes":
- orderBy = models.SearchOrderByDownloadTimes
- default:
- ctx.Data["SortType"] = "recentupdate"
- orderBy = models.SearchOrderByRecentUpdated
- }
-
- keyword := strings.Trim(ctx.Query("q"), " ")
-
- var ownerID int64
- if ctx.User != nil && !ctx.User.IsAdmin {
- ownerID = ctx.User.ID
- }
- opts := &models.SearchDatasetOptions{
- Keyword: keyword,
- IncludePublic: true,
- SearchOrderBy: orderBy,
- OwnerID: ownerID,
- ListOptions: models.ListOptions{
- Page: page,
- PageSize: setting.UI.ExplorePagingNum,
- },
- }
-
- datasets, count, err = models.SearchDataset(opts)
- if err != nil {
- ctx.ServerError("SearchDatasets", err)
- return
- }
-
- pager := context.NewPagination(int(count), opts.PageSize, page, 5)
- ctx.Data["Keyword"] = opts.Keyword
- pager.SetDefaultParams(ctx)
- ctx.Data["Page"] = pager
-
- ctx.Data["Datasets"] = datasets
- ctx.Data["Total"] = count
- ctx.Data["PageIsDatasets"] = true
- ctx.HTML(200, tplExploreDataset)
- }
-
- // RenderUserSearch render user search page
- func RenderUserSearch(ctx *context.Context, opts *models.SearchUserOptions, tplName base.TplName) {
- opts.Page = ctx.QueryInt("page")
- if opts.Page <= 1 {
- opts.Page = 1
- }
-
- var (
- users []*models.User
- count int64
- err error
- orderBy models.SearchOrderBy
- )
-
- ctx.Data["SortType"] = ctx.Query("sort")
- switch ctx.Query("sort") {
- case "newest":
- orderBy = models.SearchOrderByIDReverse
- case "oldest":
- orderBy = models.SearchOrderByID
- case "recentupdate":
- orderBy = models.SearchOrderByRecentUpdated
- case "leastupdate":
- orderBy = models.SearchOrderByLeastUpdated
- case "reversealphabetically":
- orderBy = models.SearchOrderByAlphabeticallyReverse
- case "alphabetically":
- orderBy = models.SearchOrderByAlphabetically
- default:
- ctx.Data["SortType"] = "alphabetically"
- orderBy = models.SearchOrderByAlphabetically
- }
-
- opts.Keyword = strings.Trim(ctx.Query("q"), " ")
- opts.OrderBy = orderBy
- if len(opts.Keyword) == 0 || isKeywordValid(opts.Keyword) {
- users, count, err = models.SearchUsers(opts)
- if err != nil {
- ctx.ServerError("SearchUsers", err)
- return
- }
- }
- ctx.Data["Keyword"] = opts.Keyword
- ctx.Data["Total"] = count
- ctx.Data["Users"] = users
- 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)
- ctx.Data["Page"] = pager
-
- ctx.HTML(200, tplName)
- }
-
- // ExploreUsers render explore users page
- func ExploreUsers(ctx *context.Context) {
- ctx.Data["Title"] = ctx.Tr("explore")
- ctx.Data["PageIsExplore"] = true
- ctx.Data["PageIsExploreUsers"] = true
- ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled
-
- RenderUserSearch(ctx, &models.SearchUserOptions{
- Actor: ctx.User,
- Type: models.UserTypeIndividual,
- ListOptions: models.ListOptions{PageSize: setting.UI.ExplorePagingNum},
- IsActive: util.OptionalBoolTrue,
- Visible: []structs.VisibleType{structs.VisibleTypePublic, structs.VisibleTypeLimited, structs.VisibleTypePrivate},
- }, tplExploreUsers)
- }
-
- // ExploreOrganizations render explore organizations page
- func ExploreOrganizations(ctx *context.Context) {
- ctx.Data["Title"] = ctx.Tr("explore")
- ctx.Data["PageIsExplore"] = true
- ctx.Data["PageIsExploreOrganizations"] = true
- ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled
-
- visibleTypes := []structs.VisibleType{structs.VisibleTypePublic}
- if ctx.User != nil {
- visibleTypes = append(visibleTypes, structs.VisibleTypeLimited, structs.VisibleTypePrivate)
- }
-
- RenderUserSearch(ctx, &models.SearchUserOptions{
- Actor: ctx.User,
- Type: models.UserTypeOrganization,
- ListOptions: models.ListOptions{PageSize: setting.UI.ExplorePagingNum},
- Visible: visibleTypes,
- }, tplExploreOrganizations)
- }
-
- // ExploreCode render explore code page
- func ExploreCode(ctx *context.Context) {
- if !setting.Indexer.RepoIndexerEnabled {
- ctx.Redirect(setting.AppSubURL+"/explore", 302)
- return
- }
-
- ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled
- ctx.Data["Title"] = ctx.Tr("explore")
- ctx.Data["PageIsExplore"] = true
- ctx.Data["PageIsExploreCode"] = true
-
- language := strings.TrimSpace(ctx.Query("l"))
- keyword := strings.TrimSpace(ctx.Query("q"))
- page := ctx.QueryInt("page")
- if page <= 0 {
- page = 1
- }
-
- var (
- repoIDs []int64
- err error
- isAdmin bool
- userID int64
- )
- if ctx.User != nil {
- userID = ctx.User.ID
- isAdmin = ctx.User.IsAdmin
- }
-
- // guest user or non-admin user
- if ctx.User == nil || !isAdmin {
- repoIDs, err = models.FindUserAccessibleRepoIDs(ctx.User)
- if err != nil {
- ctx.ServerError("SearchResults", err)
- return
- }
- }
-
- var (
- total int
- searchResults []*code_indexer.Result
- searchResultLanguages []*code_indexer.SearchResultLanguages
- )
-
- // if non-admin login user, we need check UnitTypeCode at first
- if ctx.User != nil && len(repoIDs) > 0 {
- repoMaps, err := models.GetRepositoriesMapByIDs(repoIDs)
- if err != nil {
- ctx.ServerError("SearchResults", err)
- return
- }
-
- var rightRepoMap = make(map[int64]*models.Repository, len(repoMaps))
- repoIDs = make([]int64, 0, len(repoMaps))
- for id, repo := range repoMaps {
- if repo.CheckUnitUser(userID, isAdmin, models.UnitTypeCode) {
- rightRepoMap[id] = repo
- repoIDs = append(repoIDs, id)
- }
- }
-
- ctx.Data["RepoMaps"] = rightRepoMap
-
- total, searchResults, searchResultLanguages, err = code_indexer.PerformSearch(repoIDs, language, keyword, page, setting.UI.RepoSearchPagingNum)
- if err != nil {
- ctx.ServerError("SearchResults", err)
- return
- }
- // if non-login user or isAdmin, no need to check UnitTypeCode
- } else if (ctx.User == nil && len(repoIDs) > 0) || isAdmin {
- total, searchResults, searchResultLanguages, err = code_indexer.PerformSearch(repoIDs, language, keyword, page, setting.UI.RepoSearchPagingNum)
- if err != nil {
- ctx.ServerError("SearchResults", err)
- return
- }
-
- var loadRepoIDs = make([]int64, 0, len(searchResults))
- for _, result := range searchResults {
- var find bool
- for _, id := range loadRepoIDs {
- if id == result.RepoID {
- find = true
- break
- }
- }
- if !find {
- loadRepoIDs = append(loadRepoIDs, result.RepoID)
- }
- }
-
- repoMaps, err := models.GetRepositoriesMapByIDs(loadRepoIDs)
- if err != nil {
- ctx.ServerError("SearchResults", err)
- return
- }
-
- ctx.Data["RepoMaps"] = repoMaps
- }
-
- ctx.Data["Keyword"] = keyword
- ctx.Data["Language"] = language
- ctx.Data["SearchResults"] = searchResults
- ctx.Data["SearchResultLanguages"] = searchResultLanguages
- ctx.Data["RequireHighlightJS"] = true
- ctx.Data["PageIsViewCode"] = true
-
- pager := context.NewPagination(total, setting.UI.RepoSearchPagingNum, page, 5)
- pager.SetDefaultParams(ctx)
- pager.AddParam(ctx, "l", "Language")
- ctx.Data["Page"] = pager
-
- ctx.HTML(200, tplExploreCode)
- }
-
- func ExploreImages(ctx *context.Context) {
- ctx.HTML(200, tplExploreImages)
- }
-
- func ExploreDataAnalysis(ctx *context.Context) {
- ctx.HTML(200, tplExploreExploreDataAnalysis)
- }
-
- // NotFound render 404 page
- func NotFound(ctx *context.Context) {
- ctx.Data["Title"] = "Page Not Found"
- ctx.NotFound("home.NotFound", nil)
- }
-
- func RecommendOrgFromPromote(ctx *context.Context) {
- url := setting.RecommentRepoAddr + "organizations"
- result, err := repository.RecommendFromPromote(url)
- if err != nil {
- ctx.ServerError("500", err)
- return
- }
- resultOrg := make([]map[string]interface{}, 0)
- for _, userName := range result {
- user, err := models.GetUserByName(userName)
- if err == nil {
- userMap := make(map[string]interface{})
- userMap["Name"] = user.Name
- userMap["Description"] = user.Description
- userMap["FullName"] = user.FullName
- userMap["ID"] = user.ID
- userMap["Avatar"] = user.RelAvatarLink()
- userMap["NumRepos"] = user.NumRepos
- userMap["NumTeams"] = user.NumTeams
- userMap["NumMembers"] = user.NumMembers
- resultOrg = append(resultOrg, userMap)
- } else {
- log.Info("query user error," + err.Error())
- }
- }
-
- ctx.JSON(200, resultOrg)
- }
-
- func RecommendRepoFromPromote(ctx *context.Context) {
- result, err := repository.GetRecommendRepoFromPromote("projects")
- if err != nil {
- ctx.ServerError("500", err)
- } else {
- ctx.JSON(200, result)
- }
- }
|