mirror of
				https://gitee.com/gitea/gitea
				synced 2025-11-04 08:30:25 +08:00 
			
		
		
		
	Hide private repositories in packages (#19584)
This commit is contained in:
		@@ -71,6 +71,44 @@ func TestPackageAPI(t *testing.T) {
 | 
				
			|||||||
		assert.Equal(t, packageVersion, p.Version)
 | 
							assert.Equal(t, packageVersion, p.Version)
 | 
				
			||||||
		assert.NotNil(t, p.Creator)
 | 
							assert.NotNil(t, p.Creator)
 | 
				
			||||||
		assert.Equal(t, user.Name, p.Creator.UserName)
 | 
							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) {
 | 
						t.Run("ListPackageFiles", func(t *testing.T) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,28 +5,38 @@
 | 
				
			|||||||
package convert
 | 
					package convert
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
 | 
						"context"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"code.gitea.io/gitea/models"
 | 
				
			||||||
	"code.gitea.io/gitea/models/packages"
 | 
						"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"
 | 
						api "code.gitea.io/gitea/modules/structs"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ToPackage convert a packages.PackageDescriptor to api.Package
 | 
					// 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
 | 
						var repo *api.Repository
 | 
				
			||||||
	if pd.Repository != nil {
 | 
						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{
 | 
						return &api.Package{
 | 
				
			||||||
		ID:         pd.Version.ID,
 | 
							ID:         pd.Version.ID,
 | 
				
			||||||
		Owner:      ToUser(pd.Owner, nil),
 | 
							Owner:      ToUser(pd.Owner, doer),
 | 
				
			||||||
		Repository: repo,
 | 
							Repository: repo,
 | 
				
			||||||
		Creator:    ToUser(pd.Creator, nil),
 | 
							Creator:    ToUser(pd.Creator, doer),
 | 
				
			||||||
		Type:       string(pd.Package.Type),
 | 
							Type:       string(pd.Package.Type),
 | 
				
			||||||
		Name:       pd.Package.Name,
 | 
							Name:       pd.Package.Name,
 | 
				
			||||||
		Version:    pd.Version.Version,
 | 
							Version:    pd.Version.Version,
 | 
				
			||||||
		CreatedAt:  pd.Version.CreatedUnix.AsTime(),
 | 
							CreatedAt:  pd.Version.CreatedUnix.AsTime(),
 | 
				
			||||||
	}
 | 
						}, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ToPackageFile converts packages.PackageFileDescriptor to api.PackageFile
 | 
					// ToPackageFile converts packages.PackageFileDescriptor to api.PackageFile
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -872,17 +872,19 @@ func notifyPackage(sender *user_model.User, pd *packages_model.PackageDescriptor
 | 
				
			|||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	org := pd.Owner
 | 
						ctx, _, finished := process.GetManager().AddContext(graceful.GetManager().HammerContext(), fmt.Sprintf("webhook.notifyPackage Package: %s[%d]", pd.Package.Name, pd.Package.ID))
 | 
				
			||||||
	if !org.IsOrganization() {
 | 
						defer finished()
 | 
				
			||||||
		org = nil
 | 
					
 | 
				
			||||||
 | 
						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{
 | 
						if err := webhook_services.PrepareWebhooks(pd.Repository, webhook.HookEventPackage, &api.PackagePayload{
 | 
				
			||||||
		Action:       action,
 | 
							Action:  action,
 | 
				
			||||||
		Repository:   convert.ToRepo(pd.Repository, perm.AccessModeNone),
 | 
							Package: apiPackage,
 | 
				
			||||||
		Package:      convert.ToPackage(pd),
 | 
							Sender:  convert.ToUser(sender, nil),
 | 
				
			||||||
		Organization: convert.ToUser(org, nil),
 | 
					 | 
				
			||||||
		Sender:       convert.ToUser(sender, nil),
 | 
					 | 
				
			||||||
	}); err != nil {
 | 
						}); err != nil {
 | 
				
			||||||
		log.Error("PrepareWebhooks: %v", err)
 | 
							log.Error("PrepareWebhooks: %v", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -73,7 +73,12 @@ func ListPackages(ctx *context.APIContext) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	apiPackages := make([]*api.Package, 0, len(pds))
 | 
						apiPackages := make([]*api.Package, 0, len(pds))
 | 
				
			||||||
	for _, pd := range 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)
 | 
						ctx.SetLinkHeader(int(count), listOptions.PageSize)
 | 
				
			||||||
@@ -115,7 +120,13 @@ func GetPackage(ctx *context.APIContext) {
 | 
				
			|||||||
	//   "404":
 | 
						//   "404":
 | 
				
			||||||
	//     "$ref": "#/responses/notFound"
 | 
						//     "$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
 | 
					// DeletePackage deletes a package
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -62,6 +62,7 @@ func Packages(ctx *context.Context) {
 | 
				
			|||||||
	ctx.Data["HasPackages"] = hasPackages
 | 
						ctx.Data["HasPackages"] = hasPackages
 | 
				
			||||||
	ctx.Data["PackageDescriptors"] = pds
 | 
						ctx.Data["PackageDescriptors"] = pds
 | 
				
			||||||
	ctx.Data["Total"] = total
 | 
						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 := context.NewPagination(int(total), setting.UI.PackagesPagingNum, page, 5)
 | 
				
			||||||
	pager.AddParam(ctx, "q", "Query")
 | 
						pager.AddParam(ctx, "q", "Query")
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -58,6 +58,23 @@ func ListPackages(ctx *context.Context) {
 | 
				
			|||||||
		return
 | 
							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)
 | 
						hasPackages, err := packages_model.HasOwnerPackages(ctx, ctx.ContextUser.ID)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		ctx.ServerError("HasOwnerPackages", err)
 | 
							ctx.ServerError("HasOwnerPackages", err)
 | 
				
			||||||
@@ -72,6 +89,7 @@ func ListPackages(ctx *context.Context) {
 | 
				
			|||||||
	ctx.Data["HasPackages"] = hasPackages
 | 
						ctx.Data["HasPackages"] = hasPackages
 | 
				
			||||||
	ctx.Data["PackageDescriptors"] = pds
 | 
						ctx.Data["PackageDescriptors"] = pds
 | 
				
			||||||
	ctx.Data["Total"] = total
 | 
						ctx.Data["Total"] = total
 | 
				
			||||||
 | 
						ctx.Data["RepositoryAccessMap"] = repositoryAccessMap
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pager := context.NewPagination(int(total), setting.UI.PackagesPagingNum, page, 5)
 | 
						pager := context.NewPagination(int(total), setting.UI.PackagesPagingNum, page, 5)
 | 
				
			||||||
	pager.AddParam(ctx, "q", "Query")
 | 
						pager.AddParam(ctx, "q", "Query")
 | 
				
			||||||
@@ -157,6 +175,17 @@ func ViewPackageVersion(ctx *context.Context) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	ctx.Data["CanWritePackages"] = ctx.Package.AccessMode >= perm.AccessModeWrite || ctx.IsUserSiteAdmin()
 | 
						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)
 | 
						ctx.HTML(http.StatusOK, tplPackagesView)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -30,7 +30,11 @@
 | 
				
			|||||||
					</div>
 | 
										</div>
 | 
				
			||||||
					<div class="desc issue-item-bottom-row df ac fw my-1">
 | 
										<div class="desc issue-item-bottom-row df ac fw my-1">
 | 
				
			||||||
						{{$timeStr := TimeSinceUnix .Version.CreatedUnix $.i18n.Lang}}
 | 
											{{$timeStr := TimeSinceUnix .Version.CreatedUnix $.i18n.Lang}}
 | 
				
			||||||
 | 
											{{$hasRepositoryAccess := false}}
 | 
				
			||||||
						{{if .Repository}}
 | 
											{{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}}
 | 
												{{$.i18n.Tr "packages.published_by_in" $timeStr .Creator.HomeLink (.Creator.GetDisplayName | Escape) .Repository.HTMLURL (.Repository.FullName | Escape) | Safe}}
 | 
				
			||||||
						{{else}}
 | 
											{{else}}
 | 
				
			||||||
							{{$.i18n.Tr "packages.published_by" $timeStr .Creator.HomeLink (.Creator.GetDisplayName | Escape) | Safe}}
 | 
												{{$.i18n.Tr "packages.published_by" $timeStr .Creator.HomeLink (.Creator.GetDisplayName | Escape) | Safe}}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -10,7 +10,7 @@
 | 
				
			|||||||
					</div>
 | 
										</div>
 | 
				
			||||||
					<div>
 | 
										<div>
 | 
				
			||||||
						{{$timeStr := TimeSinceUnix .PackageDescriptor.Version.CreatedUnix $.i18n.Lang}}
 | 
											{{$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}}
 | 
												{{.i18n.Tr "packages.published_by_in" $timeStr .PackageDescriptor.Creator.HomeLink (.PackageDescriptor.Creator.GetDisplayName | Escape) .PackageDescriptor.Repository.HTMLURL (.PackageDescriptor.Repository.FullName | Escape) | Safe}}
 | 
				
			||||||
						{{else}}
 | 
											{{else}}
 | 
				
			||||||
							{{.i18n.Tr "packages.published_by" $timeStr .PackageDescriptor.Creator.HomeLink (.PackageDescriptor.Creator.GetDisplayName | Escape) | Safe}}
 | 
												{{.i18n.Tr "packages.published_by" $timeStr .PackageDescriptor.Creator.HomeLink (.PackageDescriptor.Creator.GetDisplayName | Escape) | Safe}}
 | 
				
			||||||
@@ -35,7 +35,7 @@
 | 
				
			|||||||
						<strong>{{.i18n.Tr "packages.details"}}</strong>
 | 
											<strong>{{.i18n.Tr "packages.details"}}</strong>
 | 
				
			||||||
						<div class="ui relaxed list">
 | 
											<div class="ui relaxed list">
 | 
				
			||||||
							<div class="item">{{svg .PackageDescriptor.Package.Type.SVGName 16 "mr-3"}} {{.PackageDescriptor.Package.Type.Name}}</div>
 | 
												<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>
 | 
												<div class="item">{{svg "octicon-repo" 16 "mr-3"}} <a href="{{.PackageDescriptor.Repository.HTMLURL}}">{{.PackageDescriptor.Repository.FullName}}</a></div>
 | 
				
			||||||
							{{end}}
 | 
												{{end}}
 | 
				
			||||||
							<div class="item">{{svg "octicon-calendar" 16 "mr-3"}} {{.PackageDescriptor.Version.CreatedUnix.FormatDate}}</div>
 | 
												<div class="item">{{svg "octicon-calendar" 16 "mr-3"}} {{.PackageDescriptor.Version.CreatedUnix.FormatDate}}</div>
 | 
				
			||||||
@@ -76,10 +76,10 @@
 | 
				
			|||||||
							{{end}}
 | 
												{{end}}
 | 
				
			||||||
							</div>
 | 
												</div>
 | 
				
			||||||
						{{end}}
 | 
											{{end}}
 | 
				
			||||||
						{{if or .CanWritePackages .PackageDescriptor.Repository}}
 | 
											{{if or .CanWritePackages .HasRepositoryAccess}}
 | 
				
			||||||
							<div class="ui divider"></div>
 | 
												<div class="ui divider"></div>
 | 
				
			||||||
							<div class="ui relaxed list">
 | 
												<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>
 | 
													<div class="item">{{svg "octicon-issue-opened" 16 "mr-3"}} <a href="{{.PackageDescriptor.Repository.HTMLURL}}/issues">{{.i18n.Tr "repo.issues"}}</a></div>
 | 
				
			||||||
								{{end}}
 | 
													{{end}}
 | 
				
			||||||
								{{if .CanWritePackages}}
 | 
													{{if .CanWritePackages}}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user