diff --git a/routers/web/web.go b/routers/web/web.go index bf111c87f6..67b4be89ec 100644 --- a/routers/web/web.go +++ b/routers/web/web.go @@ -1524,7 +1524,7 @@ func registerWebRoutes(m *web.Router, webAuth *AuthMiddleware) { m.Get("/updates/drupal.xml", repo.ServeDrupalXML) m.Get("/updates/whmcs.json", repo.ServeWHMCSJSON) m.Get("/changelog.xml", repo.ServeChangelogXML) - }, optSignIn, context.RepoAssignment) + }, context.RepoAssignmentPublicFeed()) // end "/{username}/{reponame}": update server // "/{username}/{reponame}": licenses page diff --git a/services/context/repo_public_feed.go b/services/context/repo_public_feed.go new file mode 100644 index 0000000000..a66f992b75 --- /dev/null +++ b/services/context/repo_public_feed.go @@ -0,0 +1,55 @@ +// Copyright 2026 Moko Consulting +// SPDX-License-Identifier: GPL-3.0-or-later + +package context + +import ( + licenses_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/licenses" + repo_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/repo" + user_model "code.mokoconsulting.tech/MokoConsulting/MokoGitea/models/user" + "code.mokoconsulting.tech/MokoConsulting/MokoGitea/modules/log" +) + +// RepoAssignmentPublicFeed is a lightweight repo loader for update feed endpoints. +// It loads the repo and owner without checking user permissions — the feed +// handlers gate access via license keys instead of repo membership. +// This allows private repos to serve update feeds to anonymous clients. +func RepoAssignmentPublicFeed() func(ctx *Context) { + return func(ctx *Context) { + ownerName := ctx.PathParam("username") + repoName := ctx.PathParam("reponame") + + owner, err := user_model.GetUserByName(ctx, ownerName) + if err != nil { + if user_model.IsErrUserNotExist(err) { + ctx.NotFound(err) + } else { + ctx.ServerError("GetUserByName", err) + } + return + } + + repo, err := repo_model.GetRepositoryByOwnerAndName(ctx, ownerName, repoName) + if err != nil { + if repo_model.IsErrRepoNotExist(err) { + ctx.NotFound(err) + } else { + ctx.ServerError("GetRepositoryByOwnerAndName", err) + } + return + } + + repo.Owner = owner + ctx.Repo.Repository = repo + + // Load update config for platform-aware routing. + repoUpdateCfg, _ := licenses_model.GetRepoConfig(ctx, repo.ID) + if repoUpdateCfg != nil { + ctx.Data["RepoUpdatePlatform"] = repoUpdateCfg.Platform + } else { + ctx.Data["RepoUpdatePlatform"] = "joomla" + } + + log.Trace("Public feed access: %s/%s", ownerName, repoName) + } +}