Hide private repositories in packages (#19584)
This commit is contained in:
parent
38d72d40f1
commit
8adba93498
8 changed files with 115 additions and 20 deletions
|
@ -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}}
|
||||||
|
|
Loading…
Reference in a new issue