Move package settings to package instead of being tied to version (#37026)
Unties settings page from package version and adds button to delete the package version Settings page now allows for deletion of entire package and it's versions as opposed to a single version Adds an API endpoint to delete the entire package with all versions from registry fixes: https://github.com/go-gitea/gitea/issues/36904 Co-Authored-By: gemini-3-flash --------- Co-authored-by: wxiaoguang <wxiaoguang@gmail.com> Co-authored-by: Giteabot <teabot@gitea.io>
This commit is contained in:
+37
-16
@@ -4,6 +4,7 @@
|
||||
package context
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
@@ -58,23 +59,28 @@ func PackageAssignmentAPI() func(ctx *APIContext) {
|
||||
}
|
||||
|
||||
func packageAssignment(ctx *packageAssignmentCtx, errCb func(int, any)) *Package {
|
||||
pkg := &Package{
|
||||
Owner: ctx.ContextUser,
|
||||
}
|
||||
var err error
|
||||
pkg.AccessMode, err = determineAccessMode(ctx.Base, pkg, ctx.Doer)
|
||||
pkgOwner := ctx.ContextUser
|
||||
accessMode, err := determineAccessMode(ctx.Base, pkgOwner, ctx.Doer)
|
||||
if err != nil {
|
||||
errCb(http.StatusInternalServerError, fmt.Errorf("determineAccessMode: %w", err))
|
||||
return nil
|
||||
}
|
||||
|
||||
pkg := &Package{
|
||||
Owner: pkgOwner,
|
||||
AccessMode: accessMode,
|
||||
}
|
||||
packageType := ctx.PathParam("type")
|
||||
name := ctx.PathParam("name")
|
||||
if packageType == "" || name == "" {
|
||||
return pkg
|
||||
}
|
||||
|
||||
packageType := ctx.PathParam("type")
|
||||
name := ctx.PathParam("name")
|
||||
version := ctx.PathParam("version")
|
||||
if packageType != "" && name != "" && 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 {
|
||||
if errors.Is(err, packages_model.ErrPackageNotExist) {
|
||||
errCb(http.StatusNotFound, fmt.Errorf("GetVersionByNameAndVersion: %w", err))
|
||||
} else {
|
||||
errCb(http.StatusInternalServerError, fmt.Errorf("GetVersionByNameAndVersion: %w", err))
|
||||
@@ -87,12 +93,27 @@ func packageAssignment(ctx *packageAssignmentCtx, errCb func(int, any)) *Package
|
||||
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 errors.Is(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,
|
||||
}
|
||||
}
|
||||
|
||||
return pkg
|
||||
}
|
||||
|
||||
func determineAccessMode(ctx *Base, pkg *Package, doer *user_model.User) (perm.AccessMode, error) {
|
||||
func determineAccessMode(ctx *Base, pkgOwner, doer *user_model.User) (perm.AccessMode, error) {
|
||||
if setting.Service.RequireSignInViewStrict && (doer == nil || doer.IsGhost()) {
|
||||
return perm.AccessModeNone, nil
|
||||
}
|
||||
@@ -103,8 +124,8 @@ func determineAccessMode(ctx *Base, pkg *Package, doer *user_model.User) (perm.A
|
||||
|
||||
// TODO: ActionUser permission check
|
||||
accessMode := perm.AccessModeNone
|
||||
if pkg.Owner.IsOrganization() {
|
||||
org := organization.OrgFromUser(pkg.Owner)
|
||||
if pkgOwner.IsOrganization() {
|
||||
org := organization.OrgFromUser(pkgOwner)
|
||||
|
||||
if doer != nil && !doer.IsGhost() {
|
||||
// 1. If user is logged in, check all team packages permissions
|
||||
@@ -128,19 +149,19 @@ func determineAccessMode(ctx *Base, pkg *Package, doer *user_model.User) (perm.A
|
||||
}
|
||||
}
|
||||
}
|
||||
if accessMode == perm.AccessModeNone && organization.HasOrgOrUserVisible(ctx, pkg.Owner, doer) {
|
||||
if accessMode == perm.AccessModeNone && organization.HasOrgOrUserVisible(ctx, pkgOwner, doer) {
|
||||
// 2. If user is unauthorized or no org member, check if org is visible
|
||||
accessMode = perm.AccessModeRead
|
||||
}
|
||||
} else {
|
||||
if doer != nil && !doer.IsGhost() {
|
||||
// 1. Check if user is package owner
|
||||
if doer.ID == pkg.Owner.ID {
|
||||
if doer.ID == pkgOwner.ID {
|
||||
accessMode = perm.AccessModeOwner
|
||||
} else if pkg.Owner.Visibility == structs.VisibleTypePublic || pkg.Owner.Visibility == structs.VisibleTypeLimited { // 2. Check if package owner is public or limited
|
||||
} else if pkgOwner.Visibility == structs.VisibleTypePublic || pkgOwner.Visibility == structs.VisibleTypeLimited { // 2. Check if package owner is public or limited
|
||||
accessMode = perm.AccessModeRead
|
||||
}
|
||||
} else if pkg.Owner.Visibility == structs.VisibleTypePublic { // 3. Check if package owner is public
|
||||
} else if pkgOwner.Visibility == structs.VisibleTypePublic { // 3. Check if package owner is public
|
||||
accessMode = perm.AccessModeRead
|
||||
}
|
||||
}
|
||||
|
||||
@@ -184,6 +184,7 @@ func CleanupExpiredData(ctx context.Context, olderThan time.Duration) error {
|
||||
}
|
||||
}
|
||||
|
||||
// HINT: PACKAGE-DEFER-STORAGE-DELETE: Handle blob deletion for package storage
|
||||
pbs, err = packages_model.FindExpiredUnreferencedBlobs(ctx, olderThan)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -473,7 +473,8 @@ func RemovePackageVersion(ctx context.Context, doer *user_model.User, pv *packag
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// HINT: PACKAGE-DEFER-STORAGE-DELETE: Blobs are not deleted immediately, instead they are deleted by the cleanup_packages cron task.
|
||||
// If there are no more versions for the package, the same task removes that as well.
|
||||
if err := db.WithTx(ctx, func(ctx context.Context) error {
|
||||
log.Trace("Deleting package: %v", pv.ID)
|
||||
return DeletePackageVersionAndReferences(ctx, pv)
|
||||
@@ -532,16 +533,11 @@ func DeletePackageVersionAndReferences(ctx context.Context, pv *packages_model.P
|
||||
if err := packages_model.DeleteAllProperties(ctx, packages_model.PropertyTypeVersion, pv.ID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
pfs, err := packages_model.GetFilesByVersionID(ctx, pv.ID)
|
||||
if err != nil {
|
||||
if err := packages_model.DeleteFilePropertiesByVersionID(ctx, pv.ID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, pf := range pfs {
|
||||
if err := DeletePackageFile(ctx, pf); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := packages_model.DeleteFilesByVersionID(ctx, pv.ID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return packages_model.DeleteVersionByID(ctx, pv.ID)
|
||||
@@ -629,6 +625,46 @@ 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 {
|
||||
pds, err := packages_model.GetAllPackageDescriptors(ctx, p)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// HINT: PACKAGE-DEFER-STORAGE-DELETE: Blobs are not deleted immediately, instead they are deleted by cleanup_packages cron task.
|
||||
err = db.WithTx(ctx, func(ctx context.Context) error {
|
||||
err := packages_model.DeletePropertiesByPackageID(ctx, packages_model.PropertyTypePackage, p.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = packages_model.DeletePropertiesByPackageID(ctx, packages_model.PropertyTypeFile, p.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = packages_model.DeletePropertiesByPackageID(ctx, packages_model.PropertyTypeVersion, p.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = packages_model.DeleteFilesByPackageID(ctx, p.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = packages_model.DeleteVersionsByPackageID(ctx, p.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return packages_model.DeletePackageByID(ctx, p.ID)
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, pd := range pds {
|
||||
notify_service.PackageDelete(ctx, doer, pd)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// RemoveAllPackages for User
|
||||
func RemoveAllPackages(ctx context.Context, userID int64) (int, error) {
|
||||
count := 0
|
||||
|
||||
Reference in New Issue
Block a user