diff options
author | Chai-Shi <changchaishi@gmail.com> | 2024-12-31 12:22:09 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-12-31 04:22:09 +0000 |
commit | 0387195abb82080b4c488966960f25a3e8c6fe66 (patch) | |
tree | 794cf1e7705002236a33af563729284b48a303c5 /routers | |
parent | c09656e0e0384b15405f909a0e7d7e94a373448e (diff) | |
download | gitea-0387195abb82080b4c488966960f25a3e8c6fe66.tar.gz gitea-0387195abb82080b4c488966960f25a3e8c6fe66.zip |
[Feature] Private README.md for organization (#32872)
Implemented #29503
---------
Co-authored-by: Ben Chang <ben_chang@htc.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
Diffstat (limited to 'routers')
-rw-r--r-- | routers/api/v1/repo/branch.go | 4 | ||||
-rw-r--r-- | routers/api/v1/repo/compare.go | 2 | ||||
-rw-r--r-- | routers/api/v1/repo/download.go | 2 | ||||
-rw-r--r-- | routers/api/v1/repo/file.go | 2 | ||||
-rw-r--r-- | routers/api/v1/repo/repo.go | 2 | ||||
-rw-r--r-- | routers/private/internal_repo.go | 2 | ||||
-rw-r--r-- | routers/web/org/home.go | 74 | ||||
-rw-r--r-- | routers/web/org/members.go | 4 | ||||
-rw-r--r-- | routers/web/org/teams.go | 4 | ||||
-rw-r--r-- | routers/web/shared/user/header.go | 86 | ||||
-rw-r--r-- | routers/web/user/profile.go | 7 |
11 files changed, 116 insertions, 73 deletions
diff --git a/routers/api/v1/repo/branch.go b/routers/api/v1/repo/branch.go index 67dfda39a8..2fcdd02058 100644 --- a/routers/api/v1/repo/branch.go +++ b/routers/api/v1/repo/branch.go @@ -729,7 +729,7 @@ func CreateBranchProtection(ctx *context.APIContext) { } else { if !isPlainRule { if ctx.Repo.GitRepo == nil { - ctx.Repo.GitRepo, err = gitrepo.RepositoryFromRequestContextOrOpen(ctx, ctx, ctx.Repo.Repository) + ctx.Repo.GitRepo, err = gitrepo.RepositoryFromRequestContextOrOpen(ctx, ctx.Repo.Repository) if err != nil { ctx.Error(http.StatusInternalServerError, "OpenRepository", err) return @@ -1057,7 +1057,7 @@ func EditBranchProtection(ctx *context.APIContext) { } else { if !isPlainRule { if ctx.Repo.GitRepo == nil { - ctx.Repo.GitRepo, err = gitrepo.RepositoryFromRequestContextOrOpen(ctx, ctx, ctx.Repo.Repository) + ctx.Repo.GitRepo, err = gitrepo.RepositoryFromRequestContextOrOpen(ctx, ctx.Repo.Repository) if err != nil { ctx.Error(http.StatusInternalServerError, "OpenRepository", err) return diff --git a/routers/api/v1/repo/compare.go b/routers/api/v1/repo/compare.go index 87b890cb62..a1813a8a76 100644 --- a/routers/api/v1/repo/compare.go +++ b/routers/api/v1/repo/compare.go @@ -45,7 +45,7 @@ func CompareDiff(ctx *context.APIContext) { if ctx.Repo.GitRepo == nil { var err error - ctx.Repo.GitRepo, err = gitrepo.RepositoryFromRequestContextOrOpen(ctx, ctx, ctx.Repo.Repository) + ctx.Repo.GitRepo, err = gitrepo.RepositoryFromRequestContextOrOpen(ctx, ctx.Repo.Repository) if err != nil { ctx.Error(http.StatusInternalServerError, "OpenRepository", err) return diff --git a/routers/api/v1/repo/download.go b/routers/api/v1/repo/download.go index eb967772ed..a8a23c4a8d 100644 --- a/routers/api/v1/repo/download.go +++ b/routers/api/v1/repo/download.go @@ -29,7 +29,7 @@ func DownloadArchive(ctx *context.APIContext) { if ctx.Repo.GitRepo == nil { var err error - ctx.Repo.GitRepo, err = gitrepo.RepositoryFromRequestContextOrOpen(ctx, ctx, ctx.Repo.Repository) + ctx.Repo.GitRepo, err = gitrepo.RepositoryFromRequestContextOrOpen(ctx, ctx.Repo.Repository) if err != nil { ctx.Error(http.StatusInternalServerError, "OpenRepository", err) return diff --git a/routers/api/v1/repo/file.go b/routers/api/v1/repo/file.go index 8a4f78a3d7..1ad55d225b 100644 --- a/routers/api/v1/repo/file.go +++ b/routers/api/v1/repo/file.go @@ -282,7 +282,7 @@ func GetArchive(ctx *context.APIContext) { if ctx.Repo.GitRepo == nil { var err error - ctx.Repo.GitRepo, err = gitrepo.RepositoryFromRequestContextOrOpen(ctx, ctx, ctx.Repo.Repository) + ctx.Repo.GitRepo, err = gitrepo.RepositoryFromRequestContextOrOpen(ctx, ctx.Repo.Repository) if err != nil { ctx.Error(http.StatusInternalServerError, "OpenRepository", err) return diff --git a/routers/api/v1/repo/repo.go b/routers/api/v1/repo/repo.go index a192e241b7..ce09e7fc0f 100644 --- a/routers/api/v1/repo/repo.go +++ b/routers/api/v1/repo/repo.go @@ -726,7 +726,7 @@ func updateBasicProperties(ctx *context.APIContext, opts api.EditRepoOption) err if ctx.Repo.GitRepo == nil && !repo.IsEmpty { var err error - ctx.Repo.GitRepo, err = gitrepo.RepositoryFromRequestContextOrOpen(ctx, ctx, repo) + ctx.Repo.GitRepo, err = gitrepo.RepositoryFromRequestContextOrOpen(ctx, repo) if err != nil { ctx.Error(http.StatusInternalServerError, "Unable to OpenRepository", err) return err diff --git a/routers/private/internal_repo.go b/routers/private/internal_repo.go index 8a53e1ed23..e111d6689e 100644 --- a/routers/private/internal_repo.go +++ b/routers/private/internal_repo.go @@ -27,7 +27,7 @@ func RepoAssignment(ctx *gitea_context.PrivateContext) { return } - gitRepo, err := gitrepo.RepositoryFromRequestContextOrOpen(ctx, ctx, repo) + gitRepo, err := gitrepo.RepositoryFromRequestContextOrOpen(ctx, repo) if err != nil { log.Error("Failed to open repository: %s/%s Error: %v", ownerName, repoName, err) ctx.JSON(http.StatusInternalServerError, private.Response{ diff --git a/routers/web/org/home.go b/routers/web/org/home.go index deeb18ae7c..277adb60ca 100644 --- a/routers/web/org/home.go +++ b/routers/web/org/home.go @@ -12,6 +12,7 @@ import ( "code.gitea.io/gitea/models/organization" "code.gitea.io/gitea/models/renderhelper" repo_model "code.gitea.io/gitea/models/repo" + "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/markup/markdown" "code.gitea.io/gitea/modules/setting" @@ -21,9 +22,7 @@ import ( "code.gitea.io/gitea/services/context" ) -const ( - tplOrgHome templates.TplName = "org/home" -) +const tplOrgHome templates.TplName = "org/home" // Home show organization home page func Home(ctx *context.Context) { @@ -110,15 +109,19 @@ func home(ctx *context.Context, viewRepositories bool) { ctx.Data["DisableNewPullMirrors"] = setting.Mirror.DisableNewPull ctx.Data["ShowMemberAndTeamTab"] = ctx.Org.IsMember || len(members) > 0 - if !prepareOrgProfileReadme(ctx, viewRepositories) { - ctx.Data["PageIsViewRepositories"] = true + prepareResult, err := shared_user.PrepareOrgHeader(ctx) + if err != nil { + ctx.ServerError("PrepareOrgHeader", err) + return } - var ( - repos []*repo_model.Repository - count int64 - ) - repos, count, err = repo_model.SearchRepository(ctx, &repo_model.SearchRepoOptions{ + // if no profile readme, it still means "view repositories" + isViewOverview := !viewRepositories && prepareOrgProfileReadme(ctx, prepareResult) + ctx.Data["PageIsViewRepositories"] = !isViewOverview + ctx.Data["PageIsViewOverview"] = isViewOverview + ctx.Data["ShowOrgProfileReadmeSelector"] = isViewOverview && prepareResult.ProfilePublicReadmeBlob != nil && prepareResult.ProfilePrivateReadmeBlob != nil + + repos, count, err := repo_model.SearchRepository(ctx, &repo_model.SearchRepoOptions{ ListOptions: db.ListOptions{ PageSize: setting.UI.User.RepoPagingNum, Page: page, @@ -151,28 +154,45 @@ func home(ctx *context.Context, viewRepositories bool) { ctx.HTML(http.StatusOK, tplOrgHome) } -func prepareOrgProfileReadme(ctx *context.Context, viewRepositories bool) bool { - profileDbRepo, profileGitRepo, profileReadme, profileClose := shared_user.FindUserProfileReadme(ctx, ctx.Doer) - defer profileClose() - ctx.Data["HasProfileReadme"] = profileReadme != nil - - if profileGitRepo == nil || profileReadme == nil || viewRepositories { - return false - } +func prepareOrgProfileReadme(ctx *context.Context, prepareResult *shared_user.PrepareOrgHeaderResult) bool { + viewAs := ctx.FormString("view_as", util.Iif(ctx.Org.IsMember, "member", "public")) + viewAsMember := viewAs == "member" - if bytes, err := profileReadme.GetBlobContent(setting.UI.MaxDisplayFileSize); err != nil { - log.Error("failed to GetBlobContent: %v", err) + var profileRepo *repo_model.Repository + var readmeBlob *git.Blob + if viewAsMember { + if prepareResult.ProfilePrivateReadmeBlob != nil { + profileRepo, readmeBlob = prepareResult.ProfilePrivateRepo, prepareResult.ProfilePrivateReadmeBlob + } else { + profileRepo, readmeBlob = prepareResult.ProfilePublicRepo, prepareResult.ProfilePublicReadmeBlob + viewAsMember = false + } } else { - rctx := renderhelper.NewRenderContextRepoFile(ctx, profileDbRepo, renderhelper.RepoFileOptions{ - CurrentRefPath: path.Join("branch", util.PathEscapeSegments(profileDbRepo.DefaultBranch)), - }) - if profileContent, err := markdown.RenderString(rctx, bytes); err != nil { - log.Error("failed to RenderString: %v", err) + if prepareResult.ProfilePublicReadmeBlob != nil { + profileRepo, readmeBlob = prepareResult.ProfilePublicRepo, prepareResult.ProfilePublicReadmeBlob } else { - ctx.Data["ProfileReadme"] = profileContent + profileRepo, readmeBlob = prepareResult.ProfilePrivateRepo, prepareResult.ProfilePrivateReadmeBlob + viewAsMember = true } } + if readmeBlob == nil { + return false + } + + readmeBytes, err := readmeBlob.GetBlobContent(setting.UI.MaxDisplayFileSize) + if err != nil { + log.Error("failed to GetBlobContent for profile %q (view as %q) readme: %v", profileRepo.FullName(), viewAs, err) + return false + } - ctx.Data["PageIsViewOverview"] = true + rctx := renderhelper.NewRenderContextRepoFile(ctx, profileRepo, renderhelper.RepoFileOptions{ + CurrentRefPath: path.Join("branch", util.PathEscapeSegments(profileRepo.DefaultBranch)), + }) + ctx.Data["ProfileReadmeContent"], err = markdown.RenderString(rctx, readmeBytes) + if err != nil { + log.Error("failed to GetBlobContent for profile %q (view as %q) readme: %v", profileRepo.FullName(), viewAs, err) + return false + } + ctx.Data["IsViewingOrgAsMember"] = viewAsMember return true } diff --git a/routers/web/org/members.go b/routers/web/org/members.go index 5a134caecb..1665a12302 100644 --- a/routers/web/org/members.go +++ b/routers/web/org/members.go @@ -54,9 +54,9 @@ func Members(ctx *context.Context) { return } - err = shared_user.RenderOrgHeader(ctx) + _, err = shared_user.PrepareOrgHeader(ctx) if err != nil { - ctx.ServerError("RenderOrgHeader", err) + ctx.ServerError("PrepareOrgHeader", err) return } diff --git a/routers/web/org/teams.go b/routers/web/org/teams.go index 0137f2cc96..26031029d6 100644 --- a/routers/web/org/teams.go +++ b/routers/web/org/teams.go @@ -58,9 +58,9 @@ func Teams(ctx *context.Context) { } ctx.Data["Teams"] = ctx.Org.Teams - err := shared_user.RenderOrgHeader(ctx) + _, err := shared_user.PrepareOrgHeader(ctx) if err != nil { - ctx.ServerError("RenderOrgHeader", err) + ctx.ServerError("PrepareOrgHeader", err) return } diff --git a/routers/web/shared/user/header.go b/routers/web/shared/user/header.go index d388d2b5d9..62b146c7f3 100644 --- a/routers/web/shared/user/header.go +++ b/routers/web/shared/user/header.go @@ -20,6 +20,7 @@ import ( "code.gitea.io/gitea/modules/markup/markdown" "code.gitea.io/gitea/modules/optional" "code.gitea.io/gitea/modules/setting" + "code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/services/context" ) @@ -102,37 +103,46 @@ func PrepareContextForProfileBigAvatar(ctx *context.Context) { } } -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.GetBlobByPath("README.md") - } - } +func FindOwnerProfileReadme(ctx *context.Context, doer *user_model.User, optProfileRepoName ...string) (profileDbRepo *repo_model.Repository, profileReadmeBlob *git.Blob) { + profileRepoName := util.OptionalArg(optProfileRepoName, RepoNameProfile) + profileDbRepo, err := repo_model.GetRepositoryByName(ctx, ctx.ContextUser.ID, profileRepoName) + if err != nil { + if !repo_model.IsErrRepoNotExist(err) { + log.Error("FindOwnerProfileReadme failed to GetRepositoryByName: %v", err) } - } else if !repo_model.IsErrRepoNotExist(err) { - log.Error("FindUserProfileReadme failed to GetRepositoryByName: %v", err) + return nil, nil } - return profileDbRepo, profileGitRepo, profileReadmeBlob, func() { - if profileGitRepo != nil { - _ = profileGitRepo.Close() - } + + perm, err := access_model.GetUserRepoPermission(ctx, profileDbRepo, doer) + if err != nil { + log.Error("FindOwnerProfileReadme failed to GetRepositoryByName: %v", err) + return nil, nil + } + if profileDbRepo.IsEmpty || !perm.CanRead(unit.TypeCode) { + return nil, nil } + + profileGitRepo, err := gitrepo.RepositoryFromRequestContextOrOpen(ctx, profileDbRepo) + if err != nil { + log.Error("FindOwnerProfileReadme failed to OpenRepository: %v", err) + return nil, nil + } + + commit, err := profileGitRepo.GetBranchCommit(profileDbRepo.DefaultBranch) + if err != nil { + log.Error("FindOwnerProfileReadme failed to GetBranchCommit: %v", err) + return nil, nil + } + + profileReadmeBlob, _ = commit.GetBlobByPath("README.md") // no need to handle this error + return profileDbRepo, profileReadmeBlob } func RenderUserHeader(ctx *context.Context) { prepareContextForCommonProfile(ctx) - _, _, profileReadmeBlob, profileClose := FindUserProfileReadme(ctx, ctx.Doer) - defer profileClose() - ctx.Data["HasProfileReadme"] = profileReadmeBlob != nil + _, profileReadmeBlob := FindOwnerProfileReadme(ctx, ctx.Doer) + ctx.Data["HasUserProfileReadme"] = profileReadmeBlob != nil } func LoadHeaderCount(ctx *context.Context) error { @@ -169,14 +179,28 @@ func LoadHeaderCount(ctx *context.Context) error { return nil } -func RenderOrgHeader(ctx *context.Context) error { - if err := LoadHeaderCount(ctx); err != nil { - return err - } +const ( + RepoNameProfilePrivate = ".profile-private" + RepoNameProfile = ".profile" +) - _, _, profileReadmeBlob, profileClose := FindUserProfileReadme(ctx, ctx.Doer) - defer profileClose() - ctx.Data["HasProfileReadme"] = profileReadmeBlob != nil +type PrepareOrgHeaderResult struct { + ProfilePublicRepo *repo_model.Repository + ProfilePublicReadmeBlob *git.Blob + ProfilePrivateRepo *repo_model.Repository + ProfilePrivateReadmeBlob *git.Blob + HasOrgProfileReadme bool +} - return nil +func PrepareOrgHeader(ctx *context.Context) (result *PrepareOrgHeaderResult, err error) { + if err = LoadHeaderCount(ctx); err != nil { + return nil, err + } + + result = &PrepareOrgHeaderResult{} + result.ProfilePublicRepo, result.ProfilePublicReadmeBlob = FindOwnerProfileReadme(ctx, ctx.Doer) + result.ProfilePrivateRepo, result.ProfilePrivateReadmeBlob = FindOwnerProfileReadme(ctx, ctx.Doer, RepoNameProfilePrivate) + result.HasOrgProfileReadme = result.ProfilePublicReadmeBlob != nil || result.ProfilePrivateReadmeBlob != nil + ctx.Data["HasOrgProfileReadme"] = result.HasOrgProfileReadme // many pages need it to show the "overview" tab + return result, nil } diff --git a/routers/web/user/profile.go b/routers/web/user/profile.go index 9c014bffdb..006ffdcf7e 100644 --- a/routers/web/user/profile.go +++ b/routers/web/user/profile.go @@ -74,8 +74,7 @@ func userProfile(ctx *context.Context) { ctx.Data["HeatmapTotalContributions"] = activities_model.GetTotalContributionsInHeatmap(data) } - profileDbRepo, _ /*profileGitRepo*/, profileReadmeBlob, profileClose := shared_user.FindUserProfileReadme(ctx, ctx.Doer) - defer profileClose() + profileDbRepo, profileReadmeBlob := shared_user.FindOwnerProfileReadme(ctx, ctx.Doer) showPrivate := ctx.IsSigned && (ctx.Doer.IsAdmin || ctx.Doer.ID == ctx.ContextUser.ID) prepareUserProfileTabData(ctx, showPrivate, profileDbRepo, profileReadmeBlob) @@ -96,7 +95,7 @@ func prepareUserProfileTabData(ctx *context.Context, showPrivate bool, profileDb } } ctx.Data["TabName"] = tab - ctx.Data["HasProfileReadme"] = profileReadme != nil + ctx.Data["HasUserProfileReadme"] = profileReadme != nil page := ctx.FormInt("page") if page <= 0 { @@ -254,7 +253,7 @@ func prepareUserProfileTabData(ctx *context.Context, showPrivate bool, profileDb if profileContent, err := markdown.RenderString(rctx, bytes); err != nil { log.Error("failed to RenderString: %v", err) } else { - ctx.Data["ProfileReadme"] = profileContent + ctx.Data["ProfileReadmeContent"] = profileContent } } case "organizations": |