code.gitea.io/gitea@v1.21.7/routers/web/shared/packages/packages.go (about)

     1  // Copyright 2022 The Gitea Authors. All rights reserved.
     2  // SPDX-License-Identifier: MIT
     3  
     4  package packages
     5  
     6  import (
     7  	"fmt"
     8  	"net/http"
     9  	"time"
    10  
    11  	"code.gitea.io/gitea/models/db"
    12  	packages_model "code.gitea.io/gitea/models/packages"
    13  	user_model "code.gitea.io/gitea/models/user"
    14  	"code.gitea.io/gitea/modules/base"
    15  	"code.gitea.io/gitea/modules/context"
    16  	"code.gitea.io/gitea/modules/log"
    17  	"code.gitea.io/gitea/modules/util"
    18  	"code.gitea.io/gitea/modules/web"
    19  	"code.gitea.io/gitea/services/forms"
    20  	cargo_service "code.gitea.io/gitea/services/packages/cargo"
    21  	container_service "code.gitea.io/gitea/services/packages/container"
    22  )
    23  
    24  func SetPackagesContext(ctx *context.Context, owner *user_model.User) {
    25  	pcrs, err := packages_model.GetCleanupRulesByOwner(ctx, owner.ID)
    26  	if err != nil {
    27  		ctx.ServerError("GetCleanupRulesByOwner", err)
    28  		return
    29  	}
    30  
    31  	ctx.Data["CleanupRules"] = pcrs
    32  }
    33  
    34  func SetRuleAddContext(ctx *context.Context) {
    35  	setRuleEditContext(ctx, nil)
    36  }
    37  
    38  func SetRuleEditContext(ctx *context.Context, owner *user_model.User) {
    39  	pcr := getCleanupRuleByContext(ctx, owner)
    40  	if pcr == nil {
    41  		return
    42  	}
    43  
    44  	setRuleEditContext(ctx, pcr)
    45  }
    46  
    47  func setRuleEditContext(ctx *context.Context, pcr *packages_model.PackageCleanupRule) {
    48  	ctx.Data["IsEditRule"] = pcr != nil
    49  
    50  	if pcr == nil {
    51  		pcr = &packages_model.PackageCleanupRule{}
    52  	}
    53  	ctx.Data["CleanupRule"] = pcr
    54  	ctx.Data["AvailableTypes"] = packages_model.TypeList
    55  }
    56  
    57  func PerformRuleAddPost(ctx *context.Context, owner *user_model.User, redirectURL string, template base.TplName) {
    58  	performRuleEditPost(ctx, owner, nil, redirectURL, template)
    59  }
    60  
    61  func PerformRuleEditPost(ctx *context.Context, owner *user_model.User, redirectURL string, template base.TplName) {
    62  	pcr := getCleanupRuleByContext(ctx, owner)
    63  	if pcr == nil {
    64  		return
    65  	}
    66  
    67  	form := web.GetForm(ctx).(*forms.PackageCleanupRuleForm)
    68  
    69  	if form.Action == "remove" {
    70  		if err := packages_model.DeleteCleanupRuleByID(ctx, pcr.ID); err != nil {
    71  			ctx.ServerError("DeleteCleanupRuleByID", err)
    72  			return
    73  		}
    74  
    75  		ctx.Flash.Success(ctx.Tr("packages.owner.settings.cleanuprules.success.delete"))
    76  		ctx.Redirect(redirectURL)
    77  	} else {
    78  		performRuleEditPost(ctx, owner, pcr, redirectURL, template)
    79  	}
    80  }
    81  
    82  func performRuleEditPost(ctx *context.Context, owner *user_model.User, pcr *packages_model.PackageCleanupRule, redirectURL string, template base.TplName) {
    83  	isEditRule := pcr != nil
    84  
    85  	if pcr == nil {
    86  		pcr = &packages_model.PackageCleanupRule{}
    87  	}
    88  
    89  	form := web.GetForm(ctx).(*forms.PackageCleanupRuleForm)
    90  
    91  	pcr.Enabled = form.Enabled
    92  	pcr.OwnerID = owner.ID
    93  	pcr.KeepCount = form.KeepCount
    94  	pcr.KeepPattern = form.KeepPattern
    95  	pcr.RemoveDays = form.RemoveDays
    96  	pcr.RemovePattern = form.RemovePattern
    97  	pcr.MatchFullName = form.MatchFullName
    98  
    99  	ctx.Data["IsEditRule"] = isEditRule
   100  	ctx.Data["CleanupRule"] = pcr
   101  	ctx.Data["AvailableTypes"] = packages_model.TypeList
   102  
   103  	if ctx.HasError() {
   104  		ctx.HTML(http.StatusOK, template)
   105  		return
   106  	}
   107  
   108  	if isEditRule {
   109  		if err := packages_model.UpdateCleanupRule(ctx, pcr); err != nil {
   110  			ctx.ServerError("UpdateCleanupRule", err)
   111  			return
   112  		}
   113  	} else {
   114  		pcr.Type = packages_model.Type(form.Type)
   115  
   116  		if has, err := packages_model.HasOwnerCleanupRuleForPackageType(ctx, owner.ID, pcr.Type); err != nil {
   117  			ctx.ServerError("HasOwnerCleanupRuleForPackageType", err)
   118  			return
   119  		} else if has {
   120  			ctx.Data["Err_Type"] = true
   121  			ctx.HTML(http.StatusOK, template)
   122  			return
   123  		}
   124  
   125  		var err error
   126  		if pcr, err = packages_model.InsertCleanupRule(ctx, pcr); err != nil {
   127  			ctx.ServerError("InsertCleanupRule", err)
   128  			return
   129  		}
   130  	}
   131  
   132  	ctx.Flash.Success(ctx.Tr("packages.owner.settings.cleanuprules.success.update"))
   133  	ctx.Redirect(fmt.Sprintf("%s/rules/%d", redirectURL, pcr.ID))
   134  }
   135  
   136  func SetRulePreviewContext(ctx *context.Context, owner *user_model.User) {
   137  	pcr := getCleanupRuleByContext(ctx, owner)
   138  	if pcr == nil {
   139  		return
   140  	}
   141  
   142  	if err := pcr.CompiledPattern(); err != nil {
   143  		ctx.ServerError("CompiledPattern", err)
   144  		return
   145  	}
   146  
   147  	olderThan := time.Now().AddDate(0, 0, -pcr.RemoveDays)
   148  
   149  	packages, err := packages_model.GetPackagesByType(ctx, pcr.OwnerID, pcr.Type)
   150  	if err != nil {
   151  		ctx.ServerError("GetPackagesByType", err)
   152  		return
   153  	}
   154  
   155  	versionsToRemove := make([]*packages_model.PackageDescriptor, 0, 10)
   156  
   157  	for _, p := range packages {
   158  		pvs, _, err := packages_model.SearchVersions(ctx, &packages_model.PackageSearchOptions{
   159  			PackageID:  p.ID,
   160  			IsInternal: util.OptionalBoolFalse,
   161  			Sort:       packages_model.SortCreatedDesc,
   162  			Paginator:  db.NewAbsoluteListOptions(pcr.KeepCount, 200),
   163  		})
   164  		if err != nil {
   165  			ctx.ServerError("SearchVersions", err)
   166  			return
   167  		}
   168  		for _, pv := range pvs {
   169  			if skip, err := container_service.ShouldBeSkipped(ctx, pcr, p, pv); err != nil {
   170  				ctx.ServerError("ShouldBeSkipped", err)
   171  				return
   172  			} else if skip {
   173  				continue
   174  			}
   175  
   176  			toMatch := pv.LowerVersion
   177  			if pcr.MatchFullName {
   178  				toMatch = p.LowerName + "/" + pv.LowerVersion
   179  			}
   180  
   181  			if pcr.KeepPatternMatcher != nil && pcr.KeepPatternMatcher.MatchString(toMatch) {
   182  				continue
   183  			}
   184  			if pv.CreatedUnix.AsLocalTime().After(olderThan) {
   185  				continue
   186  			}
   187  			if pcr.RemovePatternMatcher != nil && !pcr.RemovePatternMatcher.MatchString(toMatch) {
   188  				continue
   189  			}
   190  
   191  			pd, err := packages_model.GetPackageDescriptor(ctx, pv)
   192  			if err != nil {
   193  				ctx.ServerError("GetPackageDescriptor", err)
   194  				return
   195  			}
   196  			versionsToRemove = append(versionsToRemove, pd)
   197  		}
   198  	}
   199  
   200  	ctx.Data["CleanupRule"] = pcr
   201  	ctx.Data["VersionsToRemove"] = versionsToRemove
   202  }
   203  
   204  func getCleanupRuleByContext(ctx *context.Context, owner *user_model.User) *packages_model.PackageCleanupRule {
   205  	id := ctx.FormInt64("id")
   206  	if id == 0 {
   207  		id = ctx.ParamsInt64("id")
   208  	}
   209  
   210  	pcr, err := packages_model.GetCleanupRuleByID(ctx, id)
   211  	if err != nil {
   212  		if err == packages_model.ErrPackageCleanupRuleNotExist {
   213  			ctx.NotFound("", err)
   214  		} else {
   215  			ctx.ServerError("GetCleanupRuleByID", err)
   216  		}
   217  		return nil
   218  	}
   219  
   220  	if pcr != nil && pcr.OwnerID == owner.ID {
   221  		return pcr
   222  	}
   223  
   224  	ctx.NotFound("", fmt.Errorf("PackageCleanupRule[%v] not associated to owner %v", id, owner))
   225  
   226  	return nil
   227  }
   228  
   229  func InitializeCargoIndex(ctx *context.Context, owner *user_model.User) {
   230  	err := cargo_service.InitializeIndexRepository(ctx, owner, owner)
   231  	if err != nil {
   232  		log.Error("InitializeIndexRepository failed: %v", err)
   233  		ctx.Flash.Error(ctx.Tr("packages.owner.settings.cargo.initialize.error", err))
   234  	} else {
   235  		ctx.Flash.Success(ctx.Tr("packages.owner.settings.cargo.initialize.success"))
   236  	}
   237  }
   238  
   239  func RebuildCargoIndex(ctx *context.Context, owner *user_model.User) {
   240  	err := cargo_service.RebuildIndex(ctx, owner, owner)
   241  	if err != nil {
   242  		log.Error("RebuildIndex failed: %v", err)
   243  		ctx.Flash.Error(ctx.Tr("packages.owner.settings.cargo.rebuild.error", err))
   244  	} else {
   245  		ctx.Flash.Success(ctx.Tr("packages.owner.settings.cargo.rebuild.success"))
   246  	}
   247  }