code.gitea.io/gitea@v1.22.3/tests/integration/api_packages_chef_test.go (about) 1 // Copyright 2023 The Gitea Authors. All rights reserved. 2 // SPDX-License-Identifier: MIT 3 4 package integration 5 6 import ( 7 "archive/tar" 8 "bytes" 9 "compress/gzip" 10 "crypto" 11 "crypto/rand" 12 "crypto/rsa" 13 "crypto/sha1" 14 "crypto/sha256" 15 "crypto/x509" 16 "encoding/base64" 17 "encoding/pem" 18 "fmt" 19 "hash" 20 "math/big" 21 "mime/multipart" 22 "net/http" 23 "path" 24 "strings" 25 "testing" 26 "time" 27 28 "code.gitea.io/gitea/models/db" 29 "code.gitea.io/gitea/models/packages" 30 "code.gitea.io/gitea/models/unittest" 31 user_model "code.gitea.io/gitea/models/user" 32 chef_module "code.gitea.io/gitea/modules/packages/chef" 33 "code.gitea.io/gitea/modules/setting" 34 chef_router "code.gitea.io/gitea/routers/api/packages/chef" 35 "code.gitea.io/gitea/tests" 36 37 "github.com/stretchr/testify/assert" 38 ) 39 40 func TestPackageChef(t *testing.T) { 41 defer tests.PrepareTestEnv(t)() 42 43 user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) 44 45 privPem := `-----BEGIN RSA PRIVATE KEY----- 46 MIIEpQIBAAKCAQEAtWp2PZz4TSU5A6ixw41HdbfBuGJwPuTtrsdoUf0DQ0/DJBNP 47 qOCBAgEu6ZdUqIbWJ5Da+nevjtncy5hENdi6XrXjyzlUxghMuXjE5SeLGpgfQvkq 48 bTkYaFpMe8PTzNeze3fei8+Eu6mzeb6g1GrqXznuPIc7bNss0w5iX9RiBM9dWPuX 49 onx9xSEy0LYqJm7yXmshNe1aRwkjG/y5C26BzBFnMKp9YRTua0DO1WqLNhcaRnda 50 lIFYouDNVTbwxSlYL16bZVoebqzZvLGrPvZJkPuCu6vH9brvOuYo0q8hLVNkBeXc 51 imRpsDjLhQYzEJjoMTbaiVGnjBky+PWNiofJnwIDAQABAoIBAQCotF1KxLt/ejr/ 52 9ROCh9JJXV3v6tL5GgkSPOv9Oq2bHgSZer/cixJNW+5VWd5nbiSe3K1WuJBw5pbW 53 Wj4sWORPiRRR+3mjQzqeS/nGJDTOwWJo9K8IrUzOVhLEEYLX/ksxaXJyT8PehFyb 54 vbNwdhCIB6ZNcXDItTWE+95twWJ5lxAIj2dNwZZni3UkwwjYnCnqFtvHCKOg0NH2 55 RjQcFYmu3fncNeqLezUSdVyRyXxSCHsUdlYeX/e44StCnXdrmLUHlb2P27ZVdPGh 56 SW7qTUPpmJKekYiRPOpTLj+ZKXIsANkyWO+7dVtZLBm5bIyAsmp0W/DmK+wRsejj 57 alFbIsh5AoGBANJr7HSG695wkfn+kvu/V8qHbt+KDv4WjWHjGRsUqvxoHOUNkQmW 58 vZWdk4gjHYn1l+QHWmoOE3AgyqtCZ4bFILkZPLN/F8Mh3+r4B0Ac4biJJt7XGMNQ 59 Nv4wsk7TR7CCARsjO7GP1PT60hpjMvYmc1E36gNM7QIZE9jBE+L8eWYtAoGBANy2 60 JOAWf+QeBlur6o9feH76cEmpQzUUq4Lj9mmnXgIirSsFoBnDb8VA6Ws+ltL9U9H2 61 vaCoaTyi9twW9zWj+Ywg2mVR5nlSAPfdlTWS1GLUbDotlj5apc/lvnGuNlWzN+I4 62 Tu64hhgBXqGvRZ0o7HzFodqRAkpVXp6CQCqBM7p7AoGAIgO0K3oL8t87ma/fTra1 63 mFWgRJ5qogQ/Qo2VZ11F7ptd4GD7CxPE/cSFLsKOadi7fu75XJ994OhMGrcXSR/g 64 lEtSFqn6y15UdgU2FtUUX+I72FXo+Nmkqh5xFHDu68d4Kkzdv2xCvn81K3LRsByz 65 E3P4biQnQ+mN3cIIVu79KNkCgYEAm6uctrEn4y2KLn5DInyj8GuTZ2ELFhVOIzPG 66 SR7TH451tTJyiblezDHMcOfkWUx0IlN1zCr8jtgiZXmNQzg0erFxWKU7ebZtGGYh 67 J3g4dLx+2Unt/mzRJqFUgbnueOO/Nr+gbJ+ZdLUCmeeVohOLOTXrws0kYGl2Izab 68 K1+VrKECgYEAxQohoOegA0f4mofisXItbwwqTIX3bLpxBc4woa1sB4kjNrLo4slc 69 qtWZGVlRxwBvQUg0cYj+xtr5nyBdHLy0qwX/kMq4GqQnvW6NqsbrP3MjCZ8NX/Sj 70 A2W0jx50Hs/XNw6IZFLYgWVoOzCaD+jYFpHhzUZyQD6/rYhwhHrNQmU= 71 -----END RSA PRIVATE KEY-----` 72 73 tmp, _ := pem.Decode([]byte(privPem)) 74 privKey, _ := x509.ParsePKCS1PrivateKey(tmp.Bytes) 75 76 pubPem := `-----BEGIN PUBLIC KEY----- 77 MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtWp2PZz4TSU5A6ixw41H 78 dbfBuGJwPuTtrsdoUf0DQ0/DJBNPqOCBAgEu6ZdUqIbWJ5Da+nevjtncy5hENdi6 79 XrXjyzlUxghMuXjE5SeLGpgfQvkqbTkYaFpMe8PTzNeze3fei8+Eu6mzeb6g1Grq 80 XznuPIc7bNss0w5iX9RiBM9dWPuXonx9xSEy0LYqJm7yXmshNe1aRwkjG/y5C26B 81 zBFnMKp9YRTua0DO1WqLNhcaRndalIFYouDNVTbwxSlYL16bZVoebqzZvLGrPvZJ 82 kPuCu6vH9brvOuYo0q8hLVNkBeXcimRpsDjLhQYzEJjoMTbaiVGnjBky+PWNiofJ 83 nwIDAQAB 84 -----END PUBLIC KEY-----` 85 86 err := user_model.SetUserSetting(db.DefaultContext, user.ID, chef_module.SettingPublicPem, pubPem) 87 assert.NoError(t, err) 88 89 t.Run("Authenticate", func(t *testing.T) { 90 auth := &chef_router.Auth{} 91 92 t.Run("MissingUser", func(t *testing.T) { 93 defer tests.PrintCurrentTest(t)() 94 95 req := NewRequest(t, "POST", "/dummy") 96 u, err := auth.Verify(req.Request, nil, nil, nil) 97 assert.Nil(t, u) 98 assert.NoError(t, err) 99 }) 100 101 t.Run("NotExistingUser", func(t *testing.T) { 102 defer tests.PrintCurrentTest(t)() 103 104 req := NewRequest(t, "POST", "/dummy"). 105 SetHeader("X-Ops-Userid", "not-existing-user") 106 u, err := auth.Verify(req.Request, nil, nil, nil) 107 assert.Nil(t, u) 108 assert.Error(t, err) 109 }) 110 111 t.Run("Timestamp", func(t *testing.T) { 112 defer tests.PrintCurrentTest(t)() 113 114 req := NewRequest(t, "POST", "/dummy"). 115 SetHeader("X-Ops-Userid", user.Name) 116 u, err := auth.Verify(req.Request, nil, nil, nil) 117 assert.Nil(t, u) 118 assert.Error(t, err) 119 120 req.SetHeader("X-Ops-Timestamp", "2023-01-01T00:00:00Z") 121 u, err = auth.Verify(req.Request, nil, nil, nil) 122 assert.Nil(t, u) 123 assert.Error(t, err) 124 }) 125 126 t.Run("SigningVersion", func(t *testing.T) { 127 defer tests.PrintCurrentTest(t)() 128 129 req := NewRequest(t, "POST", "/dummy"). 130 SetHeader("X-Ops-Userid", user.Name). 131 SetHeader("X-Ops-Timestamp", time.Now().UTC().Format(time.RFC3339)) 132 u, err := auth.Verify(req.Request, nil, nil, nil) 133 assert.Nil(t, u) 134 assert.Error(t, err) 135 136 req.SetHeader("X-Ops-Sign", "version=none") 137 u, err = auth.Verify(req.Request, nil, nil, nil) 138 assert.Nil(t, u) 139 assert.Error(t, err) 140 141 req.SetHeader("X-Ops-Sign", "version=1.4") 142 u, err = auth.Verify(req.Request, nil, nil, nil) 143 assert.Nil(t, u) 144 assert.Error(t, err) 145 146 req.SetHeader("X-Ops-Sign", "version=1.0;algorithm=sha2") 147 u, err = auth.Verify(req.Request, nil, nil, nil) 148 assert.Nil(t, u) 149 assert.Error(t, err) 150 151 req.SetHeader("X-Ops-Sign", "version=1.0;algorithm=sha256") 152 u, err = auth.Verify(req.Request, nil, nil, nil) 153 assert.Nil(t, u) 154 assert.Error(t, err) 155 }) 156 157 t.Run("SignedHeaders", func(t *testing.T) { 158 defer tests.PrintCurrentTest(t)() 159 160 ts := time.Now().UTC().Format(time.RFC3339) 161 162 req := NewRequest(t, "POST", "/dummy"). 163 SetHeader("X-Ops-Userid", user.Name). 164 SetHeader("X-Ops-Timestamp", ts). 165 SetHeader("X-Ops-Sign", "version=1.0;algorithm=sha1"). 166 SetHeader("X-Ops-Content-Hash", "unused"). 167 SetHeader("X-Ops-Authorization-4", "dummy") 168 u, err := auth.Verify(req.Request, nil, nil, nil) 169 assert.Nil(t, u) 170 assert.Error(t, err) 171 172 signRequest := func(t *testing.T, rw *RequestWrapper, version string) { 173 req := rw.Request 174 username := req.Header.Get("X-Ops-Userid") 175 if version != "1.0" && version != "1.3" { 176 sum := sha1.Sum([]byte(username)) 177 username = base64.StdEncoding.EncodeToString(sum[:]) 178 } 179 180 req.Header.Set("X-Ops-Sign", "version="+version) 181 182 var data []byte 183 if version == "1.3" { 184 data = []byte(fmt.Sprintf( 185 "Method:%s\nPath:%s\nX-Ops-Content-Hash:%s\nX-Ops-Sign:version=%s\nX-Ops-Timestamp:%s\nX-Ops-UserId:%s\nX-Ops-Server-API-Version:%s", 186 req.Method, 187 path.Clean(req.URL.Path), 188 req.Header.Get("X-Ops-Content-Hash"), 189 version, 190 req.Header.Get("X-Ops-Timestamp"), 191 username, 192 req.Header.Get("X-Ops-Server-Api-Version"), 193 )) 194 } else { 195 sum := sha1.Sum([]byte(path.Clean(req.URL.Path))) 196 data = []byte(fmt.Sprintf( 197 "Method:%s\nHashed Path:%s\nX-Ops-Content-Hash:%s\nX-Ops-Timestamp:%s\nX-Ops-UserId:%s", 198 req.Method, 199 base64.StdEncoding.EncodeToString(sum[:]), 200 req.Header.Get("X-Ops-Content-Hash"), 201 req.Header.Get("X-Ops-Timestamp"), 202 username, 203 )) 204 } 205 206 for k := range req.Header { 207 if strings.HasPrefix(k, "X-Ops-Authorization-") { 208 req.Header.Del(k) 209 } 210 } 211 212 var signature []byte 213 if version == "1.3" || version == "1.2" { 214 var h hash.Hash 215 var ch crypto.Hash 216 if version == "1.3" { 217 h = sha256.New() 218 ch = crypto.SHA256 219 } else { 220 h = sha1.New() 221 ch = crypto.SHA1 222 } 223 h.Write(data) 224 225 signature, _ = rsa.SignPKCS1v15(rand.Reader, privKey, ch, h.Sum(nil)) 226 } else { 227 c := new(big.Int).SetBytes(data) 228 m := new(big.Int).Exp(c, privKey.D, privKey.N) 229 230 signature = m.Bytes() 231 } 232 233 enc := base64.StdEncoding.EncodeToString(signature) 234 235 const chunkSize = 60 236 chunks := make([]string, 0, (len(enc)-1)/chunkSize+1) 237 currentLen := 0 238 currentStart := 0 239 for i := range enc { 240 if currentLen == chunkSize { 241 chunks = append(chunks, enc[currentStart:i]) 242 currentLen = 0 243 currentStart = i 244 } 245 currentLen++ 246 } 247 chunks = append(chunks, enc[currentStart:]) 248 249 for i, chunk := range chunks { 250 req.Header.Set(fmt.Sprintf("X-Ops-Authorization-%d", i+1), chunk) 251 } 252 } 253 254 for _, v := range []string{"1.0", "1.1", "1.2", "1.3"} { 255 t.Run(v, func(t *testing.T) { 256 defer tests.PrintCurrentTest(t)() 257 258 signRequest(t, req, v) 259 u, err = auth.Verify(req.Request, nil, nil, nil) 260 assert.NotNil(t, u) 261 assert.NoError(t, err) 262 }) 263 } 264 }) 265 }) 266 267 packageName := "test" 268 packageVersion := "1.0.1" 269 packageDescription := "Test Description" 270 packageAuthor := "KN4CK3R" 271 272 root := fmt.Sprintf("/api/packages/%s/chef/api/v1", user.Name) 273 274 uploadPackage := func(t *testing.T, version string, expectedStatus int) { 275 var body bytes.Buffer 276 mpw := multipart.NewWriter(&body) 277 part, _ := mpw.CreateFormFile("tarball", fmt.Sprintf("%s.tar.gz", version)) 278 zw := gzip.NewWriter(part) 279 tw := tar.NewWriter(zw) 280 281 content := `{"name":"` + packageName + `","version":"` + version + `","description":"` + packageDescription + `","maintainer":"` + packageAuthor + `"}` 282 283 hdr := &tar.Header{ 284 Name: packageName + "/metadata.json", 285 Mode: 0o600, 286 Size: int64(len(content)), 287 } 288 tw.WriteHeader(hdr) 289 tw.Write([]byte(content)) 290 291 tw.Close() 292 zw.Close() 293 mpw.Close() 294 295 req := NewRequestWithBody(t, "POST", root+"/cookbooks", &body). 296 SetHeader("Content-Type", mpw.FormDataContentType()). 297 AddBasicAuth(user.Name) 298 MakeRequest(t, req, expectedStatus) 299 } 300 301 t.Run("Upload", func(t *testing.T) { 302 defer tests.PrintCurrentTest(t)() 303 304 req := NewRequestWithBody(t, "POST", root+"/cookbooks", bytes.NewReader([]byte{})) 305 MakeRequest(t, req, http.StatusUnauthorized) 306 307 uploadPackage(t, packageVersion, http.StatusCreated) 308 309 pvs, err := packages.GetVersionsByPackageType(db.DefaultContext, user.ID, packages.TypeChef) 310 assert.NoError(t, err) 311 assert.Len(t, pvs, 1) 312 313 pd, err := packages.GetPackageDescriptor(db.DefaultContext, pvs[0]) 314 assert.NoError(t, err) 315 assert.NotNil(t, pd.SemVer) 316 assert.IsType(t, &chef_module.Metadata{}, pd.Metadata) 317 assert.Equal(t, packageName, pd.Package.Name) 318 assert.Equal(t, packageVersion, pd.Version.Version) 319 320 pfs, err := packages.GetFilesByVersionID(db.DefaultContext, pvs[0].ID) 321 assert.NoError(t, err) 322 assert.Len(t, pfs, 1) 323 assert.Equal(t, fmt.Sprintf("%s.tar.gz", packageVersion), pfs[0].Name) 324 assert.True(t, pfs[0].IsLead) 325 326 uploadPackage(t, packageVersion, http.StatusConflict) 327 }) 328 329 t.Run("Download", func(t *testing.T) { 330 defer tests.PrintCurrentTest(t)() 331 332 req := NewRequest(t, "GET", fmt.Sprintf("%s/cookbooks/%s/versions/%s/download", root, packageName, packageVersion)) 333 MakeRequest(t, req, http.StatusOK) 334 }) 335 336 t.Run("Universe", func(t *testing.T) { 337 defer tests.PrintCurrentTest(t)() 338 339 req := NewRequest(t, "GET", root+"/universe") 340 resp := MakeRequest(t, req, http.StatusOK) 341 342 type VersionInfo struct { 343 LocationType string `json:"location_type"` 344 LocationPath string `json:"location_path"` 345 DownloadURL string `json:"download_url"` 346 Dependencies map[string]string `json:"dependencies"` 347 } 348 349 var result map[string]map[string]*VersionInfo 350 DecodeJSON(t, resp, &result) 351 352 assert.Len(t, result, 1) 353 assert.Contains(t, result, packageName) 354 355 versions := result[packageName] 356 357 assert.Len(t, versions, 1) 358 assert.Contains(t, versions, packageVersion) 359 360 info := versions[packageVersion] 361 362 assert.Equal(t, "opscode", info.LocationType) 363 assert.Equal(t, setting.AppURL+root[1:], info.LocationPath) 364 assert.Equal(t, fmt.Sprintf("%s%s/cookbooks/%s/versions/%s/download", setting.AppURL, root[1:], packageName, packageVersion), info.DownloadURL) 365 }) 366 367 t.Run("Search", func(t *testing.T) { 368 defer tests.PrintCurrentTest(t)() 369 370 cases := []struct { 371 Query string 372 Start int 373 Items int 374 ExpectedTotal int 375 ExpectedResults int 376 }{ 377 {"", 0, 0, 1, 1}, 378 {"", 0, 10, 1, 1}, 379 {"gitea", 0, 10, 0, 0}, 380 {"test", 0, 10, 1, 1}, 381 {"test", 1, 10, 1, 0}, 382 } 383 384 type Item struct { 385 CookbookName string `json:"cookbook_name"` 386 CookbookMaintainer string `json:"cookbook_maintainer"` 387 CookbookDescription string `json:"cookbook_description"` 388 Cookbook string `json:"cookbook"` 389 } 390 391 type Result struct { 392 Start int `json:"start"` 393 Total int `json:"total"` 394 Items []*Item `json:"items"` 395 } 396 397 for i, c := range cases { 398 req := NewRequest(t, "GET", fmt.Sprintf("%s/search?q=%s&start=%d&items=%d", root, c.Query, c.Start, c.Items)). 399 AddBasicAuth(user.Name) 400 resp := MakeRequest(t, req, http.StatusOK) 401 402 var result Result 403 DecodeJSON(t, resp, &result) 404 405 assert.Equal(t, c.ExpectedTotal, result.Total, "case %d: unexpected total hits", i) 406 assert.Len(t, result.Items, c.ExpectedResults, "case %d: unexpected result count", i) 407 408 if len(result.Items) == 1 { 409 item := result.Items[0] 410 assert.Equal(t, packageName, item.CookbookName) 411 assert.Equal(t, packageAuthor, item.CookbookMaintainer) 412 assert.Equal(t, packageDescription, item.CookbookDescription) 413 assert.Equal(t, fmt.Sprintf("%s%s/cookbooks/%s", setting.AppURL, root[1:], packageName), item.Cookbook) 414 } 415 } 416 }) 417 418 t.Run("EnumeratePackages", func(t *testing.T) { 419 defer tests.PrintCurrentTest(t)() 420 421 cases := []struct { 422 Sort string 423 Start int 424 Items int 425 ExpectedTotal int 426 ExpectedResults int 427 }{ 428 {"", 0, 0, 1, 1}, 429 {"", 0, 10, 1, 1}, 430 {"RECENTLY_ADDED", 0, 10, 1, 1}, 431 {"RECENTLY_UPDATED", 0, 10, 1, 1}, 432 {"", 1, 10, 1, 0}, 433 } 434 435 type Item struct { 436 CookbookName string `json:"cookbook_name"` 437 CookbookMaintainer string `json:"cookbook_maintainer"` 438 CookbookDescription string `json:"cookbook_description"` 439 Cookbook string `json:"cookbook"` 440 } 441 442 type Result struct { 443 Start int `json:"start"` 444 Total int `json:"total"` 445 Items []*Item `json:"items"` 446 } 447 448 for i, c := range cases { 449 req := NewRequest(t, "GET", fmt.Sprintf("%s/cookbooks?start=%d&items=%d&sort=%s", root, c.Start, c.Items, c.Sort)). 450 AddBasicAuth(user.Name) 451 resp := MakeRequest(t, req, http.StatusOK) 452 453 var result Result 454 DecodeJSON(t, resp, &result) 455 456 assert.Equal(t, c.ExpectedTotal, result.Total, "case %d: unexpected total hits", i) 457 assert.Len(t, result.Items, c.ExpectedResults, "case %d: unexpected result count", i) 458 459 if len(result.Items) == 1 { 460 item := result.Items[0] 461 assert.Equal(t, packageName, item.CookbookName) 462 assert.Equal(t, packageAuthor, item.CookbookMaintainer) 463 assert.Equal(t, packageDescription, item.CookbookDescription) 464 assert.Equal(t, fmt.Sprintf("%s%s/cookbooks/%s", setting.AppURL, root[1:], packageName), item.Cookbook) 465 } 466 } 467 }) 468 469 t.Run("PackageMetadata", func(t *testing.T) { 470 defer tests.PrintCurrentTest(t)() 471 472 req := NewRequest(t, "GET", fmt.Sprintf("%s/cookbooks/%s", root, packageName)) 473 resp := MakeRequest(t, req, http.StatusOK) 474 475 type Result struct { 476 Name string `json:"name"` 477 Maintainer string `json:"maintainer"` 478 Description string `json:"description"` 479 Category string `json:"category"` 480 LatestVersion string `json:"latest_version"` 481 SourceURL string `json:"source_url"` 482 CreatedAt time.Time `json:"created_at"` 483 UpdatedAt time.Time `json:"updated_at"` 484 Deprecated bool `json:"deprecated"` 485 Versions []string `json:"versions"` 486 } 487 488 var result Result 489 DecodeJSON(t, resp, &result) 490 491 versionURL := fmt.Sprintf("%s%s/cookbooks/%s/versions/%s", setting.AppURL, root[1:], packageName, packageVersion) 492 493 assert.Equal(t, packageName, result.Name) 494 assert.Equal(t, packageAuthor, result.Maintainer) 495 assert.Equal(t, packageDescription, result.Description) 496 assert.Equal(t, versionURL, result.LatestVersion) 497 assert.False(t, result.Deprecated) 498 assert.ElementsMatch(t, []string{versionURL}, result.Versions) 499 }) 500 501 t.Run("PackageVersionMetadata", func(t *testing.T) { 502 defer tests.PrintCurrentTest(t)() 503 504 req := NewRequest(t, "GET", fmt.Sprintf("%s/cookbooks/%s/versions/%s", root, packageName, packageVersion)) 505 resp := MakeRequest(t, req, http.StatusOK) 506 507 type Result struct { 508 Version string `json:"version"` 509 TarballFileSize int64 `json:"tarball_file_size"` 510 PublishedAt time.Time `json:"published_at"` 511 Cookbook string `json:"cookbook"` 512 File string `json:"file"` 513 License string `json:"license"` 514 Dependencies map[string]string `json:"dependencies"` 515 } 516 517 var result Result 518 DecodeJSON(t, resp, &result) 519 520 packageURL := fmt.Sprintf("%s%s/cookbooks/%s", setting.AppURL, root[1:], packageName) 521 522 assert.Equal(t, packageVersion, result.Version) 523 assert.Equal(t, packageURL, result.Cookbook) 524 assert.Equal(t, fmt.Sprintf("%s/versions/%s/download", packageURL, packageVersion), result.File) 525 }) 526 527 t.Run("Delete", func(t *testing.T) { 528 uploadPackage(t, "1.0.2", http.StatusCreated) 529 uploadPackage(t, "1.0.3", http.StatusCreated) 530 531 t.Run("Version", func(t *testing.T) { 532 defer tests.PrintCurrentTest(t)() 533 534 req := NewRequest(t, "DELETE", fmt.Sprintf("%s/cookbooks/%s/versions/%s", root, packageName, "1.0.2")) 535 MakeRequest(t, req, http.StatusUnauthorized) 536 537 req = NewRequest(t, "DELETE", fmt.Sprintf("%s/cookbooks/%s/versions/%s", root, packageName, "1.0.2")). 538 AddBasicAuth(user.Name) 539 MakeRequest(t, req, http.StatusOK) 540 541 pv, err := packages.GetVersionByNameAndVersion(db.DefaultContext, user.ID, packages.TypeChef, packageName, "1.0.2") 542 assert.Nil(t, pv) 543 assert.Error(t, err) 544 }) 545 546 t.Run("Package", func(t *testing.T) { 547 defer tests.PrintCurrentTest(t)() 548 549 req := NewRequest(t, "DELETE", fmt.Sprintf("%s/cookbooks/%s", root, packageName)) 550 MakeRequest(t, req, http.StatusUnauthorized) 551 552 req = NewRequest(t, "DELETE", fmt.Sprintf("%s/cookbooks/%s", root, packageName)). 553 AddBasicAuth(user.Name) 554 MakeRequest(t, req, http.StatusOK) 555 556 pvs, err := packages.GetVersionsByPackageType(db.DefaultContext, user.ID, packages.TypeChef) 557 assert.NoError(t, err) 558 assert.Empty(t, pvs) 559 }) 560 }) 561 }