diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go index e27c4ca272..5415b2a312 100644 --- a/routers/api/v1/api.go +++ b/routers/api/v1/api.go @@ -69,14 +69,12 @@ import ( "strconv" "strings" - actions_model "code.gitea.io/gitea/models/actions" auth_model "code.gitea.io/gitea/models/auth" - "code.gitea.io/gitea/models/db" + group_model "code.gitea.io/gitea/models/group" "code.gitea.io/gitea/models/organization" "code.gitea.io/gitea/models/perm" access_model "code.gitea.io/gitea/models/perm/access" repo_model "code.gitea.io/gitea/models/repo" - group_model "code.gitea.io/gitea/models/group" shared_group_model "code.gitea.io/gitea/models/shared/group" "code.gitea.io/gitea/models/unit" user_model "code.gitea.io/gitea/models/user" @@ -1163,11 +1161,13 @@ func Routes() *web.Router { // (repo scope) m.Group("/starred", func() { m.Get("", user.GetMyStarredRepos) - m.Group("/{username}/{group_id}?/{reponame}", func() { + fn := func() { m.Get("", user.IsStarring) m.Put("", user.Star) m.Delete("", user.Unstar) - }, repoAssignment(), checkTokenPublicOnly()) + } + m.Group("/{username}/{reponame}", fn, repoAssignment(), checkTokenPublicOnly()) + m.Group("/{username}/{group_id}/{reponame}", fn, repoAssignment(), checkTokenPublicOnly()) }, reqStarsEnabled(), tokenRequiresScopes(auth_model.AccessTokenScopeCategoryRepository)) m.Get("/times", repo.ListMyTrackedTimes) m.Get("/stopwatches", repo.GetStopwatches) @@ -1214,8 +1214,7 @@ func Routes() *web.Router { // (repo scope) m.Post("/migrate", reqToken(), bind(api.MigrateRepoOptions{}), repo.Migrate) - - m.Group("/{username}/{group_id}?/{reponame}", func() { + fn := func() { m.Get("/compare/*", reqRepoReader(unit.TypeCode), repo.CompareDiff) m.Combo("").Get(reqAnyRepoReader(), repo.Get). @@ -1508,27 +1507,31 @@ func Routes() *web.Router { }, reqAdmin(), reqToken()) m.Methods("HEAD,GET", "/{ball_type:tarball|zipball|bundle}/*", reqRepoReader(unit.TypeCode), context.ReferencesGitRepo(true), repo.DownloadArchive) - }, repoAssignment(), checkTokenPublicOnly()) + } + m.Group("/{username}/{reponame}", fn, repoAssignment(), checkTokenPublicOnly()) + m.Group("/{username}/{group_id}/{reponame}", fn, repoAssignment(), checkTokenPublicOnly()) }, tokenRequiresScopes(auth_model.AccessTokenScopeCategoryRepository)) // Artifacts direct download endpoint authenticates via signed url // it is protected by the "sig" parameter (to help to access private repo), so no need to use other middlewares - m.Get("/repos/{username}/{group_id}?/{reponame}/actions/artifacts/{artifact_id}/zip/raw", repo.DownloadArtifactRaw) + m.Get("/repos/{username}/{reponame}/actions/artifacts/{artifact_id}/zip/raw", repo.DownloadArtifactRaw) + m.Get("/repos/{username}/{group_id}/{reponame}/actions/artifacts/{artifact_id}/zip/raw", repo.DownloadArtifactRaw) // Notifications (requires notifications scope) m.Group("/repos", func() { - m.Group("/{username}/{group_id}?/{reponame}", func() { + fn := func() { m.Combo("/notifications", reqToken()). Get(notify.ListRepoNotifications). Put(notify.ReadRepoNotifications) - }, repoAssignment(), checkTokenPublicOnly()) + } + m.Group("/{username}/{reponame}", fn, repoAssignment(), checkTokenPublicOnly()) + m.Group("/{username}/{group_id}/{reponame}", fn, repoAssignment(), checkTokenPublicOnly()) }, tokenRequiresScopes(auth_model.AccessTokenScopeCategoryNotification)) // Issue (requires issue scope) m.Group("/repos", func() { m.Get("/issues/search", repo.SearchIssues) - - m.Group("/{username}/{group_id}?/{reponame}", func() { + fn := func() { m.Group("/issues", func() { m.Combo("").Get(repo.ListIssues). Post(reqToken(), mustNotBeArchived, bind(api.CreateIssueOption{}), reqRepoReader(unit.TypeIssues), repo.CreateIssue) @@ -1640,7 +1643,9 @@ func Routes() *web.Router { Patch(reqToken(), reqRepoWriter(unit.TypeIssues, unit.TypePullRequests), bind(api.EditMilestoneOption{}), repo.EditMilestone). Delete(reqToken(), reqRepoWriter(unit.TypeIssues, unit.TypePullRequests), repo.DeleteMilestone) }) - }, repoAssignment(), checkTokenPublicOnly()) + } + m.Group("/{username}/{reponame}", fn, repoAssignment(), checkTokenPublicOnly()) + m.Group("/{username}/{group_id}/{reponame}", fn, repoAssignment(), checkTokenPublicOnly()) }, tokenRequiresScopes(auth_model.AccessTokenScopeCategoryIssue)) // NOTE: these are Gitea package management API - see packages.CommonRoutes and packages.DockerContainerRoutes for endpoints that implement package manager APIs diff --git a/routers/common/lfs.go b/routers/common/lfs.go index 1d2b71394b..b2438a54e0 100644 --- a/routers/common/lfs.go +++ b/routers/common/lfs.go @@ -14,7 +14,7 @@ const RouterMockPointCommonLFS = "common-lfs" func AddOwnerRepoGitLFSRoutes(m *web.Router, middlewares ...any) { // shared by web and internal routers - m.Group("/{username}/{reponame}/info/lfs", func() { + fn := func() { m.Post("/objects/batch", lfs.CheckAcceptMediaType, lfs.BatchHandler) m.Put("/objects/{oid}/{size}", lfs.UploadHandler) m.Get("/objects/{oid}/{filename}", lfs.DownloadHandler) @@ -27,5 +27,7 @@ func AddOwnerRepoGitLFSRoutes(m *web.Router, middlewares ...any) { m.Post("/{lid}/unlock", lfs.UnLockHandler) }, lfs.CheckAcceptMediaType) m.Any("/*", http.NotFound) - }, append([]any{web.RouterMockPoint(RouterMockPointCommonLFS)}, middlewares...)...) + } + m.Group("/{username}/{reponame}/info/lfs", fn, append([]any{web.RouterMockPoint(RouterMockPointCommonLFS)}, middlewares...)...) + m.Group("/{username}/{group_id}/{reponame}/info/lfs", fn, append([]any{web.RouterMockPoint(RouterMockPointCommonLFS)}, middlewares...)...) } diff --git a/routers/web/githttp.go b/routers/web/githttp.go index 24af5e534d..841c42d9c2 100644 --- a/routers/web/githttp.go +++ b/routers/web/githttp.go @@ -9,7 +9,7 @@ import ( ) func addOwnerRepoGitHTTPRouters(m *web.Router, middlewares ...any) { - m.Group("/{username}/{group_id}?/{reponame}", func() { + fn := func() { m.Methods("POST,OPTIONS", "/git-upload-pack", repo.ServiceUploadPack) m.Methods("POST,OPTIONS", "/git-receive-pack", repo.ServiceReceivePack) m.Methods("POST,OPTIONS", "/git-upload-archive", repo.ServiceUploadArchive) @@ -22,5 +22,7 @@ func addOwnerRepoGitHTTPRouters(m *web.Router, middlewares ...any) { m.Methods("GET,OPTIONS", "/objects/{head:[0-9a-f]{2}}/{hash:[0-9a-f]{38,62}}", repo.GetLooseObject) m.Methods("GET,OPTIONS", "/objects/pack/pack-{file:[0-9a-f]{40,64}}.pack", repo.GetPackFile) m.Methods("GET,OPTIONS", "/objects/pack/pack-{file:[0-9a-f]{40,64}}.idx", repo.GetIdxFile) - }, middlewares...) + } + m.Group("/{username}/{reponame}", fn, middlewares...) + m.Group("/{username}/{group_id}/{reponame}", fn, middlewares...) } diff --git a/routers/web/web.go b/routers/web/web.go index 49abcd2fe4..6656980766 100644 --- a/routers/web/web.go +++ b/routers/web/web.go @@ -8,7 +8,6 @@ import ( "strings" auth_model "code.gitea.io/gitea/models/auth" - "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/perm" "code.gitea.io/gitea/models/unit" "code.gitea.io/gitea/modules/git" @@ -1128,19 +1127,23 @@ func registerWebRoutes(m *web.Router, webAuth *AuthMiddleware) { }, optSignIn, context.UserAssignmentWeb(), context.OrgAssignment(context.OrgAssignmentOptions{})) // end "/{username}/-": packages, projects, code - m.Group("/{username}/{reponame}/-", func() { + repoDashFn := func() { m.Group("/migrate", func() { m.Get("/status", repo.MigrateStatus) }) - }, optSignIn, context.RepoAssignment, reqUnitCodeReader) - // end "/{username}/{reponame}/-": migrate + } + m.Group("/{username}/{reponame}/-", repoDashFn, optSignIn, context.RepoAssignment, reqUnitCodeReader) + m.Group("/{username}/{group_id}/{reponame}/-", repoDashFn, optSignIn, context.RepoAssignment, reqUnitCodeReader) + // end "/{username}/{group_id}/{reponame}/-": migrate - m.Group("/{username}/{reponame}/-", func() { + mentionsFn := func() { m.Get("/mentions-in-repo", repo.GetMentionsInRepo) - }, optSignIn, context.RepoAssignment, reqUnitsWithMentions) + } + m.Group("/{username}/{reponame}/-", mentionsFn, optSignIn, context.RepoAssignment, reqUnitsWithMentions) + m.Group("/{username}/{group_id}/{reponame}/-", mentionsFn, optSignIn, context.RepoAssignment, reqUnitsWithMentions) // end "/{username}/{reponame}/-": mentions - m.Group("/{username}/{reponame}/settings", func() { + settingsFn := func() { m.Group("", func() { m.Combo("").Get(repo_setting.Settings). Post(web.Bind(forms.RepoSettingForm{}), repo_setting.SettingsPost) @@ -1239,7 +1242,12 @@ func registerWebRoutes(m *web.Router, webAuth *AuthMiddleware) { m.Post("/retry", repo.MigrateRetryPost) m.Post("/cancel", repo.MigrateCancelPost) }) - }, + } + m.Group("/{username}/{reponame}/settings", settingsFn, + reqSignIn, context.RepoAssignment, reqRepoAdmin, + ctxDataSet("PageIsRepoSettings", true, "LFSStartServer", setting.LFS.StartServer), + ) + m.Group("/{username}/{group_id}/{reponame}/settings", settingsFn, reqSignIn, context.RepoAssignment, reqRepoAdmin, ctxDataSet("PageIsRepoSettings", true, "LFSStartServer", setting.LFS.StartServer), ) @@ -1249,8 +1257,9 @@ func registerWebRoutes(m *web.Router, webAuth *AuthMiddleware) { m.Get("/{username}/{reponame}", optSignIn, webAuth.AllowBasic, context.RepoAssignment, context.RepoRefByType(git.RefTypeBranch), repo.SetEditorconfigIfExists, repo.Home) m.Post("/{username}/{reponame}/markup", optSignIn, context.RepoAssignment, reqUnitsWithMarkdown, web.Bind(structs.MarkupOption{}), misc.Markup) + m.Post("/{username}/{group_id}/{reponame}/markup", optSignIn, context.RepoAssignment, reqUnitsWithMarkdown, web.Bind(structs.MarkupOption{}), misc.Markup) - m.Group("/{username}/{reponame}", func() { + rootRepoFn := func() { m.Group("/tree-list", func() { m.Get("/branch/*", context.RepoRefByType(git.RefTypeBranch), repo.TreeList) m.Get("/tag/*", context.RepoRefByType(git.RefTypeTag), repo.TreeList) @@ -1266,11 +1275,13 @@ func registerWebRoutes(m *web.Router, webAuth *AuthMiddleware) { Get(repo.SetDiffViewStyle, repo.SetWhitespaceBehavior, repo.CompareDiff). Post(reqSignIn, context.RepoMustNotBeArchived(), reqUnitPullsReader, repo.MustAllowPulls, web.Bind(forms.CreateIssueForm{}), repo.SetWhitespaceBehavior, repo.CompareAndPullRequestPost) m.Get("/pulls/new/*", repo.PullsNewRedirect) - }, optSignIn, context.RepoAssignment, reqUnitCodeReader) - // end "/{username}/{reponame}": repo code: find, compare, list + } + m.Group("/{username}/{reponame}", rootRepoFn, optSignIn, context.RepoAssignment, reqUnitCodeReader) + m.Group("/{username}/{group_id}{reponame}", rootRepoFn, optSignIn, context.RepoAssignment, reqUnitCodeReader) + // end "/{username}/{group_id}/{reponame}": repo code: find, compare, list addIssuesPullsViewRoutes := func() { - // for /{username}/{reponame}/issues" or "/{username}/{reponame}/pulls" + // for /{username}/{group_id}/{reponame}/issues" or "/{username}/{group_id}/{reponame}/pulls" m.Get("/posters", repo.IssuePullPosters) m.Group("/{index}", func() { m.Get("/info", repo.GetIssueInfo) @@ -1285,25 +1296,31 @@ func registerWebRoutes(m *web.Router, webAuth *AuthMiddleware) { } // FIXME: many "pulls" requests are sent to "issues" endpoints correctly, so the issue endpoints have to tolerate pull request permissions at the moment m.Group("/{username}/{reponame}/{type:issues}", addIssuesPullsViewRoutes, optSignIn, context.RepoAssignment, context.RequireUnitReader(unit.TypeIssues, unit.TypePullRequests)) - m.Group("/{username}/{reponame}/{type:pulls}", addIssuesPullsViewRoutes, optSignIn, context.RepoAssignment, reqUnitPullsReader) + m.Group("/{username}/{group_id}/reponame}/{type:issues}", addIssuesPullsViewRoutes, optSignIn, context.RepoAssignment, context.RequireUnitReader(unit.TypeIssues, unit.TypePullRequests)) + m.Group("/{username}/reponame}/{type:pulls}", addIssuesPullsViewRoutes, optSignIn, context.RepoAssignment, reqUnitPullsReader) + m.Group("/{username}/{group_id}/reponame}/{type:pulls}", addIssuesPullsViewRoutes, optSignIn, context.RepoAssignment, reqUnitPullsReader) - m.Group("/{username}/{reponame}", func() { + repoIssueAttachmentFn := func() { m.Get("/comments/{id}/attachments", repo.GetCommentAttachments) m.Get("/labels", repo.RetrieveLabelsForList, repo.Labels) m.Get("/milestones", repo.Milestones) m.Get("/milestone/{id}", repo.MilestoneIssuesAndPulls) m.Get("/issues/suggestions", repo.IssueSuggestions) - }, optSignIn, context.RepoAssignment, reqRepoIssuesOrPullsReader) // issue/pull attachments, labels, milestones - // end "/{username}/{reponame}": view milestone, label, issue, pull, etc + } - m.Group("/{username}/{reponame}/{type:issues}", func() { - // these handlers also check unit permissions internally + m.Group("/{username}/{reponame}", repoIssueAttachmentFn, optSignIn, context.RepoAssignment, reqRepoIssuesOrPullsReader) // issue/pull attachments, labels, milestones + m.Group("/{username}/{group_id}/{reponame}", repoIssueAttachmentFn, optSignIn, context.RepoAssignment, reqRepoIssuesOrPullsReader) // issue/pull attachments, labels, milestones + // end "/{username}/{group_id}/{reponame}": view milestone, label, issue, pull, etc + + issueViewFn := func() { m.Get("", repo.Issues) - m.Get("/{index}", repo.ViewIssue) // also do pull-request redirection (".../issues/{PR-number}" -> ".../pulls/{PR-number}") - }, optSignIn, context.RepoAssignment, context.RequireUnitReader(unit.TypeIssues, unit.TypePullRequests, unit.TypeExternalTracker)) - // end "/{username}/{reponame}": issue list, issue view (pull-request redirection), external tracker + m.Get("/{index}", repo.ViewIssue) + } + m.Group("/{username}/{reponame}/{type:issues}", issueViewFn, optSignIn, context.RepoAssignment, context.RequireUnitReader(unit.TypeIssues, unit.TypeExternalTracker)) + m.Group("/{username}/{group_id}/{reponame}/{type:issues}", issueViewFn, optSignIn, context.RepoAssignment, context.RequireUnitReader(unit.TypeIssues, unit.TypeExternalTracker)) + // end "/{username}/{group_id}/{reponame}": issue/pull list, issue/pull view, external tracker - m.Group("/{username}/{reponame}", func() { // edit issues, pulls, labels, milestones, etc + editIssueFn := func() { // edit issues, pulls, labels, milestones, etc m.Group("/issues", func() { m.Group("/new", func() { m.Combo("").Get(repo.NewIssue). @@ -1314,7 +1331,7 @@ func registerWebRoutes(m *web.Router, webAuth *AuthMiddleware) { }, reqUnitIssuesReader) addIssuesPullsUpdateRoutes := func() { - // for "/{username}/{reponame}/issues" or "/{username}/{reponame}/pulls" + // for "/{username}/{group_id}/{reponame}/issues" or "/{username}/{group_id}/{reponame}/pulls" m.Group("/{index}", func() { m.Post("/title", repo.UpdateIssueTitle) m.Post("/content", repo.UpdateIssueContent) @@ -1390,10 +1407,12 @@ func registerWebRoutes(m *web.Router, webAuth *AuthMiddleware) { m.Post("/resolve_conversation", repo.SetShowOutdatedComments, repo.UpdateResolveConversation) }, reqUnitPullsReader) m.Post("/pull/{index}/target_branch", reqUnitPullsReader, repo.UpdatePullRequestTarget) - }, reqSignIn, context.RepoAssignment, context.RepoMustNotBeArchived()) - // end "/{username}/{reponame}": create or edit issues, pulls, labels, milestones + } + m.Group("/{username}/{reponame}", editIssueFn, reqSignIn, context.RepoAssignment, context.RepoMustNotBeArchived()) + m.Group("/{username}/{group_id}/{reponame}", editIssueFn, reqSignIn, context.RepoAssignment, context.RepoMustNotBeArchived()) + // end "/{username}/{group_id}/{reponame}": create or edit issues, pulls, labels, milestones - m.Group("/{username}/{reponame}", func() { // repo code (at least "code reader") + codeFn := func() { // repo code (at least "code reader") m.Group("", func() { m.Group("", func() { // "GET" requests only need "code reader" permission, "POST" requests need "code writer" permission. @@ -1441,10 +1460,12 @@ func registerWebRoutes(m *web.Router, webAuth *AuthMiddleware) { }, context.RepoMustNotBeArchived(), reqRepoCodeWriter, repo.MustBeNotEmpty) m.Combo("/fork").Get(repo.Fork).Post(web.Bind(forms.CreateRepoForm{}), repo.ForkPost) - }, reqSignIn, context.RepoAssignment, reqUnitCodeReader) - // end "/{username}/{reponame}": repo code + } + m.Group("/{username}/{reponame}", codeFn, reqSignIn, context.RepoAssignment, reqUnitCodeReader) + m.Group("/{username}/{group_id}/{reponame}", codeFn, reqSignIn, context.RepoAssignment, reqUnitCodeReader) + // end "/{username}/{group_id}/{reponame}": repo code - m.Group("/{username}/{reponame}", func() { // repo tags + repoTagFn := func() { // repo tags m.Group("/tags", func() { m.Get("", context.RepoRefByDefaultBranch() /* for the "commits" tab */, repo.TagsList) m.Get(".rss", webAuth.AllowBasic, feedEnabled, repo.TagsListFeedRSS) @@ -1452,10 +1473,12 @@ func registerWebRoutes(m *web.Router, webAuth *AuthMiddleware) { m.Get("/list", repo.GetTagList) }, ctxDataSet("EnableFeed", setting.Other.EnableFeed)) m.Post("/tags/delete", reqSignIn, reqRepoCodeWriter, context.RepoMustNotBeArchived(), repo.DeleteTag) - }, optSignIn, context.RepoAssignment, repo.MustBeNotEmpty, reqUnitCodeReader) - // end "/{username}/{reponame}": repo tags + } + m.Group("/{username}/{reponame}", repoTagFn, optSignIn, context.RepoAssignment, repo.MustBeNotEmpty, reqUnitCodeReader) + m.Group("/{username}/{group_id}/{reponame}", repoTagFn, optSignIn, context.RepoAssignment, repo.MustBeNotEmpty, reqUnitCodeReader) + // end "/{username}/{group_id}/{reponame}": repo tags - m.Group("/{username}/{reponame}", func() { // repo releases + repoReleaseFn := func() { // repo releases m.Group("/releases", func() { m.Get("", repo.Releases) m.Get(".rss", webAuth.AllowBasic, feedEnabled, repo.ReleasesFeedRSS) @@ -1477,25 +1500,33 @@ func registerWebRoutes(m *web.Router, webAuth *AuthMiddleware) { m.Get("/edit/*", repo.EditRelease) m.Post("/edit/*", web.Bind(forms.EditReleaseForm{}), repo.EditReleasePost) }, reqSignIn, context.RepoMustNotBeArchived(), reqRepoReleaseWriter, repo.CommitInfoCache) - }, optSignIn, context.RepoAssignment, repo.MustBeNotEmpty, reqRepoReleaseReader) - // end "/{username}/{reponame}": repo releases + } + m.Group("/{username}/{reponame}", repoReleaseFn, optSignIn, context.RepoAssignment, repo.MustBeNotEmpty, reqRepoReleaseReader) + m.Group("/{username}/{group_id}/{reponame}", repoReleaseFn, optSignIn, context.RepoAssignment, repo.MustBeNotEmpty, reqRepoReleaseReader) + // end "/{username}/{group_id}/{reponame}": repo releases - m.Group("/{username}/{reponame}", func() { // to maintain compatibility with old attachments + repoAttachmentsFn := func() { // to maintain compatibility with old attachments m.Get("/attachments/{uuid}", webAuth.AllowBasic, webAuth.AllowOAuth2, repo.GetAttachment) - }, optSignIn, context.RepoAssignment) - // end "/{username}/{reponame}": compatibility with old attachments + } + m.Group("/{username}/{reponame}", repoAttachmentsFn, optSignIn, context.RepoAssignment) + m.Group("/{username}/{group_id}/{reponame}", repoAttachmentsFn, optSignIn, context.RepoAssignment) + // end "/{username}/{group_id}/{reponame}": compatibility with old attachments - m.Group("/{username}/{reponame}", func() { + repoTopicFn := func() { m.Post("/topics", repo.TopicsPost) - }, context.RepoAssignment, reqRepoAdmin, context.RepoMustNotBeArchived()) + } + m.Group("/{username}/{reponame}", repoTopicFn, context.RepoAssignment, reqRepoAdmin, context.RepoMustNotBeArchived()) + m.Group("/{username}/{group_id}/{reponame}", repoTopicFn, context.RepoAssignment, reqRepoAdmin, context.RepoMustNotBeArchived()) - m.Group("/{username}/{reponame}", func() { + repoPackageFn := func() { if setting.Packages.Enabled { m.Get("/packages", repo.Packages) } - }, optSignIn, context.RepoAssignment) + } + m.Group("/{username}/{reponame}", repoPackageFn, optSignIn, context.RepoAssignment) + m.Group("/{username}/{group_id}/{reponame}", repoPackageFn, optSignIn, context.RepoAssignment) - m.Group("/{username}/{reponame}/projects", func() { + repoProjectsFn := func() { m.Get("", repo.Projects) m.Get("/{id}", repo.ViewProject) m.Group("", func() { //nolint:dupl // duplicates lines 1034-1054 @@ -1519,10 +1550,12 @@ func registerWebRoutes(m *web.Router, webAuth *AuthMiddleware) { }) }) }, reqRepoProjectsWriter, context.RepoMustNotBeArchived()) - }, optSignIn, context.RepoAssignment, reqRepoProjectsReader, repo.MustEnableRepoProjects) - // end "/{username}/{reponame}/projects" + } + m.Group("/{username}/{reponame}/projects", repoProjectsFn, optSignIn, context.RepoAssignment, reqRepoProjectsReader, repo.MustEnableRepoProjects) + m.Group("/{username}/{group_id}/{reponame}/projects", repoProjectsFn, optSignIn, context.RepoAssignment, reqRepoProjectsReader, repo.MustEnableRepoProjects) + // end "/{username}/{group_id}/{reponame}/projects" - m.Group("/{username}/{reponame}/actions", func() { + repoActionsFn := func() { m.Get("", actions.List) m.Post("/disable", reqRepoAdmin, actions.DisableWorkflowFile) m.Post("/enable", reqRepoAdmin, actions.EnableWorkflowFile) @@ -1553,10 +1586,12 @@ func registerWebRoutes(m *web.Router, webAuth *AuthMiddleware) { m.Group("/workflows/{workflow_name}", func() { m.Get("/badge.svg", webAuth.AllowBasic, webAuth.AllowOAuth2, actions.GetWorkflowBadge) }) - }, optSignIn, context.RepoAssignment, repo.MustBeNotEmpty, reqRepoActionsReader, actions.MustEnableActions) - // end "/{username}/{reponame}/actions" + } + m.Group("/{username}/{reponame}/actions", repoActionsFn, optSignIn, context.RepoAssignment, repo.MustBeNotEmpty, reqRepoActionsReader, actions.MustEnableActions) + m.Group("/{username}/{group_id}/{reponame}/actions", repoActionsFn, optSignIn, context.RepoAssignment, repo.MustBeNotEmpty, reqRepoActionsReader, actions.MustEnableActions) + // end "/{username}/{group_id}/{reponame}/actions" - m.Group("/{username}/{reponame}/wiki", func() { + repoWikiFn := func() { m.Combo(""). Get(repo.Wiki). Post(context.RepoMustNotBeArchived(), reqSignIn, reqUnitWikiWriter, web.Bind(forms.NewWikiForm{}), repo.WikiPost) @@ -1567,13 +1602,18 @@ func registerWebRoutes(m *web.Router, webAuth *AuthMiddleware) { m.Get("/commit/{sha:[a-f0-9]{7,64}}", repo.SetEditorconfigIfExists, repo.SetDiffViewStyle, repo.SetWhitespaceBehavior, repo.Diff) m.Get("/commit/{sha:[a-f0-9]{7,64}}.{ext:patch|diff}", repo.RawDiff) m.Get("/raw/*", repo.WikiRaw) - }, optSignIn, context.RepoAssignment, repo.MustEnableWiki, reqUnitWikiReader, func(ctx *context.Context) { + } + m.Group("/{username}/{reponame}/wiki", repoWikiFn, optSignIn, context.RepoAssignment, repo.MustEnableWiki, reqUnitWikiReader, func(ctx *context.Context) { ctx.Data["PageIsWiki"] = true ctx.Data["CloneButtonOriginLink"] = ctx.Repo.Repository.WikiCloneLink(ctx, ctx.Doer) }) - // end "/{username}/{reponame}/wiki" + m.Group("/{username}/{group_id}/{reponame}/wiki", repoWikiFn, optSignIn, context.RepoAssignment, repo.MustEnableWiki, reqUnitWikiReader, func(ctx *context.Context) { + ctx.Data["PageIsWiki"] = true + ctx.Data["CloneButtonOriginLink"] = ctx.Repo.Repository.WikiCloneLink(ctx, ctx.Doer) + }) + // end "/{username}/{group_id}/{reponame}/wiki" - m.Group("/{username}/{reponame}/activity", func() { + activityFn := func() { // activity has its own permission checks m.Get("", repo.Activity) m.Get("/{period}", repo.Activity) @@ -1592,13 +1632,18 @@ func registerWebRoutes(m *web.Router, webAuth *AuthMiddleware) { m.Get("/data", repo.CodeFrequencyData) // "recent-commits" also uses the same data as "code-frequency" }) }, reqUnitCodeReader) - }, + } + m.Group("/{username}/{reponame}/activity", activityFn, optSignIn, context.RepoAssignment, repo.MustBeNotEmpty, context.RequireUnitReader(unit.TypeCode, unit.TypeIssues, unit.TypePullRequests, unit.TypeReleases), ) - // end "/{username}/{reponame}/activity" + m.Group("/{username}/{group_id}/{reponame}/activity", activityFn, + optSignIn, context.RepoAssignment, repo.MustBeNotEmpty, + context.RequireUnitReader(unit.TypeCode, unit.TypeIssues, unit.TypePullRequests, unit.TypeReleases), + ) + // end "/{username}/{group_id}/{reponame}/activity" - m.Group("/{username}/{reponame}", func() { + repoPullFn := func() { m.Get("/{type:pulls}", repo.Issues) m.Group("/{type:pulls}/{index}", func() { m.Get("", repo.SetEditorconfigIfExists, repo.SetWhitespaceBehavior, repo.GetPullDiffStats, repo.ViewIssue) @@ -1625,10 +1670,12 @@ func registerWebRoutes(m *web.Router, webAuth *AuthMiddleware) { }, context.RepoMustNotBeArchived()) }) }) - }, optSignIn, context.RepoAssignment, repo.MustAllowPulls, reqUnitPullsReader) - // end "/{username}/{reponame}/pulls/{index}": repo pull request + } + m.Group("/{username}/{reponame}", repoPullFn, optSignIn, context.RepoAssignment, repo.MustAllowPulls, reqUnitPullsReader) + m.Group("/{username}/{group_id}/{reponame}", repoPullFn, optSignIn, context.RepoAssignment, repo.MustAllowPulls, reqUnitPullsReader) + // end "/{username}/{group_id}/{reponame}/pulls/{index}": repo pull request - m.Group("/{username}/{reponame}", func() { + repoCodeFn := func() { m.Group("/activity_author_data", func() { m.Get("", repo.ActivityAuthors) m.Get("/{period}", repo.ActivityAuthors) @@ -1707,17 +1754,21 @@ func registerWebRoutes(m *web.Router, webAuth *AuthMiddleware) { m.Get("/forks", repo.Forks) m.Get("/commit/{sha:([a-f0-9]{7,64})}.{ext:patch|diff}", repo.MustBeNotEmpty, repo.RawDiff) m.Post("/lastcommit/*", context.RepoRefByType(git.RefTypeCommit), repo.LastCommit) - }, optSignIn, context.RepoAssignment, reqUnitCodeReader) - // end "/{username}/{reponame}": repo code + } + m.Group("/{username}/{reponame}", repoCodeFn, optSignIn, context.RepoAssignment, reqUnitCodeReader) + m.Group("/{username}/{group_id}/{reponame}", repoCodeFn, optSignIn, context.RepoAssignment, reqUnitCodeReader) + // end "/{username}/{group_id}/{reponame}": repo code - m.Group("/{username}/{reponame}", func() { + fn := func() { m.Get("/stars", starsEnabled, repo.Stars) m.Get("/watchers", repo.Watchers) m.Get("/search", reqUnitCodeReader, repo.Search) m.Post("/action/{action:star|unstar}", reqSignIn, starsEnabled, repo.ActionStar) m.Post("/action/{action:watch|unwatch}", reqSignIn, repo.ActionWatch) m.Post("/action/{action:accept_transfer|reject_transfer}", reqSignIn, repo.ActionTransfer) - }, optSignIn, context.RepoAssignment) + } + m.Group("/{username}/{reponame}", fn, optSignIn, context.RepoAssignment) + m.Group("/{username}/{group_id}/{reponame}", fn, optSignIn, context.RepoAssignment) // git lfs uses its own jwt key, and it handles the token & auth by itself, it conflicts with the general "OAuth2" auth method // pattern: "/{username}/{reponame}/{lfs-paths}": git-lfs support, see also addOwnerRepoGitHTTPRouters diff --git a/tests/integration/mirror_pull_test.go b/tests/integration/mirror_pull_test.go index 7902dc10cb..108eee9830 100644 --- a/tests/integration/mirror_pull_test.go +++ b/tests/integration/mirror_pull_test.go @@ -29,7 +29,7 @@ func TestMirrorPull(t *testing.T) { ctx := t.Context() user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) - repoPath := repo_model.RepoPath(user.Name, repo.Name) + repoPath := repo_model.RepoPath(user.Name, repo.Name, repo.GroupID) opts := migration.MigrateOptions{ RepoName: "test_mirror", diff --git a/tests/integration/pull_merge_test.go b/tests/integration/pull_merge_test.go index efc6d35f55..a22396e690 100644 --- a/tests/integration/pull_merge_test.go +++ b/tests/integration/pull_merge_test.go @@ -11,12 +11,14 @@ import ( "net/url" "os" "path" + "path/filepath" "strconv" "strings" "testing" "time" auth_model "code.gitea.io/gitea/models/auth" + "code.gitea.io/gitea/models/db" git_model "code.gitea.io/gitea/models/git" issues_model "code.gitea.io/gitea/models/issues" pull_model "code.gitea.io/gitea/models/pull"