Some checks failed
Build and Release / Create Release (push) Successful in 0s
Build and Release / Unit Tests (push) Successful in 3m12s
Build and Release / Integration Tests (PostgreSQL) (push) Successful in 5m8s
Build and Release / Lint (push) Successful in 5m19s
Build and Release / Build Binaries (amd64, linux, linux-latest) (push) Successful in 3m11s
Build and Release / Build Binaries (amd64, darwin, macos) (push) Successful in 5m38s
Build and Release / Build Binaries (amd64, windows, windows-latest) (push) Successful in 9h5m9s
Build and Release / Build Binary (linux/arm64) (push) Successful in 8m29s
Build and Release / Build Binaries (arm64, darwin, macos) (push) Failing after 10m38s
Add ability to bulk set packages as private or public in both admin and repository package views. Includes new bulk action buttons, visibility grouping in repository view, and corresponding backend handlers for processing visibility changes. Admin can manage all packages while repository owners can manage their own packages.
239 lines
6.7 KiB
Go
239 lines
6.7 KiB
Go
// Copyright 2014 The Gogs Authors. All rights reserved.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package admin
|
|
|
|
import (
|
|
"fmt"
|
|
"net/http"
|
|
"net/url"
|
|
"time"
|
|
|
|
"code.gitcaddy.com/server/v3/models/db"
|
|
packages_model "code.gitcaddy.com/server/v3/models/packages"
|
|
"code.gitcaddy.com/server/v3/modules/optional"
|
|
"code.gitcaddy.com/server/v3/modules/setting"
|
|
"code.gitcaddy.com/server/v3/modules/templates"
|
|
"code.gitcaddy.com/server/v3/services/context"
|
|
packages_service "code.gitcaddy.com/server/v3/services/packages"
|
|
packages_cleanup_service "code.gitcaddy.com/server/v3/services/packages/cleanup"
|
|
)
|
|
|
|
const (
|
|
tplPackagesList templates.TplName = "admin/packages/list"
|
|
)
|
|
|
|
// Packages shows all packages
|
|
func Packages(ctx *context.Context) {
|
|
page := max(ctx.FormInt("page"), 1)
|
|
query := ctx.FormTrim("q")
|
|
packageType := ctx.FormTrim("type")
|
|
sort := ctx.FormTrim("sort")
|
|
|
|
pvs, total, err := packages_model.SearchVersions(ctx, &packages_model.PackageSearchOptions{
|
|
Type: packages_model.Type(packageType),
|
|
Name: packages_model.SearchValue{Value: query},
|
|
Sort: sort,
|
|
IsInternal: optional.Some(false),
|
|
Paginator: &db.ListOptions{
|
|
PageSize: setting.UI.PackagesPagingNum,
|
|
Page: page,
|
|
},
|
|
})
|
|
if err != nil {
|
|
ctx.ServerError("SearchVersions", err)
|
|
return
|
|
}
|
|
|
|
pds, err := packages_model.GetPackageDescriptors(ctx, pvs)
|
|
if err != nil {
|
|
ctx.ServerError("GetPackageDescriptors", err)
|
|
return
|
|
}
|
|
|
|
totalBlobSize, err := packages_model.GetTotalBlobSize(ctx)
|
|
if err != nil {
|
|
ctx.ServerError("GetTotalBlobSize", err)
|
|
return
|
|
}
|
|
|
|
totalUnreferencedBlobSize, err := packages_model.GetTotalUnreferencedBlobSize(ctx)
|
|
if err != nil {
|
|
ctx.ServerError("CalculateBlobSize", err)
|
|
return
|
|
}
|
|
|
|
ctx.Data["Title"] = ctx.Tr("packages.title")
|
|
ctx.Data["PageIsAdminPackages"] = true
|
|
ctx.Data["Query"] = query
|
|
ctx.Data["PackageType"] = packageType
|
|
ctx.Data["AvailableTypes"] = packages_model.TypeList
|
|
ctx.Data["SortType"] = sort
|
|
ctx.Data["PackageDescriptors"] = pds
|
|
ctx.Data["TotalCount"] = total
|
|
ctx.Data["TotalBlobSize"] = totalBlobSize - totalUnreferencedBlobSize
|
|
ctx.Data["TotalUnreferencedBlobSize"] = totalUnreferencedBlobSize
|
|
|
|
pager := context.NewPagination(int(total), setting.UI.PackagesPagingNum, page, 5)
|
|
pager.AddParamFromRequest(ctx.Req)
|
|
ctx.Data["Page"] = pager
|
|
|
|
ctx.HTML(http.StatusOK, tplPackagesList)
|
|
}
|
|
|
|
// DeletePackageVersion deletes a package version
|
|
func DeletePackageVersion(ctx *context.Context) {
|
|
pv, err := packages_model.GetVersionByID(ctx, ctx.FormInt64("id"))
|
|
if err != nil {
|
|
ctx.ServerError("GetRepositoryByID", err)
|
|
return
|
|
}
|
|
|
|
if err := packages_service.RemovePackageVersion(ctx, ctx.Doer, pv); err != nil {
|
|
ctx.ServerError("RemovePackageVersion", err)
|
|
return
|
|
}
|
|
|
|
ctx.Flash.Success(ctx.Tr("packages.settings.delete.success"))
|
|
ctx.JSONRedirect(setting.AppSubURL + "/-/admin/packages?page=" + url.QueryEscape(ctx.FormString("page")) + "&q=" + url.QueryEscape(ctx.FormString("q")) + "&type=" + url.QueryEscape(ctx.FormString("type")))
|
|
}
|
|
|
|
func CleanupExpiredData(ctx *context.Context) {
|
|
if err := packages_cleanup_service.CleanupExpiredData(ctx, time.Duration(0)); err != nil {
|
|
ctx.ServerError("CleanupExpiredData", err)
|
|
return
|
|
}
|
|
|
|
ctx.Flash.Success(ctx.Tr("admin.packages.cleanup.success"))
|
|
ctx.Redirect(setting.AppSubURL + "/-/admin/packages")
|
|
}
|
|
|
|
// BulkSetGlobal sets/unsets global flag on multiple packages
|
|
func BulkSetGlobal(ctx *context.Context) {
|
|
packageIDs := ctx.FormStrings("ids[]")
|
|
isGlobal := ctx.FormBool("is_global")
|
|
|
|
ids := make([]int64, 0, len(packageIDs))
|
|
for _, idStr := range packageIDs {
|
|
var id int64
|
|
if _, err := fmt.Sscanf(idStr, "%d", &id); err == nil && id > 0 {
|
|
ids = append(ids, id)
|
|
}
|
|
}
|
|
|
|
if len(ids) == 0 {
|
|
ctx.Flash.Error(ctx.Tr("admin.packages.bulk.no_selection"))
|
|
ctx.JSONRedirect(setting.AppSubURL + "/-/admin/packages")
|
|
return
|
|
}
|
|
|
|
succeeded, failed, _ := packages_model.SetPackagesIsGlobal(ctx, ids, isGlobal)
|
|
|
|
if failed > 0 {
|
|
ctx.Flash.Warning(ctx.Tr("admin.packages.bulk.global.partial", succeeded, failed))
|
|
} else {
|
|
if isGlobal {
|
|
ctx.Flash.Success(ctx.Tr("admin.packages.bulk.global.enabled", succeeded))
|
|
} else {
|
|
ctx.Flash.Success(ctx.Tr("admin.packages.bulk.global.disabled", succeeded))
|
|
}
|
|
}
|
|
|
|
ctx.JSONRedirect(setting.AppSubURL + "/-/admin/packages")
|
|
}
|
|
|
|
// BulkAutoMatch automatically matches packages to repositories
|
|
func BulkAutoMatch(ctx *context.Context) {
|
|
packageIDs := ctx.FormStrings("ids[]")
|
|
|
|
ids := make([]int64, 0, len(packageIDs))
|
|
for _, idStr := range packageIDs {
|
|
var id int64
|
|
if _, err := fmt.Sscanf(idStr, "%d", &id); err == nil && id > 0 {
|
|
ids = append(ids, id)
|
|
}
|
|
}
|
|
|
|
if len(ids) == 0 {
|
|
ctx.Flash.Error(ctx.Tr("admin.packages.bulk.no_selection"))
|
|
ctx.JSONRedirect(setting.AppSubURL + "/-/admin/packages")
|
|
return
|
|
}
|
|
|
|
matched := 0
|
|
for _, id := range ids {
|
|
repoID, err := packages_model.AutoMatchPackageToRepository(ctx, id)
|
|
if err == nil && repoID > 0 {
|
|
matched++
|
|
}
|
|
}
|
|
|
|
if matched > 0 {
|
|
ctx.Flash.Success(ctx.Tr("admin.packages.bulk.automatch.success", matched))
|
|
} else {
|
|
ctx.Flash.Warning(ctx.Tr("admin.packages.bulk.automatch.none"))
|
|
}
|
|
|
|
ctx.JSONRedirect(setting.AppSubURL + "/-/admin/packages")
|
|
}
|
|
|
|
// BulkSetPrivate sets/unsets private flag on multiple packages
|
|
func BulkSetPrivate(ctx *context.Context) {
|
|
packageIDs := ctx.FormStrings("ids[]")
|
|
isPrivate := ctx.FormBool("is_private")
|
|
|
|
ids := make([]int64, 0, len(packageIDs))
|
|
for _, idStr := range packageIDs {
|
|
var id int64
|
|
if _, err := fmt.Sscanf(idStr, "%d", &id); err == nil && id > 0 {
|
|
ids = append(ids, id)
|
|
}
|
|
}
|
|
|
|
if len(ids) == 0 {
|
|
ctx.Flash.Error(ctx.Tr("admin.packages.bulk.no_selection"))
|
|
ctx.JSONRedirect(setting.AppSubURL + "/-/admin/packages")
|
|
return
|
|
}
|
|
|
|
succeeded := 0
|
|
for _, id := range ids {
|
|
if err := packages_model.SetPackageIsPrivate(ctx, id, isPrivate); err == nil {
|
|
succeeded++
|
|
}
|
|
}
|
|
|
|
if isPrivate {
|
|
ctx.Flash.Success(ctx.Tr("admin.packages.bulk.private.enabled", succeeded))
|
|
} else {
|
|
ctx.Flash.Success(ctx.Tr("admin.packages.bulk.private.disabled", succeeded))
|
|
}
|
|
|
|
ctx.JSONRedirect(setting.AppSubURL + "/-/admin/packages")
|
|
}
|
|
|
|
// SingleAutoMatch automatically matches a single package to a repository
|
|
func SingleAutoMatch(ctx *context.Context) {
|
|
packageID := ctx.FormInt64("id")
|
|
if packageID == 0 {
|
|
ctx.Flash.Error(ctx.Tr("admin.packages.automatch.invalid"))
|
|
ctx.JSONRedirect(setting.AppSubURL + "/-/admin/packages")
|
|
return
|
|
}
|
|
|
|
repoID, err := packages_model.AutoMatchPackageToRepository(ctx, packageID)
|
|
if err != nil {
|
|
ctx.Flash.Error(ctx.Tr("admin.packages.automatch.error"))
|
|
ctx.JSONRedirect(setting.AppSubURL + "/-/admin/packages")
|
|
return
|
|
}
|
|
|
|
if repoID > 0 {
|
|
ctx.Flash.Success(ctx.Tr("admin.packages.automatch.success"))
|
|
} else {
|
|
ctx.Flash.Warning(ctx.Tr("admin.packages.automatch.no_match"))
|
|
}
|
|
|
|
ctx.JSONRedirect(setting.AppSubURL + "/-/admin/packages")
|
|
}
|