0
0
mirror of https://github.com/go-gitea/gitea.git synced 2026-05-06 23:38:48 +02:00

move settings tab from package version to package

This commit is contained in:
TheFox0x7 2026-03-29 12:04:37 +02:00
parent 0ec66b5380
commit d8c16470d2
No known key found for this signature in database
7 changed files with 106 additions and 31 deletions

View File

@ -3607,6 +3607,7 @@
"packages.settings.delete": "Delete package",
"packages.settings.delete.description": "Deleting a package is permanent and cannot be undone.",
"packages.settings.delete.notice": "You are about to delete %s (%s). This operation is irreversible, are you sure?",
"packages.settings.delete.notice.package": "You are about to delete %s and all its versions. This operation is irreversible, are you sure?",
"packages.settings.delete.success": "The package has been deleted.",
"packages.settings.delete.error": "Failed to delete the package.",
"packages.owner.settings.cargo.title": "Cargo Registry Index",

View File

@ -491,18 +491,37 @@ func packageSettingsPostActionLink(ctx *context.Context, form *forms.PackageSett
}
func packageSettingsPostActionDelete(ctx *context.Context) {
err := packages_service.RemovePackageVersion(ctx, ctx.Doer, ctx.Package.Descriptor.Version)
if err != nil {
pd := ctx.Package.Descriptor
if err := packages_service.RemovePackage(ctx, ctx.Doer, pd.Package); err != nil {
log.Error("Error deleting package: %v", err)
ctx.Flash.Error(ctx.Tr("packages.settings.delete.error"))
} else {
ctx.Flash.Success(ctx.Tr("packages.settings.delete.success"))
}
ctx.Redirect(ctx.Package.Owner.HomeLink() + "/-/packages")
}
// PackageVersionDelete deletes a package version
func PackageVersionDelete(ctx *context.Context) {
pd := ctx.Package.Descriptor
if pd.Version == nil {
ctx.NotFound(nil)
return
}
if err := packages_service.RemovePackageVersion(ctx, ctx.Doer, pd.Version); err != nil {
log.Error("Error deleting package version: %v", err)
ctx.Flash.Error(ctx.Tr("packages.settings.delete.error"))
} else {
ctx.Flash.Success(ctx.Tr("packages.settings.delete.success"))
}
redirectURL := ctx.Package.Owner.HomeLink() + "/-/packages"
// redirect to the package if there are still versions available
if has, _ := packages_model.ExistVersion(ctx, &packages_model.PackageSearchOptions{PackageID: ctx.Package.Descriptor.Package.ID, IsInternal: optional.Some(false)}); has {
redirectURL = ctx.Package.Descriptor.PackageWebLink()
if has, _ := packages_model.ExistVersion(ctx, &packages_model.PackageSearchOptions{PackageID: pd.Package.ID, IsInternal: optional.Some(false)}); has {
redirectURL = pd.PackageWebLink()
}
ctx.Redirect(redirectURL)

View File

@ -1072,16 +1072,18 @@ func registerWebRoutes(m *web.Router, webAuth *AuthMiddleware) {
m.Get("", user.ListPackages)
m.Group("/{type}/{name}", func() {
m.Get("", user.RedirectToLastVersion)
m.Get("/versions", user.ListPackageVersions)
m.Group("/{version}", func() {
m.Get("", user.ViewPackageVersion)
m.Get("/{version_sub}", user.ViewPackageVersion)
m.Get("/files/{fileid}", user.DownloadPackageFile)
m.Group("/settings", func() {
m.Get("", user.PackageSettings)
m.Post("", web.Bind(forms.PackageSettingForm{}), user.PackageSettingsPost)
}, reqPackageAccess(perm.AccessModeWrite))
})
// use `~` as a separator; otherwise it might clash with a user package named `-` or `settings`
m.Group("/~/settings", func() {
m.Get("", user.PackageSettings)
m.Post("", web.Bind(forms.PackageSettingForm{}), user.PackageSettingsPost)
}, reqPackageAccess(perm.AccessModeWrite))
})
m.Get("/versions", user.ListPackageVersions)
m.Group("/{version}", func() {
m.Get("", user.ViewPackageVersion)
m.Post("", reqPackageAccess(perm.AccessModeWrite), user.PackageVersionDelete)
m.Get("/{version_sub}", user.ViewPackageVersion)
m.Get("/files/{fileid}", user.DownloadPackageFile)
})
}, context.PackageAssignment(), reqPackageAccess(perm.AccessModeRead))
}

View File

@ -70,22 +70,39 @@ func packageAssignment(ctx *packageAssignmentCtx, errCb func(int, any)) *Package
packageType := ctx.PathParam("type")
name := ctx.PathParam("name")
version := ctx.PathParam("version")
if packageType != "" && name != "" && version != "" {
pv, err := packages_model.GetVersionByNameAndVersion(ctx, pkg.Owner.ID, packages_model.Type(packageType), name, version)
if err != nil {
if err == packages_model.ErrPackageNotExist {
errCb(http.StatusNotFound, fmt.Errorf("GetVersionByNameAndVersion: %w", err))
} else {
errCb(http.StatusInternalServerError, fmt.Errorf("GetVersionByNameAndVersion: %w", err))
if packageType != "" && name != "" {
version := ctx.PathParam("version")
if version != "" {
pv, err := packages_model.GetVersionByNameAndVersion(ctx, pkg.Owner.ID, packages_model.Type(packageType), name, version)
if err != nil {
if err == packages_model.ErrPackageNotExist {
errCb(http.StatusNotFound, fmt.Errorf("GetVersionByNameAndVersion: %w", err))
} else {
errCb(http.StatusInternalServerError, fmt.Errorf("GetVersionByNameAndVersion: %w", err))
}
return pkg
}
return pkg
}
pkg.Descriptor, err = packages_model.GetPackageDescriptor(ctx, pv)
if err != nil {
errCb(http.StatusInternalServerError, fmt.Errorf("GetPackageDescriptor: %w", err))
return pkg
pkg.Descriptor, err = packages_model.GetPackageDescriptor(ctx, pv)
if err != nil {
errCb(http.StatusInternalServerError, fmt.Errorf("GetPackageDescriptor: %w", err))
return pkg
}
} else {
p, err := packages_model.GetPackageByName(ctx, pkg.Owner.ID, packages_model.Type(packageType), name)
if err != nil {
if err == packages_model.ErrPackageNotExist {
errCb(http.StatusNotFound, fmt.Errorf("GetPackageByName: %w", err))
} else {
errCb(http.StatusInternalServerError, fmt.Errorf("GetPackageByName: %w", err))
}
return pkg
}
pkg.Descriptor = &packages_model.PackageDescriptor{
Package: p,
Owner: pkg.Owner,
}
}
}

View File

@ -629,6 +629,25 @@ func OpenBlobForDownload(ctx context.Context, pf *packages_model.PackageFile, pb
return s, u, pf, nil
}
// RemovePackage deletes the package and all its versions
func RemovePackage(ctx context.Context, doer *user_model.User, p *packages_model.Package) error {
pvs, _, err := packages_model.SearchVersions(ctx, &packages_model.PackageSearchOptions{
PackageID: p.ID,
IsInternal: optional.None[bool](),
})
if err != nil {
return err
}
for _, pv := range pvs {
if err := RemovePackageVersion(ctx, doer, pv); err != nil {
return err
}
}
return packages_model.DeletePackageByID(ctx, p.ID)
}
// RemoveAllPackages for User
func RemoveAllPackages(ctx context.Context, userID int64) (int, error) {
count := 0

View File

@ -10,7 +10,7 @@
{{template "user/overview/header" .}}
{{end}}
{{template "base/alert" .}}
<p><a href="{{.PackageDescriptor.VersionWebLink}}">{{.PackageDescriptor.Package.Name}} ({{.PackageDescriptor.Version.Version}})</a> / <strong>{{ctx.Locale.Tr "repo.settings"}}</strong></p>
<p><a href="{{.PackageDescriptor.PackageWebLink}}">{{.PackageDescriptor.Package.Name}}</a> / <strong>{{ctx.Locale.Tr "repo.settings"}}</strong></p>
<h4 class="ui top attached header">
{{ctx.Locale.Tr "packages.settings.link"}}
</h4>
@ -45,7 +45,7 @@
</div>
<div class="content">
<div class="ui warning message tw-break-anywhere">
{{ctx.Locale.Tr "packages.settings.delete.notice" .PackageDescriptor.Package.Name .PackageDescriptor.Version.Version}}
{{ctx.Locale.Tr "packages.settings.delete.notice.package" .PackageDescriptor.Package.Name}}
</div>
<form class="ui form" action="{{.Link}}" method="post">
<input type="hidden" name="action" value="delete">

View File

@ -99,7 +99,24 @@
<div class="item">{{svg "octicon-issue-opened"}} <a href="{{.PackageDescriptor.Repository.Link}}/issues">{{ctx.Locale.Tr "repo.issues"}}</a></div>
{{end}}
{{if .CanWritePackages}}
<div class="item">{{svg "octicon-tools"}} <a href="{{$packageVersionLink}}/settings">{{ctx.Locale.Tr "repo.settings"}}</a></div>
<div class="item">{{svg "octicon-tools"}} <a href="{{.PackageDescriptor.PackageWebLink}}/settings">{{ctx.Locale.Tr "repo.settings"}}</a></div>
<div class="item">
{{svg "octicon-trash"}}
<a class="show-modal" data-modal="#delete-package-version-modal">{{ctx.Locale.Tr "packages.settings.delete"}}</a>
<div class="ui tiny modal" id="delete-package-version-modal">
<div class="header">
{{ctx.Locale.Tr "packages.settings.delete"}}
</div>
<div class="content">
<div class="ui warning message tw-break-anywhere">
{{ctx.Locale.Tr "packages.settings.delete.notice" .PackageDescriptor.Package.Name .PackageDescriptor.Version.Version}}
</div>
<form class="ui form" action="{{$packageVersionLink}}" method="post">
{{template "base/modal_actions_confirm" .}}
</form>
</div>
</div>
</div>
{{end}}
</div>
{{end}}