]> source.dussan.org Git - gitea.git/commitdiff
Hide private repositories in packages (#19584)
authorKN4CK3R <admin@oldschoolhack.me>
Sat, 7 May 2022 16:21:15 +0000 (18:21 +0200)
committerGitHub <noreply@github.com>
Sat, 7 May 2022 16:21:15 +0000 (18:21 +0200)
integrations/api_packages_test.go
modules/convert/package.go
modules/notification/webhook/webhook.go
routers/api/v1/packages/package.go
routers/web/repo/packages.go
routers/web/user/package.go
templates/package/shared/list.tmpl
templates/package/view.tmpl

index b3f6e88d9f20a808ac67d1d4fc2e9b9acf90051c..1f24807060df752f004f65e1b661e32c2a40ca9c 100644 (file)
@@ -71,6 +71,44 @@ func TestPackageAPI(t *testing.T) {
                assert.Equal(t, packageVersion, p.Version)
                assert.NotNil(t, p.Creator)
                assert.Equal(t, user.Name, p.Creator.UserName)
+
+               t.Run("RepositoryLink", func(t *testing.T) {
+                       defer PrintCurrentTest(t)()
+
+                       p, err := packages_model.GetPackageByName(db.DefaultContext, user.ID, packages_model.TypeGeneric, packageName)
+                       assert.NoError(t, err)
+
+                       // no repository link
+                       req := NewRequest(t, "GET", fmt.Sprintf("/api/v1/packages/%s/generic/%s/%s?token=%s", user.Name, packageName, packageVersion, token))
+                       resp := MakeRequest(t, req, http.StatusOK)
+
+                       var ap1 *api.Package
+                       DecodeJSON(t, resp, &ap1)
+                       assert.Nil(t, ap1.Repository)
+
+                       // link to public repository
+                       assert.NoError(t, packages_model.SetRepositoryLink(db.DefaultContext, p.ID, 1))
+
+                       req = NewRequest(t, "GET", fmt.Sprintf("/api/v1/packages/%s/generic/%s/%s?token=%s", user.Name, packageName, packageVersion, token))
+                       resp = MakeRequest(t, req, http.StatusOK)
+
+                       var ap2 *api.Package
+                       DecodeJSON(t, resp, &ap2)
+                       assert.NotNil(t, ap2.Repository)
+                       assert.EqualValues(t, 1, ap2.Repository.ID)
+
+                       // link to private repository
+                       assert.NoError(t, packages_model.SetRepositoryLink(db.DefaultContext, p.ID, 2))
+
+                       req = NewRequest(t, "GET", fmt.Sprintf("/api/v1/packages/%s/generic/%s/%s?token=%s", user.Name, packageName, packageVersion, token))
+                       resp = MakeRequest(t, req, http.StatusOK)
+
+                       var ap3 *api.Package
+                       DecodeJSON(t, resp, &ap3)
+                       assert.Nil(t, ap3.Repository)
+
+                       assert.NoError(t, packages_model.UnlinkRepositoryFromAllPackages(db.DefaultContext, 2))
+               })
        })
 
        t.Run("ListPackageFiles", func(t *testing.T) {
index 681219ca1a413cd66986a459b0a507a55b34f8c2..a4ea41d522e7710e369418863d2f090d9f3cbbaf 100644 (file)
@@ -5,28 +5,38 @@
 package convert
 
 import (
+       "context"
+
+       "code.gitea.io/gitea/models"
        "code.gitea.io/gitea/models/packages"
-       "code.gitea.io/gitea/models/perm"
+       user_model "code.gitea.io/gitea/models/user"
        api "code.gitea.io/gitea/modules/structs"
 )
 
 // ToPackage convert a packages.PackageDescriptor to api.Package
-func ToPackage(pd *packages.PackageDescriptor) *api.Package {
+func ToPackage(ctx context.Context, pd *packages.PackageDescriptor, doer *user_model.User) (*api.Package, error) {
        var repo *api.Repository
        if pd.Repository != nil {
-               repo = ToRepo(pd.Repository, perm.AccessModeNone)
+               permission, err := models.GetUserRepoPermission(ctx, pd.Repository, doer)
+               if err != nil {
+                       return nil, err
+               }
+
+               if permission.HasAccess() {
+                       repo = ToRepo(pd.Repository, permission.AccessMode)
+               }
        }
 
        return &api.Package{
                ID:         pd.Version.ID,
-               Owner:      ToUser(pd.Owner, nil),
+               Owner:      ToUser(pd.Owner, doer),
                Repository: repo,
-               Creator:    ToUser(pd.Creator, nil),
+               Creator:    ToUser(pd.Creator, doer),
                Type:       string(pd.Package.Type),
                Name:       pd.Package.Name,
                Version:    pd.Version.Version,
                CreatedAt:  pd.Version.CreatedUnix.AsTime(),
-       }
+       }, nil
 }
 
 // ToPackageFile converts packages.PackageFileDescriptor to api.PackageFile
index d24440d585c79950d258a933badc15ed3461dc61..c59e972ed6e6cc042e7aceaed0944e1ed303d87b 100644 (file)
@@ -872,17 +872,19 @@ func notifyPackage(sender *user_model.User, pd *packages_model.PackageDescriptor
                return
        }
 
-       org := pd.Owner
-       if !org.IsOrganization() {
-               org = nil
+       ctx, _, finished := process.GetManager().AddContext(graceful.GetManager().HammerContext(), fmt.Sprintf("webhook.notifyPackage Package: %s[%d]", pd.Package.Name, pd.Package.ID))
+       defer finished()
+
+       apiPackage, err := convert.ToPackage(ctx, pd, sender)
+       if err != nil {
+               log.Error("Error converting package: %v", err)
+               return
        }
 
        if err := webhook_services.PrepareWebhooks(pd.Repository, webhook.HookEventPackage, &api.PackagePayload{
-               Action:       action,
-               Repository:   convert.ToRepo(pd.Repository, perm.AccessModeNone),
-               Package:      convert.ToPackage(pd),
-               Organization: convert.ToUser(org, nil),
-               Sender:       convert.ToUser(sender, nil),
+               Action:  action,
+               Package: apiPackage,
+               Sender:  convert.ToUser(sender, nil),
        }); err != nil {
                log.Error("PrepareWebhooks: %v", err)
        }
index f3aa19c3192e743d8320b89b66ca724174004073..038924737ac7c6205a53633054781e29ddc168ca 100644 (file)
@@ -73,7 +73,12 @@ func ListPackages(ctx *context.APIContext) {
 
        apiPackages := make([]*api.Package, 0, len(pds))
        for _, pd := range pds {
-               apiPackages = append(apiPackages, convert.ToPackage(pd))
+               apiPackage, err := convert.ToPackage(ctx, pd, ctx.Doer)
+               if err != nil {
+                       ctx.Error(http.StatusInternalServerError, "Error converting package for api", err)
+                       return
+               }
+               apiPackages = append(apiPackages, apiPackage)
        }
 
        ctx.SetLinkHeader(int(count), listOptions.PageSize)
@@ -115,7 +120,13 @@ func GetPackage(ctx *context.APIContext) {
        //   "404":
        //     "$ref": "#/responses/notFound"
 
-       ctx.JSON(http.StatusOK, convert.ToPackage(ctx.Package.Descriptor))
+       apiPackage, err := convert.ToPackage(ctx, ctx.Package.Descriptor, ctx.Doer)
+       if err != nil {
+               ctx.Error(http.StatusInternalServerError, "Error converting package for api", err)
+               return
+       }
+
+       ctx.JSON(http.StatusOK, apiPackage)
 }
 
 // DeletePackage deletes a package
index b4db2d5787bf9d36118d36528cf30d4903d6f466..03ea4fc5f4f46aee3354505103dec40ae1fa8735 100644 (file)
@@ -62,6 +62,7 @@ func Packages(ctx *context.Context) {
        ctx.Data["HasPackages"] = hasPackages
        ctx.Data["PackageDescriptors"] = pds
        ctx.Data["Total"] = total
+       ctx.Data["RepositoryAccessMap"] = map[int64]bool{ctx.Repo.Repository.ID: true} // There is only the current repository
 
        pager := context.NewPagination(int(total), setting.UI.PackagesPagingNum, page, 5)
        pager.AddParam(ctx, "q", "Query")
index 04b4e1e8ecd6c5bec4ddd09a2c9aecc810566b4e..1c33998db90baca6f4bd2cbc02d7696d59eeb0dc 100644 (file)
@@ -58,6 +58,23 @@ func ListPackages(ctx *context.Context) {
                return
        }
 
+       repositoryAccessMap := make(map[int64]bool)
+       for _, pd := range pds {
+               if pd.Repository == nil {
+                       continue
+               }
+               if _, has := repositoryAccessMap[pd.Repository.ID]; has {
+                       continue
+               }
+
+               permission, err := models.GetUserRepoPermission(ctx, pd.Repository, ctx.Doer)
+               if err != nil {
+                       ctx.ServerError("GetUserRepoPermission", err)
+                       return
+               }
+               repositoryAccessMap[pd.Repository.ID] = permission.HasAccess()
+       }
+
        hasPackages, err := packages_model.HasOwnerPackages(ctx, ctx.ContextUser.ID)
        if err != nil {
                ctx.ServerError("HasOwnerPackages", err)
@@ -72,6 +89,7 @@ func ListPackages(ctx *context.Context) {
        ctx.Data["HasPackages"] = hasPackages
        ctx.Data["PackageDescriptors"] = pds
        ctx.Data["Total"] = total
+       ctx.Data["RepositoryAccessMap"] = repositoryAccessMap
 
        pager := context.NewPagination(int(total), setting.UI.PackagesPagingNum, page, 5)
        pager.AddParam(ctx, "q", "Query")
@@ -157,6 +175,17 @@ func ViewPackageVersion(ctx *context.Context) {
 
        ctx.Data["CanWritePackages"] = ctx.Package.AccessMode >= perm.AccessModeWrite || ctx.IsUserSiteAdmin()
 
+       hasRepositoryAccess := false
+       if pd.Repository != nil {
+               permission, err := models.GetUserRepoPermission(ctx, pd.Repository, ctx.Doer)
+               if err != nil {
+                       ctx.ServerError("GetUserRepoPermission", err)
+                       return
+               }
+               hasRepositoryAccess = permission.HasAccess()
+       }
+       ctx.Data["HasRepositoryAccess"] = hasRepositoryAccess
+
        ctx.HTML(http.StatusOK, tplPackagesView)
 }
 
index 0b0f71283b155d8ce55f4ac35afd17e0cb9fae25..9e6bf5ce9e7c23e593f378c142294caa0c27be9a 100644 (file)
                                        </div>
                                        <div class="desc issue-item-bottom-row df ac fw my-1">
                                                {{$timeStr := TimeSinceUnix .Version.CreatedUnix $.i18n.Lang}}
+                                               {{$hasRepositoryAccess := false}}
                                                {{if .Repository}}
+                                                       {{$hasRepositoryAccess = index $.RepositoryAccessMap .Repository.ID}}
+                                               {{end}}
+                                               {{if $hasRepositoryAccess}}
                                                        {{$.i18n.Tr "packages.published_by_in" $timeStr .Creator.HomeLink (.Creator.GetDisplayName | Escape) .Repository.HTMLURL (.Repository.FullName | Escape) | Safe}}
                                                {{else}}
                                                        {{$.i18n.Tr "packages.published_by" $timeStr .Creator.HomeLink (.Creator.GetDisplayName | Escape) | Safe}}
index bb96da34106694f7555a6537f6af301ba3ed9c31..efad9f9b8fe9a41ec06adb19c82012f70197c8e6 100644 (file)
@@ -10,7 +10,7 @@
                                        </div>
                                        <div>
                                                {{$timeStr := TimeSinceUnix .PackageDescriptor.Version.CreatedUnix $.i18n.Lang}}
-                                               {{if .PackageDescriptor.Repository}}
+                                               {{if .HasRepositoryAccess}}
                                                        {{.i18n.Tr "packages.published_by_in" $timeStr .PackageDescriptor.Creator.HomeLink (.PackageDescriptor.Creator.GetDisplayName | Escape) .PackageDescriptor.Repository.HTMLURL (.PackageDescriptor.Repository.FullName | Escape) | Safe}}
                                                {{else}}
                                                        {{.i18n.Tr "packages.published_by" $timeStr .PackageDescriptor.Creator.HomeLink (.PackageDescriptor.Creator.GetDisplayName | Escape) | Safe}}
@@ -35,7 +35,7 @@
                                                <strong>{{.i18n.Tr "packages.details"}}</strong>
                                                <div class="ui relaxed list">
                                                        <div class="item">{{svg .PackageDescriptor.Package.Type.SVGName 16 "mr-3"}} {{.PackageDescriptor.Package.Type.Name}}</div>
-                                                       {{if .PackageDescriptor.Repository}}
+                                                       {{if .HasRepositoryAccess}}
                                                        <div class="item">{{svg "octicon-repo" 16 "mr-3"}} <a href="{{.PackageDescriptor.Repository.HTMLURL}}">{{.PackageDescriptor.Repository.FullName}}</a></div>
                                                        {{end}}
                                                        <div class="item">{{svg "octicon-calendar" 16 "mr-3"}} {{.PackageDescriptor.Version.CreatedUnix.FormatDate}}</div>
                                                        {{end}}
                                                        </div>
                                                {{end}}
-                                               {{if or .CanWritePackages .PackageDescriptor.Repository}}
+                                               {{if or .CanWritePackages .HasRepositoryAccess}}
                                                        <div class="ui divider"></div>
                                                        <div class="ui relaxed list">
-                                                               {{if .PackageDescriptor.Repository}}
+                                                               {{if .HasRepositoryAccess}}
                                                                <div class="item">{{svg "octicon-issue-opened" 16 "mr-3"}} <a href="{{.PackageDescriptor.Repository.HTMLURL}}/issues">{{.i18n.Tr "repo.issues"}}</a></div>
                                                                {{end}}
                                                                {{if .CanWritePackages}}