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 }