summaryrefslogtreecommitdiffstats
path: root/routers/web/shared/user
diff options
context:
space:
mode:
authorDaniel Baumann <daniel@debian.org>2024-10-18 20:33:49 +0200
committerDaniel Baumann <daniel@debian.org>2024-12-12 23:57:56 +0100
commite68b9d00a6e05b3a941f63ffb696f91e554ac5ec (patch)
tree97775d6c13b0f416af55314eb6a89ef792474615 /routers/web/shared/user
parentInitial commit. (diff)
downloadforgejo-e68b9d00a6e05b3a941f63ffb696f91e554ac5ec.tar.xz
forgejo-e68b9d00a6e05b3a941f63ffb696f91e554ac5ec.zip
Adding upstream version 9.0.3.
Signed-off-by: Daniel Baumann <daniel@debian.org>
Diffstat (limited to 'routers/web/shared/user')
-rw-r--r--routers/web/shared/user/header.go163
1 files changed, 163 insertions, 0 deletions
diff --git a/routers/web/shared/user/header.go b/routers/web/shared/user/header.go
new file mode 100644
index 0000000..fd7605c
--- /dev/null
+++ b/routers/web/shared/user/header.go
@@ -0,0 +1,163 @@
+// Copyright 2022 The Gitea Authors. All rights reserved.
+// Copyright 2024 The Forgejo Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package user
+
+import (
+ "net/url"
+
+ "code.gitea.io/gitea/models/db"
+ "code.gitea.io/gitea/models/organization"
+ packages_model "code.gitea.io/gitea/models/packages"
+ access_model "code.gitea.io/gitea/models/perm/access"
+ project_model "code.gitea.io/gitea/models/project"
+ repo_model "code.gitea.io/gitea/models/repo"
+ "code.gitea.io/gitea/models/unit"
+ user_model "code.gitea.io/gitea/models/user"
+ "code.gitea.io/gitea/modules/git"
+ "code.gitea.io/gitea/modules/gitrepo"
+ "code.gitea.io/gitea/modules/log"
+ "code.gitea.io/gitea/modules/markup"
+ "code.gitea.io/gitea/modules/markup/markdown"
+ "code.gitea.io/gitea/modules/optional"
+ "code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/services/context"
+)
+
+// prepareContextForCommonProfile store some common data into context data for user's profile related pages (including the nav menu)
+// It is designed to be fast and safe to be called multiple times in one request
+func prepareContextForCommonProfile(ctx *context.Context) {
+ ctx.Data["IsPackageEnabled"] = setting.Packages.Enabled
+ ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled
+ ctx.Data["EnableFeed"] = setting.Other.EnableFeed
+ ctx.Data["FeedURL"] = ctx.ContextUser.HomeLink()
+}
+
+// PrepareContextForProfileBigAvatar set the context for big avatar view on the profile page
+func PrepareContextForProfileBigAvatar(ctx *context.Context) {
+ prepareContextForCommonProfile(ctx)
+
+ ctx.Data["IsBlocked"] = ctx.Doer != nil && user_model.IsBlocked(ctx, ctx.Doer.ID, ctx.ContextUser.ID)
+ ctx.Data["IsFollowing"] = ctx.Doer != nil && user_model.IsFollowing(ctx, ctx.Doer.ID, ctx.ContextUser.ID)
+ ctx.Data["ShowUserEmail"] = setting.UI.ShowUserEmail && ctx.ContextUser.Email != "" && ctx.IsSigned && !ctx.ContextUser.KeepEmailPrivate
+ if setting.Service.UserLocationMapURL != "" {
+ ctx.Data["ContextUserLocationMapURL"] = setting.Service.UserLocationMapURL + url.QueryEscape(ctx.ContextUser.Location)
+ }
+ // Show OpenID URIs
+ openIDs, err := user_model.GetUserOpenIDs(ctx, ctx.ContextUser.ID)
+ if err != nil {
+ ctx.ServerError("GetUserOpenIDs", err)
+ return
+ }
+ ctx.Data["OpenIDs"] = openIDs
+ if len(ctx.ContextUser.Description) != 0 {
+ content, err := markdown.RenderString(&markup.RenderContext{
+ Metas: map[string]string{"mode": "document"},
+ Ctx: ctx,
+ }, ctx.ContextUser.Description)
+ if err != nil {
+ ctx.ServerError("RenderString", err)
+ return
+ }
+ ctx.Data["RenderedDescription"] = content
+ }
+
+ showPrivate := ctx.IsSigned && (ctx.Doer.IsAdmin || ctx.Doer.ID == ctx.ContextUser.ID)
+ orgs, err := db.Find[organization.Organization](ctx, organization.FindOrgOptions{
+ UserID: ctx.ContextUser.ID,
+ IncludePrivate: showPrivate,
+ })
+ if err != nil {
+ ctx.ServerError("FindOrgs", err)
+ return
+ }
+ ctx.Data["Orgs"] = orgs
+ ctx.Data["HasOrgsVisible"] = organization.HasOrgsVisible(ctx, orgs, ctx.Doer)
+
+ badges, _, err := user_model.GetUserBadges(ctx, ctx.ContextUser)
+ if err != nil {
+ ctx.ServerError("GetUserBadges", err)
+ return
+ }
+ ctx.Data["Badges"] = badges
+
+ // in case the numbers are already provided by other functions, no need to query again (which is slow)
+ if _, ok := ctx.Data["NumFollowers"]; !ok {
+ _, ctx.Data["NumFollowers"], _ = user_model.GetUserFollowers(ctx, ctx.ContextUser, ctx.Doer, db.ListOptions{PageSize: 1, Page: 1})
+ }
+ if _, ok := ctx.Data["NumFollowing"]; !ok {
+ _, ctx.Data["NumFollowing"], _ = user_model.GetUserFollowing(ctx, ctx.ContextUser, ctx.Doer, db.ListOptions{PageSize: 1, Page: 1})
+ }
+}
+
+func FindUserProfileReadme(ctx *context.Context, doer *user_model.User) (profileDbRepo *repo_model.Repository, profileGitRepo *git.Repository, profileReadmeBlob *git.Blob, profileClose func()) {
+ profileDbRepo, err := repo_model.GetRepositoryByName(ctx, ctx.ContextUser.ID, ".profile")
+ if err == nil {
+ perm, err := access_model.GetUserRepoPermission(ctx, profileDbRepo, doer)
+ if err == nil && !profileDbRepo.IsEmpty && perm.CanRead(unit.TypeCode) {
+ if profileGitRepo, err = gitrepo.OpenRepository(ctx, profileDbRepo); err != nil {
+ log.Error("FindUserProfileReadme failed to OpenRepository: %v", err)
+ } else {
+ if commit, err := profileGitRepo.GetBranchCommit(profileDbRepo.DefaultBranch); err != nil {
+ log.Error("FindUserProfileReadme failed to GetBranchCommit: %v", err)
+ } else {
+ profileReadmeBlob, _ = commit.GetBlobByFoldedPath("README.md")
+ }
+ }
+ }
+ } else if !repo_model.IsErrRepoNotExist(err) {
+ log.Error("FindUserProfileReadme failed to GetRepositoryByName: %v", err)
+ }
+ return profileDbRepo, profileGitRepo, profileReadmeBlob, func() {
+ if profileGitRepo != nil {
+ _ = profileGitRepo.Close()
+ }
+ }
+}
+
+func RenderUserHeader(ctx *context.Context) {
+ prepareContextForCommonProfile(ctx)
+
+ _, _, profileReadmeBlob, profileClose := FindUserProfileReadme(ctx, ctx.Doer)
+ defer profileClose()
+ ctx.Data["HasProfileReadme"] = profileReadmeBlob != nil
+}
+
+func LoadHeaderCount(ctx *context.Context) error {
+ prepareContextForCommonProfile(ctx)
+
+ var err error
+
+ ctx.Data["RepoCount"], err = repo_model.CountRepository(ctx, &repo_model.SearchRepoOptions{
+ Actor: ctx.Doer,
+ OwnerID: ctx.ContextUser.ID,
+ Private: ctx.IsSigned,
+ Collaborate: optional.Some(false),
+ IncludeDescription: setting.UI.SearchRepoDescription,
+ })
+ if err != nil {
+ return err
+ }
+
+ var projectType project_model.Type
+ if ctx.ContextUser.IsOrganization() {
+ projectType = project_model.TypeOrganization
+ } else {
+ projectType = project_model.TypeIndividual
+ }
+ ctx.Data["ProjectCount"], err = db.Count[project_model.Project](ctx, project_model.SearchOptions{
+ OwnerID: ctx.ContextUser.ID,
+ IsClosed: optional.Some(false),
+ Type: projectType,
+ })
+ if err != nil {
+ return err
+ }
+ ctx.Data["PackageCount"], err = packages_model.CountOwnerPackages(ctx, ctx.ContextUser.ID)
+ if err != nil {
+ return err
+ }
+
+ return nil
+}