diff --git a/.github/workflows/sca-scan.yml b/.github/workflows/sca-scan.yml index 986c6e9..30d262e 100644 --- a/.github/workflows/sca-scan.yml +++ b/.github/workflows/sca-scan.yml @@ -16,7 +16,6 @@ jobs: env: SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }} with: - args: --file=Contentstack.Management.Core/obj/project.assets.json --fail-on=all - json: true + args: --file=Contentstack.Management.Core/obj/project.assets.json --fail-on=all --json-file-output=snyk.json continue-on-error: true - uses: contentstack/sca-policy@main diff --git a/Contentstack.Management.Core.Tests/Helpers/PersonalizeTestHelper.cs b/Contentstack.Management.Core.Tests/Helpers/PersonalizeTestHelper.cs new file mode 100644 index 0000000..1b7bbe3 --- /dev/null +++ b/Contentstack.Management.Core.Tests/Helpers/PersonalizeTestHelper.cs @@ -0,0 +1,170 @@ +using System; +using System.Net.Http; +using System.Net.Http.Headers; +using System.Text; +using System.Text.Json; +using System.Text.Json.Nodes; +using System.Threading.Tasks; +using Contentstack.Management.Core.Endpoints; + +namespace Contentstack.Management.Core.Tests.Helpers +{ + /// + /// Raw-HTTP client for the Contentstack Personalize Management API, used only by + /// integration tests. The core SDK has no Project/Audience/Experience wrapper classes + /// (Personalize is a separate product surface from Content Management), so this helper + /// drives Personalize directly to auto-provision real Variant Group/Variant data on a + /// stack instead of relying on a hardcoded variant UID. + /// + /// NOTE(verify at implementation time): exact endpoint paths, payload shapes, and + /// required headers below are best-effort based on Contentstack's published Personalize + /// API conventions and have not been exercised against a live org in this change. + /// Confirm against https://www.contentstack.com/docs/developers/apis/personalize-management-api + /// before relying on this in CI, and adjust the marked TODO(verify) spots as needed. + /// + internal class PersonalizeTestHelper + { + private readonly HttpClient _httpClient; + private readonly string _baseUrl; + private readonly string _organizationUid; + + internal PersonalizeTestHelper(string authtoken, string organizationUid, string region = "na") + { + if (string.IsNullOrEmpty(authtoken)) + { + throw new ArgumentException("authtoken is required", nameof(authtoken)); + } + if (string.IsNullOrEmpty(organizationUid)) + { + throw new ArgumentException("organizationUid is required", nameof(organizationUid)); + } + + _organizationUid = organizationUid; + _baseUrl = Endpoint.GetContentstackEndpoint(region, "personalizeManagement").TrimEnd('/'); + + _httpClient = new HttpClient(new LoggingHttpHandler()) + { + Timeout = TimeSpan.FromSeconds(30) + }; + _httpClient.DefaultRequestHeaders.Add("authtoken", authtoken); + _httpClient.DefaultRequestHeaders.Add("organization_uid", organizationUid); + } + + /// + /// Creates a Personalize project connected to the given stack, so that Audiences/ + /// Experiences created within it can auto-provision Variant Groups on that stack. + /// TODO(verify): confirm path is "/projects" and payload shape against Personalize docs. + /// + internal async Task CreateProjectAsync(string stackApiKey, string projectName) + { + var payload = new JsonObject + { + ["name"] = projectName, + ["connectedStackApiKey"] = stackApiKey + }; + + var project = await PostAsync("/projects", payload, null); + return project?["uid"]?.ToString(); + } + + /// + /// Returns the uid of an existing audience on the project if one is found, otherwise + /// creates a new default audience and returns its uid. + /// TODO(verify): confirm paths "/audiences" (GET list / POST create) and payload shape. + /// + internal async Task GetOrCreateDefaultAudienceAsync(string projectUid, string audienceName) + { + var existing = await GetAsync("/audiences", projectUid); + var audiences = existing?["audiences"]?.AsArray(); + if (audiences != null && audiences.Count > 0) + { + return audiences[0]?["uid"]?.ToString(); + } + + var payload = new JsonObject + { + ["name"] = audienceName, + ["definition"] = new JsonObject + { + ["rules"] = new JsonArray(), + ["operator"] = "and" + } + }; + + var audience = await PostAsync("/audiences", payload, projectUid); + return audience?["uid"]?.ToString(); + } + + /// + /// Creates an Experience linked to the given audience. In the real product, creating + /// an Experience on a stack-connected project auto-provisions a Variant Group (and its + /// Variants) on the Content Management side of that stack. + /// TODO(verify): confirm path "/experiences" and payload shape (variant count/short_uids). + /// + internal async Task CreateExperienceAsync(string projectUid, string audienceUid, string experienceName) + { + var payload = new JsonObject + { + ["name"] = experienceName, + ["audiences"] = new JsonArray(audienceUid), + ["variants"] = new JsonArray(new JsonObject { ["name"] = "Variant A" }) + }; + + var experience = await PostAsync("/experiences", payload, projectUid); + return experience?["uid"]?.ToString(); + } + + /// Best-effort teardown of an experience created for a test run. Failures are non-fatal. + internal async Task DeleteExperienceAsync(string projectUid, string experienceUid) + { + await DeleteAsync($"/experiences/{experienceUid}", projectUid); + } + + /// Best-effort teardown of a project created for a test run. Failures are non-fatal. + internal async Task DeleteProjectAsync(string projectUid) + { + await DeleteAsync($"/projects/{projectUid}", null); + } + + private async Task PostAsync(string path, JsonObject payload, string projectUid) + { + using var request = new HttpRequestMessage(HttpMethod.Post, _baseUrl + path); + ApplyProjectHeader(request, projectUid); + request.Content = new StringContent(payload.ToJsonString(), Encoding.UTF8, "application/json"); + + using var response = await _httpClient.SendAsync(request); + string body = await response.Content.ReadAsStringAsync(); + response.EnsureSuccessStatusCode(); + + return string.IsNullOrEmpty(body) ? null : JsonNode.Parse(body)?.AsObject(); + } + + private async Task GetAsync(string path, string projectUid) + { + using var request = new HttpRequestMessage(HttpMethod.Get, _baseUrl + path); + ApplyProjectHeader(request, projectUid); + + using var response = await _httpClient.SendAsync(request); + string body = await response.Content.ReadAsStringAsync(); + response.EnsureSuccessStatusCode(); + + return string.IsNullOrEmpty(body) ? null : JsonNode.Parse(body)?.AsObject(); + } + + private async Task DeleteAsync(string path, string projectUid) + { + using var request = new HttpRequestMessage(HttpMethod.Delete, _baseUrl + path); + ApplyProjectHeader(request, projectUid); + using var response = await _httpClient.SendAsync(request); + response.EnsureSuccessStatusCode(); + } + + private static void ApplyProjectHeader(HttpRequestMessage request, string projectUid) + { + if (!string.IsNullOrEmpty(projectUid)) + { + request.Headers.TryAddWithoutValidation("x-project-uid", projectUid); + } + } + } +} diff --git a/Contentstack.Management.Core.Tests/IntegrationTest/Contentstack003_StackTest.cs b/Contentstack.Management.Core.Tests/IntegrationTest/Contentstack003_StackTest.cs index a9d5a4a..d0e9ac9 100644 --- a/Contentstack.Management.Core.Tests/IntegrationTest/Contentstack003_StackTest.cs +++ b/Contentstack.Management.Core.Tests/IntegrationTest/Contentstack003_StackTest.cs @@ -6,6 +6,7 @@ using Contentstack.Management.Core; using Contentstack.Management.Core.Exceptions; using Contentstack.Management.Core.Models; +using Contentstack.Management.Core.Models.Token; using Contentstack.Management.Core.Tests.Helpers; using Contentstack.Management.Core.Tests.Model; using Microsoft.VisualStudio.TestTools.UnitTesting; @@ -1191,5 +1192,71 @@ private static void AssertStackAuthError(Exception ex, string assertionName) } #endregion + + #region Global management token (shared infrastructure for variant/personalize tests) + + [TestMethod] + [DoNotParallelize] + public void Test065_Should_Create_Management_Token() + { + TestOutputLogger.LogContext("TestScenario", "CreateGlobalManagementToken"); + AssertStackApiKeyOrInconclusive(); + try + { + Stack stack = _client.Stack(Contentstack.Stack.APIKey); + var model = new ManagementTokenModel + { + Name = "DotNet SDK Integration Test Token", + Description = "Shared management token used by the .NET SDK integration test suite", + Scope = new List + { + new TokenScope + { + Module = "content_type", + ACL = new Dictionary { { "read", "true" }, { "write", "true" } } + }, + new TokenScope + { + Module = "entry", + ACL = new Dictionary { { "read", "true" }, { "write", "true" } } + }, + new TokenScope + { + Module = "asset", + ACL = new Dictionary { { "read", "true" }, { "write", "true" } } + }, + new TokenScope + { + Module = "environment", + ACL = new Dictionary { { "read", "true" }, { "write", "true" } } + }, + new TokenScope + { + Module = "taxonomy", + ACL = new Dictionary { { "read", "true" }, { "write", "true" } } + } + } + }; + + ContentstackResponse contentstackResponse = stack.ManagementTokens().Create(model); + + AssertLogger.IsTrue(contentstackResponse.IsSuccessStatusCode, $"Create management token failed: {contentstackResponse.OpenResponse()}", "CreateManagementTokenSuccess"); + + File.WriteAllText("./managementTokenInfo.txt", contentstackResponse.OpenResponse()); + + ManagementTokenResponse tokenResponse = contentstackResponse.OpenTResponse(); + AssertLogger.IsNotNull(tokenResponse.Token, "tokenResponse.Token"); + AssertLogger.IsNotNull(tokenResponse.Token.Uid, "tokenResponse.Token.Uid"); + AssertLogger.IsNotNull(tokenResponse.Token.Token, "tokenResponse.Token.Token"); + + TestOutputLogger.LogContext("ManagementTokenUid", tokenResponse.Token.Uid ?? ""); + } + catch (Exception e) + { + AssertLogger.Fail(e.Message); + } + } + + #endregion } } diff --git a/Contentstack.Management.Core.Tests/IntegrationTest/Contentstack021_EntryVariantTest.cs b/Contentstack.Management.Core.Tests/IntegrationTest/Contentstack021_EntryVariantTest.cs index afa6012..8cfa149 100644 --- a/Contentstack.Management.Core.Tests/IntegrationTest/Contentstack021_EntryVariantTest.cs +++ b/Contentstack.Management.Core.Tests/IntegrationTest/Contentstack021_EntryVariantTest.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using System.Net; +using System.Net.Http; using System.Threading; using System.Threading.Tasks; using Contentstack.Management.Core.Exceptions; @@ -38,6 +39,9 @@ public class Contentstack021_EntryVariantTest private static string _variantUid; private static string _variantGroupUid; + private const int VariantGroupPollTimeoutSeconds = 90; + private const int VariantGroupPollIntervalSeconds = 5; + #region Helper Methods /// @@ -235,17 +239,25 @@ public static void ClassCleanup() [TestInitialize] public void TestInitialize() { - // Read the API key from appSettings.json - string apiKey = Contentstack.Config["Contentstack:Stack:api_key"]; - - // Optional: Fallback to stackApiKey.txt if it's missing in appSettings.json - if (string.IsNullOrEmpty(apiKey)) + // Always use the dynamically-created stack shared by the rest of the suite + // (matches Contentstack012_ContentTypeTest.cs and friends) rather than the + // static Contentstack:Stack:api_key from appSettings.json. + StackResponse response = StackResponse.getStack(_client.serializer); + string apiKey = response.Stack.APIKey; + + string managementToken = null; + try { - StackResponse response = StackResponse.getStack(_client.serializer); - apiKey = response.Stack.APIKey; + managementToken = ManagementTokenResponse.getManagementToken(_client.serializer)?.Token?.Token; } - - _stack = _client.Stack(apiKey); + catch + { + // managementTokenInfo.txt missing (e.g. isolated test run) — fall back to session-token-only stack. + } + + _stack = string.IsNullOrEmpty(managementToken) + ? _client.Stack(apiKey) + : _client.Stack(apiKey, managementToken); } [TestMethod] @@ -254,21 +266,74 @@ public async System.Threading.Tasks.Task Test001_Ensure_Setup_Data() { TestOutputLogger.LogContext("TestScenario", "ProductBannerVariantLifecycle_Setup"); - // 1. Ensure Variant Group exists + // 1. Ensure a Variant Group (with real Variants) exists on the dynamic stack. var collection = new global::Contentstack.Management.Core.Queryable.ParameterCollection(); collection.Add("include_variant_info", "true"); collection.Add("include_variant_count", "true"); - var vgResponse = await _stack.VariantGroup().FindAsync(collection); - Console.WriteLine("Variant Groups Response: " + vgResponse.OpenResponse()); + async Task FindVariantGroupsAsync() + { + var response = await _stack.VariantGroup().FindAsync(collection); + Console.WriteLine("Variant Groups Response: " + response.OpenResponse()); + return response.OpenJsonObjectResponse()["variant_groups"]?.AsArray(); + } - var vgJsonObject = vgResponse.OpenJsonObjectResponse(); - var groups = vgJsonObject["variant_groups"]?.AsArray(); + var groups = await FindVariantGroupsAsync(); if (groups == null || groups.Count == 0) { - Assert.Inconclusive("No variant groups found in the stack. Create one to run EntryVariant tests. Response was: " + vgResponse.OpenResponse()); - return; + // No pre-existing variant group — drive the Personalize API to create a + // project/audience/experience on this stack, which auto-provisions a real + // Variant Group + Variants on the Content Management side. + try + { + var personalize = new PersonalizeTestHelper(_client.contentstackOptions.Authtoken, Contentstack.Organization.Uid); + long runId = DateTimeOffset.UtcNow.ToUnixTimeSeconds(); + + string projectUid = await personalize.CreateProjectAsync(_stack.APIKey, $"DotNet SDK Integration Test Project {runId}"); + string audienceUid = await personalize.GetOrCreateDefaultAudienceAsync(projectUid, $"DotNet SDK Test Audience {runId}"); + string experienceUid = await personalize.CreateExperienceAsync(projectUid, audienceUid, $"DotNet SDK Test Experience {runId}"); + + TestOutputLogger.LogContext("PersonalizeProjectUid", projectUid ?? ""); + TestOutputLogger.LogContext("PersonalizeAudienceUid", audienceUid ?? ""); + TestOutputLogger.LogContext("PersonalizeExperienceUid", experienceUid ?? ""); + + var pollDeadline = DateTime.UtcNow.AddSeconds(VariantGroupPollTimeoutSeconds); + while (DateTime.UtcNow < pollDeadline) + { + groups = await FindVariantGroupsAsync(); + if (groups != null && groups.Count > 0) + { + break; + } + await Task.Delay(TimeSpan.FromSeconds(VariantGroupPollIntervalSeconds)); + } + + if (groups == null || groups.Count == 0) + { + // Personalize setup succeeded but the CMS side never produced a + // Variant Group in time — a real product/integration bug, not an + // environment precondition, so fail loudly instead of silently + // degrading to a hardcoded UID like this test used to. + Assert.Fail( + $"Personalize project/audience/experience were created (project={projectUid}, " + + $"audience={audienceUid}, experience={experienceUid}) but no Variant Group appeared " + + $"on the stack within {VariantGroupPollTimeoutSeconds}s."); + return; + } + } + catch (HttpRequestException ex) when (ex.StatusCode == HttpStatusCode.Forbidden || ex.StatusCode == HttpStatusCode.Unauthorized) + { + Assert.Inconclusive("Personalize is not enabled/entitled for this organization; cannot drive dynamic variant setup. " + ex.Message); + return; + } + catch (Exception ex) + { + // Environment/transient issue (network, unexpected schema, etc.) — don't + // block the rest of the suite on this, but make it loudly diagnosable. + Assert.Inconclusive("Personalize-driven variant setup failed unexpectedly: " + ex.Message); + return; + } } _variantGroupUid = groups[0]?["uid"]?.ToString(); @@ -289,9 +354,8 @@ public async System.Threading.Tasks.Task Test001_Ensure_Setup_Data() if (string.IsNullOrEmpty(_variantUid)) { - // Fallback to demo UIDs if none are returned by the API so the test doesn't skip - _variantUid = "cs372c03252b23f623"; - Console.WriteLine("Warning: The variant group had no variants. Using a hardcoded variant UID for testing: " + _variantUid); + Assert.Fail("Variant Group was found/created but contains no variants."); + return; } TestOutputLogger.LogContext("VariantGroup", _variantGroupUid); diff --git a/Contentstack.Management.Core.Tests/IntegrationTest/Contentstack022_VariantGroupTest.cs b/Contentstack.Management.Core.Tests/IntegrationTest/Contentstack022_VariantGroupTest.cs index c17aabf..3d617d2 100644 --- a/Contentstack.Management.Core.Tests/IntegrationTest/Contentstack022_VariantGroupTest.cs +++ b/Contentstack.Management.Core.Tests/IntegrationTest/Contentstack022_VariantGroupTest.cs @@ -194,13 +194,24 @@ public static async Task ClassInitialize(TestContext context) // Test001 / Test003 happened to run after the guard was evaluated. try { - string apiKey = Contentstack.Config["Contentstack:Stack:api_key"]; - if (string.IsNullOrEmpty(apiKey)) + // Always use the dynamically-created stack shared by the rest of the suite, + // rather than the static Contentstack:Stack:api_key from appSettings.json. + StackResponse stackResp = StackResponse.getStack(_client.serializer); + string apiKey = stackResp.Stack.APIKey; + + string managementToken = null; + try + { + managementToken = ManagementTokenResponse.getManagementToken(_client.serializer)?.Token?.Token; + } + catch { - StackResponse stackResp = StackResponse.getStack(_client.serializer); - apiKey = stackResp.Stack.APIKey; + // managementTokenInfo.txt missing (e.g. isolated test run) — fall back to session-token-only stack. } - var setupStack = _client.Stack(apiKey); + + var setupStack = string.IsNullOrEmpty(managementToken) + ? _client.Stack(apiKey) + : _client.Stack(apiKey, managementToken); // Variant groups var vgResponse = await setupStack.VariantGroup().FindAsync(); @@ -245,17 +256,25 @@ public static void ClassCleanup() [TestInitialize] public void TestInitialize() { - // Read the API key from appSettings.json - string apiKey = Contentstack.Config["Contentstack:Stack:api_key"]; - - // Optional: Fallback to stackApiKey.txt if it's missing in appSettings.json - if (string.IsNullOrEmpty(apiKey)) + // Always use the dynamically-created stack shared by the rest of the suite + // (matches Contentstack012_ContentTypeTest.cs and friends) rather than the + // static Contentstack:Stack:api_key from appSettings.json. + StackResponse response = StackResponse.getStack(_client.serializer); + string apiKey = response.Stack.APIKey; + + string managementToken = null; + try { - StackResponse response = StackResponse.getStack(_client.serializer); - apiKey = response.Stack.APIKey; + managementToken = ManagementTokenResponse.getManagementToken(_client.serializer)?.Token?.Token; } - - _stack = _client.Stack(apiKey); + catch + { + // managementTokenInfo.txt missing (e.g. isolated test run) — fall back to session-token-only stack. + } + + _stack = string.IsNullOrEmpty(managementToken) + ? _client.Stack(apiKey) + : _client.Stack(apiKey, managementToken); } #region Positive Test Cases diff --git a/Contentstack.Management.Core.Tests/IntegrationTest/Contentstack024_ManagementTokenTest.cs b/Contentstack.Management.Core.Tests/IntegrationTest/Contentstack024_ManagementTokenTest.cs new file mode 100644 index 0000000..9b3d05a --- /dev/null +++ b/Contentstack.Management.Core.Tests/IntegrationTest/Contentstack024_ManagementTokenTest.cs @@ -0,0 +1,489 @@ +using System; +using System.Collections.Generic; +using System.Net; +using System.Threading.Tasks; +using Contentstack.Management.Core.Exceptions; +using Contentstack.Management.Core.Models; +using Contentstack.Management.Core.Models.Token; +using Contentstack.Management.Core.Tests.Helpers; +using Contentstack.Management.Core.Tests.Model; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System.Text.Json.Nodes; + +namespace Contentstack.Management.Core.Tests.IntegrationTest +{ + [TestClass] + public class Contentstack024_ManagementTokenTest + { + private static ContentstackClient _client; + private Stack _stack; + private string _managementTokenUid; + private ManagementTokenModel _testTokenModel; + + private const string NonExistentTokenUid = "blt00000000000000000000"; + + [ClassInitialize] + public static void ClassInitialize(TestContext context) + { + _client = Contentstack.CreateAuthenticatedClient(); + } + + [ClassCleanup] + public static void ClassCleanup() + { + try { _client?.Logout(); } catch { } + _client = null; + } + + [TestInitialize] + public void Initialize() + { + StackResponse response = StackResponse.getStack(_client.serializer); + _stack = _client.Stack(response.Stack.APIKey); + + _testTokenModel = BuildValidTokenModel("Test Management Token"); + } + + private static ManagementTokenModel BuildValidTokenModel(string name) + { + return new ManagementTokenModel + { + Name = name, + Description = "Integration test management token", + Scope = new List + { + new TokenScope + { + Module = "content_type", + ACL = new Dictionary { { "read", "true" }, { "write", "true" } } + }, + new TokenScope + { + Module = "entry", + ACL = new Dictionary { { "read", "true" }, { "write", "true" } } + } + } + }; + } + + [TestMethod] + [DoNotParallelize] + public void Test001_Should_Create_Management_Token() + { + TestOutputLogger.LogContext("TestScenario", "Test001_Should_Create_Management_Token"); + try + { + ContentstackResponse response = _stack.ManagementTokens().Create(_testTokenModel); + + AssertLogger.IsTrue(response.IsSuccessStatusCode, $"Create management token failed: {response.OpenResponse()}", "CreateManagementTokenSuccess"); + + var responseObject = response.OpenJsonObjectResponse(); + AssertLogger.IsNotNull(responseObject["token"], "Response should contain token object"); + + var tokenData = responseObject["token"] as JsonObject; + AssertLogger.IsNotNull(tokenData["uid"], "Token should have UID"); + AssertLogger.AreEqual(_testTokenModel.Name, tokenData["name"]?.ToString(), "Token name should match", "TokenName"); + + // Proves the JSON-casing fix: a "Scope"-cased payload would previously have been + // silently dropped by the API, leaving this field empty/missing. + var scope = tokenData["scope"] as JsonArray; + AssertLogger.IsNotNull(scope, "Token should have scope"); + AssertLogger.IsTrue(scope.Count == _testTokenModel.Scope.Count, "Scope module count should round-trip", "ScopeRoundTrip"); + + _managementTokenUid = tokenData["uid"]?.ToString(); + AssertLogger.IsNotNull(_managementTokenUid, "Management token UID should not be null"); + + TestOutputLogger.LogContext("ManagementTokenUid", _managementTokenUid ?? ""); + } + catch (Exception ex) + { + AssertLogger.Fail("Create management token test failed", ex.Message); + } + } + + [TestMethod] + [DoNotParallelize] + public async Task Test002_Should_Create_Management_Token_Async() + { + TestOutputLogger.LogContext("TestScenario", "Test002_Should_Create_Management_Token_Async"); + try + { + var model = BuildValidTokenModel("Async Test Management Token"); + ContentstackResponse response = await _stack.ManagementTokens().CreateAsync(model); + + AssertLogger.IsTrue(response.IsSuccessStatusCode, $"Async create management token failed: {response.OpenResponse()}", "AsyncCreateSuccess"); + + var responseObject = response.OpenJsonObjectResponse(); + var tokenData = responseObject["token"] as JsonObject; + AssertLogger.IsNotNull(tokenData["uid"], "Token should have UID"); + + string asyncTokenUid = tokenData["uid"]?.ToString(); + TestOutputLogger.LogContext("AsyncCreatedTokenUid", asyncTokenUid ?? ""); + + if (!string.IsNullOrEmpty(asyncTokenUid)) + { + await _stack.ManagementTokens(asyncTokenUid).DeleteAsync(); + } + } + catch (Exception ex) + { + AssertLogger.Fail("Async create management token test failed", ex.Message); + } + } + + [TestMethod] + [DoNotParallelize] + public void Test003_Should_Fetch_Management_Token() + { + TestOutputLogger.LogContext("TestScenario", "Test003_Should_Fetch_Management_Token"); + try + { + if (string.IsNullOrEmpty(_managementTokenUid)) + { + Test001_Should_Create_Management_Token(); + } + + ContentstackResponse response = _stack.ManagementTokens(_managementTokenUid).Fetch(); + + AssertLogger.IsTrue(response.IsSuccessStatusCode, $"Fetch management token failed: {response.OpenResponse()}", "FetchSuccess"); + + var responseObject = response.OpenJsonObjectResponse(); + var tokenData = responseObject["token"] as JsonObject; + AssertLogger.AreEqual(_managementTokenUid, tokenData["uid"]?.ToString(), "Token UID should match", "TokenUid"); + } + catch (Exception ex) + { + AssertLogger.Fail($"Fetch management token test failed: {ex.Message}"); + } + } + + [TestMethod] + [DoNotParallelize] + public async Task Test004_Should_Fetch_Management_Token_Async() + { + TestOutputLogger.LogContext("TestScenario", "Test004_Should_Fetch_Management_Token_Async"); + try + { + if (string.IsNullOrEmpty(_managementTokenUid)) + { + Test001_Should_Create_Management_Token(); + } + + ContentstackResponse response = await _stack.ManagementTokens(_managementTokenUid).FetchAsync(); + + AssertLogger.IsTrue(response.IsSuccessStatusCode, $"Async fetch management token failed: {response.OpenResponse()}", "AsyncFetchSuccess"); + + var responseObject = response.OpenJsonObjectResponse(); + var tokenData = responseObject["token"] as JsonObject; + AssertLogger.AreEqual(_managementTokenUid, tokenData["uid"]?.ToString(), "Token UID should match", "TokenUid"); + } + catch (Exception ex) + { + AssertLogger.Fail($"Async fetch management token test failed: {ex.Message}"); + } + } + + [TestMethod] + [DoNotParallelize] + public void Test005_Should_Update_Management_Token() + { + TestOutputLogger.LogContext("TestScenario", "Test005_Should_Update_Management_Token"); + try + { + if (string.IsNullOrEmpty(_managementTokenUid)) + { + Test001_Should_Create_Management_Token(); + } + + var updateModel = BuildValidTokenModel("Updated Test Management Token"); + ContentstackResponse response = _stack.ManagementTokens(_managementTokenUid).Update(updateModel); + + AssertLogger.IsTrue(response.IsSuccessStatusCode, $"Update management token failed: {response.OpenResponse()}", "UpdateSuccess"); + + var responseObject = response.OpenJsonObjectResponse(); + var tokenData = responseObject["token"] as JsonObject; + AssertLogger.AreEqual(_managementTokenUid, tokenData["uid"]?.ToString(), "Token UID should match", "TokenUid"); + AssertLogger.AreEqual(updateModel.Name, tokenData["name"]?.ToString(), "Updated token name should match", "UpdatedTokenName"); + } + catch (Exception ex) + { + AssertLogger.Fail($"Update management token test failed: {ex.Message}"); + } + } + + [TestMethod] + [DoNotParallelize] + public async Task Test006_Should_Update_Management_Token_Async() + { + TestOutputLogger.LogContext("TestScenario", "Test006_Should_Update_Management_Token_Async"); + try + { + if (string.IsNullOrEmpty(_managementTokenUid)) + { + Test001_Should_Create_Management_Token(); + } + + var updateModel = BuildValidTokenModel("Async Updated Test Management Token"); + ContentstackResponse response = await _stack.ManagementTokens(_managementTokenUid).UpdateAsync(updateModel); + + AssertLogger.IsTrue(response.IsSuccessStatusCode, $"Async update management token failed: {response.OpenResponse()}", "AsyncUpdateSuccess"); + + var responseObject = response.OpenJsonObjectResponse(); + var tokenData = responseObject["token"] as JsonObject; + AssertLogger.AreEqual(updateModel.Name, tokenData["name"]?.ToString(), "Updated token name should match", "UpdatedTokenName"); + } + catch (Exception ex) + { + AssertLogger.Fail($"Async update management token test failed: {ex.Message}"); + } + } + + [TestMethod] + [DoNotParallelize] + public void Test007_Should_Query_All_Management_Tokens() + { + TestOutputLogger.LogContext("TestScenario", "Test007_Should_Query_All_Management_Tokens"); + try + { + if (string.IsNullOrEmpty(_managementTokenUid)) + { + Test001_Should_Create_Management_Token(); + } + + ContentstackResponse response = _stack.ManagementTokens().Query().Find(); + + AssertLogger.IsTrue(response.IsSuccessStatusCode, $"Query management tokens failed: {response.OpenResponse()}", "QuerySuccess"); + + var responseObject = response.OpenJsonObjectResponse(); + AssertLogger.IsNotNull(responseObject["tokens"], "Response should contain tokens array"); + + var tokens = responseObject["tokens"] as JsonArray; + AssertLogger.IsTrue(tokens.Count > 0, "Should have at least one management token", "TokensCountGreaterThanZero"); + + bool foundTestToken = false; + foreach (var token in tokens) + { + if (token["uid"]?.ToString() == _managementTokenUid) + { + foundTestToken = true; + break; + } + } + + AssertLogger.IsTrue(foundTestToken, "Test token should be found in query results", "TestTokenFoundInQuery"); + } + catch (Exception ex) + { + AssertLogger.Fail($"Query management tokens test failed: {ex.Message}"); + } + } + + [TestMethod] + [DoNotParallelize] + public async Task Test008_Should_Query_All_Management_Tokens_Async() + { + TestOutputLogger.LogContext("TestScenario", "Test008_Should_Query_All_Management_Tokens_Async"); + try + { + if (string.IsNullOrEmpty(_managementTokenUid)) + { + Test001_Should_Create_Management_Token(); + } + + ContentstackResponse response = await _stack.ManagementTokens().Query().FindAsync(); + + AssertLogger.IsTrue(response.IsSuccessStatusCode, $"Async query management tokens failed: {response.OpenResponse()}", "AsyncQuerySuccess"); + + var responseObject = response.OpenJsonObjectResponse(); + var tokens = responseObject["tokens"] as JsonArray; + AssertLogger.IsTrue(tokens.Count > 0, "Should have at least one management token", "AsyncTokensCount"); + } + catch (Exception ex) + { + AssertLogger.Fail($"Async query management tokens test failed: {ex.Message}"); + } + } + + [TestMethod] + [DoNotParallelize] + public void Test009_Should_Delete_Management_Token() + { + TestOutputLogger.LogContext("TestScenario", "Test009_Should_Delete_Management_Token"); + try + { + ContentstackResponse createResponse = _stack.ManagementTokens().Create(BuildValidTokenModel("Delete Test Management Token")); + AssertLogger.IsTrue(createResponse.IsSuccessStatusCode, "Setup create for delete test failed"); + var tokenData = createResponse.OpenJsonObjectResponse()["token"] as JsonObject; + string tokenUidToDelete = tokenData["uid"]?.ToString(); + AssertLogger.IsNotNull(tokenUidToDelete, "Should have a valid token UID to delete"); + + ContentstackResponse response = _stack.ManagementTokens(tokenUidToDelete).Delete(); + + AssertLogger.IsTrue(response.IsSuccessStatusCode, $"Delete management token failed: {response.OpenResponse()}", "DeleteSuccess"); + + AssertLogger.ThrowsContentstackError( + () => _stack.ManagementTokens(tokenUidToDelete).Fetch(), + "FetchDeletedManagementToken", + HttpStatusCode.NotFound, + (HttpStatusCode)422); + } + catch (Exception ex) + { + AssertLogger.Fail("Delete management token test failed", ex.Message); + } + } + + [TestMethod] + [DoNotParallelize] + public async Task Test010_Should_Delete_Management_Token_Async() + { + TestOutputLogger.LogContext("TestScenario", "Test010_Should_Delete_Management_Token_Async"); + try + { + ContentstackResponse createResponse = await _stack.ManagementTokens().CreateAsync(BuildValidTokenModel("Async Delete Test Management Token")); + AssertLogger.IsTrue(createResponse.IsSuccessStatusCode, "Setup create for async delete test failed"); + var tokenData = createResponse.OpenJsonObjectResponse()["token"] as JsonObject; + string tokenUidToDelete = tokenData["uid"]?.ToString(); + AssertLogger.IsNotNull(tokenUidToDelete, "Should have a valid token UID to delete"); + + ContentstackResponse response = await _stack.ManagementTokens(tokenUidToDelete).DeleteAsync(); + + AssertLogger.IsTrue(response.IsSuccessStatusCode, $"Async delete management token failed: {response.OpenResponse()}", "AsyncDeleteSuccess"); + + await AssertLogger.ThrowsContentstackErrorAsync( + async () => await _stack.ManagementTokens(tokenUidToDelete).FetchAsync(), + "AsyncFetchDeletedManagementToken", + HttpStatusCode.NotFound, + (HttpStatusCode)422); + } + catch (Exception ex) + { + AssertLogger.Fail("Async delete management token test failed", ex.Message); + } + } + + #region Negative-path tests + + [TestMethod] + [DoNotParallelize] + public void Test011_Should_Fail_Create_With_Null_Model() + { + TestOutputLogger.LogContext("TestScenario", "Test011_Should_Fail_Create_With_Null_Model"); + AssertLogger.ThrowsException( + () => _stack.ManagementTokens().Create(null), + "CreateWithNullModel"); + } + + [TestMethod] + [DoNotParallelize] + public async Task Test012_Should_Fail_Create_With_Null_Model_Async() + { + TestOutputLogger.LogContext("TestScenario", "Test012_Should_Fail_Create_With_Null_Model_Async"); + await AssertLogger.ThrowsExceptionAsync( + () => _stack.ManagementTokens().CreateAsync(null), + "CreateWithNullModelAsync"); + } + + [TestMethod] + [DoNotParallelize] + public void Test013_Should_Fail_Fetch_With_Null_Uid() + { + TestOutputLogger.LogContext("TestScenario", "Test013_Should_Fail_Fetch_With_Null_Uid"); + AssertLogger.ThrowsException( + () => _stack.ManagementTokens(null).Fetch(), + "FetchWithNullUid"); + } + + [TestMethod] + [DoNotParallelize] + public void Test014_Should_Fail_Fetch_With_Empty_Uid() + { + TestOutputLogger.LogContext("TestScenario", "Test014_Should_Fail_Fetch_With_Empty_Uid"); + AssertLogger.ThrowsException( + () => _stack.ManagementTokens("").Fetch(), + "FetchWithEmptyUid"); + } + + [TestMethod] + [DoNotParallelize] + public void Test015_Should_Fail_Fetch_NonExistent_Token() + { + TestOutputLogger.LogContext("TestScenario", "Test015_Should_Fail_Fetch_NonExistent_Token"); + AssertLogger.ThrowsContentstackError( + () => _stack.ManagementTokens(NonExistentTokenUid).Fetch(), + "FetchNonExistentToken", + HttpStatusCode.NotFound, + (HttpStatusCode)422); + } + + [TestMethod] + [DoNotParallelize] + public async Task Test016_Should_Fail_Fetch_NonExistent_Token_Async() + { + TestOutputLogger.LogContext("TestScenario", "Test016_Should_Fail_Fetch_NonExistent_Token_Async"); + await AssertLogger.ThrowsContentstackErrorAsync( + async () => await _stack.ManagementTokens(NonExistentTokenUid).FetchAsync(), + "FetchNonExistentTokenAsync", + HttpStatusCode.NotFound, + (HttpStatusCode)422); + } + + [TestMethod] + [DoNotParallelize] + public void Test017_Should_Fail_Update_With_Null_Model() + { + TestOutputLogger.LogContext("TestScenario", "Test017_Should_Fail_Update_With_Null_Model"); + AssertLogger.ThrowsException( + () => _stack.ManagementTokens(NonExistentTokenUid).Update(null), + "UpdateWithNullModel"); + } + + [TestMethod] + [DoNotParallelize] + public void Test018_Should_Fail_Update_NonExistent_Token() + { + TestOutputLogger.LogContext("TestScenario", "Test018_Should_Fail_Update_NonExistent_Token"); + var model = BuildValidTokenModel("Update Non Existent"); + AssertLogger.ThrowsContentstackError( + () => _stack.ManagementTokens(NonExistentTokenUid).Update(model), + "UpdateNonExistentToken", + HttpStatusCode.NotFound, + (HttpStatusCode)422); + } + + [TestMethod] + [DoNotParallelize] + public void Test019_Should_Fail_Delete_NonExistent_Token() + { + TestOutputLogger.LogContext("TestScenario", "Test019_Should_Fail_Delete_NonExistent_Token"); + AssertLogger.ThrowsContentstackError( + () => _stack.ManagementTokens(NonExistentTokenUid).Delete(), + "DeleteNonExistentToken", + HttpStatusCode.NotFound, + (HttpStatusCode)422); + } + + [TestMethod] + [DoNotParallelize] + public void Test020_Should_Fail_When_Stack_Api_Key_Missing() + { + TestOutputLogger.LogContext("TestScenario", "Test020_Should_Fail_When_Stack_Api_Key_Missing"); + var stackWithNoApiKey = _client.Stack(); + AssertLogger.ThrowsException( + () => stackWithNoApiKey.ManagementTokens(), + "ManagementTokensWithMissingApiKey"); + } + + [TestMethod] + [DoNotParallelize] + public void Test021_Should_Fail_Delete_With_Empty_Uid() + { + TestOutputLogger.LogContext("TestScenario", "Test021_Should_Fail_Delete_With_Empty_Uid"); + AssertLogger.ThrowsException( + () => _stack.ManagementTokens("").Delete(), + "DeleteWithEmptyUid"); + } + + #endregion + } +} diff --git a/Contentstack.Management.Core.Tests/IntegrationTest/Contentstack999_LogoutTest.cs b/Contentstack.Management.Core.Tests/IntegrationTest/Contentstack999_LogoutTest.cs index 8e1614e..e59b29d 100644 --- a/Contentstack.Management.Core.Tests/IntegrationTest/Contentstack999_LogoutTest.cs +++ b/Contentstack.Management.Core.Tests/IntegrationTest/Contentstack999_LogoutTest.cs @@ -3,14 +3,254 @@ using System.Net.Http; using System.Threading.Tasks; using Contentstack.Management.Core.Exceptions; +using Contentstack.Management.Core.Models; using Contentstack.Management.Core.Tests.Helpers; +using Contentstack.Management.Core.Tests.Model; using Microsoft.VisualStudio.TestTools.UnitTesting; +using System.Text.Json.Nodes; namespace Contentstack.Management.Core.Tests.IntegrationTest { [TestClass] public class Contentstack999_LogoutTest { + /// + /// Wipes all content from the dynamically-created stack before the Logout-behavior + /// tests below run, using a dedicated client so it can't interfere with those tests' + /// assertions about Authtoken state. The stack itself is kept (no Stack.Delete() exists + /// in this SDK) — only its content is removed, via query-and-delete-everything-found + /// since content here was created by many independent test classes with no shared + /// tracked-UID list. + /// + [ClassInitialize] + public static async Task ClassInitialize(TestContext context) + { + ContentstackClient cleanupClient = null; + try + { + cleanupClient = Contentstack.CreateAuthenticatedClient(); + + StackResponse stackResponse = StackResponse.getStack(cleanupClient.serializer); + string apiKey = stackResponse.Stack.APIKey; + + string managementToken = null; + try + { + managementToken = ManagementTokenResponse.getManagementToken(cleanupClient.serializer)?.Token?.Token; + } + catch + { + // managementTokenInfo.txt missing — fall back to session-token-only stack. + } + + Stack stack = string.IsNullOrEmpty(managementToken) + ? cleanupClient.Stack(apiKey) + : cleanupClient.Stack(apiKey, managementToken); + + // Order matters: content types before taxonomies (taxonomies may be referenced + // by content type schema fields); management token deleted last (in case any + // step above ends up authenticated via it). + await CleanupAllContentTypes(stack); + await CleanupAllTaxonomies(stack); + await LogUncleanableVariantGroups(stack); + await CleanupAllAssets(stack); + await CleanupAllEnvironments(stack); + await CleanupAllReleases(stack); + await CleanupAllDeliveryTokens(stack); + await CleanupManagementToken(stack, managementToken); + } + catch (Exception ex) + { + Console.WriteLine($"Stack-wide cleanup failed unexpectedly: {ex.Message}"); + } + finally + { + try { cleanupClient?.Logout(); } catch { } + } + } + + private static async Task CleanupAllContentTypes(Stack stack) + { + try + { + // ContentType.Delete() cascade-deletes the content type's entries too, so a + // separate entry-deletion pass is unnecessary. + var response = await stack.ContentType().Query().FindAsync(); + var contentTypes = response.OpenJsonObjectResponse()["content_types"]?.AsArray(); + if (contentTypes == null) return; + + foreach (var ct in contentTypes) + { + string uid = ct?["uid"]?.ToString(); + if (string.IsNullOrEmpty(uid)) continue; + try { await stack.ContentType(uid).DeleteAsync(); } + catch (Exception ex) { Console.WriteLine($"Cleanup: failed to delete content type '{uid}': {ex.Message}"); } + } + } + catch (Exception ex) + { + Console.WriteLine($"Cleanup: failed to query content types: {ex.Message}"); + } + } + + private static async Task CleanupAllTaxonomies(Stack stack) + { + try + { + var response = await stack.Taxonomy().Query().FindAsync(); + var taxonomies = response.OpenJsonObjectResponse()["taxonomies"]?.AsArray(); + if (taxonomies == null) return; + + foreach (var taxonomy in taxonomies) + { + string uid = taxonomy?["uid"]?.ToString(); + if (string.IsNullOrEmpty(uid)) continue; + try { await stack.Taxonomy(uid).DeleteAsync(); } + catch (Exception ex) { Console.WriteLine($"Cleanup: failed to delete taxonomy '{uid}': {ex.Message}"); } + } + } + catch (Exception ex) + { + Console.WriteLine($"Cleanup: failed to query taxonomies: {ex.Message}"); + } + } + + /// + /// VariantGroup has no Delete API in this SDK (only Find/LinkContentTypes/ + /// UnlinkContentTypes) — these groups are provisioned by Personalize Experiences, + /// and this SDK has no Personalize wrapper either. Full cleanup of Personalize- + /// provisioned variant groups is a known limitation; this just logs what's left + /// behind so it's visible rather than silently incomplete. + /// + private static async Task LogUncleanableVariantGroups(Stack stack) + { + try + { + var response = await stack.VariantGroup().FindAsync(); + var groups = response.OpenJsonObjectResponse()["variant_groups"]?.AsArray(); + if (groups == null || groups.Count == 0) return; + + Console.WriteLine( + $"Cleanup: {groups.Count} variant group(s) remain on the stack and could not be " + + "deleted (VariantGroup has no Delete API in this SDK; these are Personalize-provisioned)."); + } + catch (Exception ex) + { + Console.WriteLine($"Cleanup: failed to query variant groups: {ex.Message}"); + } + } + + private static async Task CleanupAllAssets(Stack stack) + { + try + { + var response = await stack.Asset().Query().FindAsync(); + var assets = response.OpenJsonObjectResponse()["assets"]?.AsArray(); + if (assets == null) return; + + foreach (var asset in assets) + { + string uid = asset?["uid"]?.ToString(); + if (string.IsNullOrEmpty(uid)) continue; + try { await stack.Asset(uid).DeleteAsync(); } + catch (Exception ex) { Console.WriteLine($"Cleanup: failed to delete asset '{uid}': {ex.Message}"); } + } + } + catch (Exception ex) + { + Console.WriteLine($"Cleanup: failed to query assets: {ex.Message}"); + } + } + + private static async Task CleanupAllEnvironments(Stack stack) + { + try + { + var response = await stack.Environment().Query().FindAsync(); + var environments = response.OpenJsonObjectResponse()["environments"]?.AsArray(); + if (environments == null) return; + + foreach (var environment in environments) + { + string uid = environment?["uid"]?.ToString(); + if (string.IsNullOrEmpty(uid)) continue; + try { await stack.Environment(uid).DeleteAsync(); } + catch (Exception ex) { Console.WriteLine($"Cleanup: failed to delete environment '{uid}': {ex.Message}"); } + } + } + catch (Exception ex) + { + Console.WriteLine($"Cleanup: failed to query environments: {ex.Message}"); + } + } + + private static async Task CleanupAllReleases(Stack stack) + { + try + { + var response = await stack.Release().Query().FindAsync(); + var releases = response.OpenJsonObjectResponse()["releases"]?.AsArray(); + if (releases == null) return; + + foreach (var release in releases) + { + string uid = release?["uid"]?.ToString(); + if (string.IsNullOrEmpty(uid)) continue; + try { await stack.Release(uid).DeleteAsync(); } + catch (Exception ex) { Console.WriteLine($"Cleanup: failed to delete release '{uid}': {ex.Message}"); } + } + } + catch (Exception ex) + { + Console.WriteLine($"Cleanup: failed to query releases: {ex.Message}"); + } + } + + private static async Task CleanupAllDeliveryTokens(Stack stack) + { + try + { + var response = await stack.DeliveryToken().Query().FindAsync(); + var tokens = response.OpenJsonObjectResponse()["tokens"]?.AsArray(); + if (tokens == null) return; + + foreach (var token in tokens) + { + string uid = token?["uid"]?.ToString(); + if (string.IsNullOrEmpty(uid)) continue; + try { await stack.DeliveryToken(uid).DeleteAsync(); } + catch (Exception ex) { Console.WriteLine($"Cleanup: failed to delete delivery token '{uid}': {ex.Message}"); } + } + } + catch (Exception ex) + { + Console.WriteLine($"Cleanup: failed to query delivery tokens: {ex.Message}"); + } + } + + /// + /// Deletes the one global management token created for this run (see + /// Contentstack003_StackTest.Test065_Should_Create_Management_Token), last — in case + /// any prior cleanup step above ends up authenticated via this same token. + /// + private static async Task CleanupManagementToken(Stack stack, string managementToken) + { + if (string.IsNullOrEmpty(managementToken)) return; + + try + { + var tokenInfo = ManagementTokenResponse.getManagementToken(stack.client.SerializerOptions); + string uid = tokenInfo?.Token?.Uid; + if (string.IsNullOrEmpty(uid)) return; + + await stack.ManagementTokens(uid).DeleteAsync(); + } + catch (Exception ex) + { + Console.WriteLine($"Cleanup: failed to delete management token: {ex.Message}"); + } + } + private static ContentstackClient CreateClientWithLogging() { var handler = new LoggingHttpHandler(); diff --git a/Contentstack.Management.Core.Tests/Model/ManagementTokenTestModel.cs b/Contentstack.Management.Core.Tests/Model/ManagementTokenTestModel.cs new file mode 100644 index 0000000..191358a --- /dev/null +++ b/Contentstack.Management.Core.Tests/Model/ManagementTokenTestModel.cs @@ -0,0 +1,29 @@ +using System.IO; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Contentstack.Management.Core.Tests.Model +{ + public class ManagementTokenInfo + { + [JsonPropertyName("uid")] + public string Uid { get; set; } + + [JsonPropertyName("token")] + public string Token { get; set; } + + [JsonPropertyName("name")] + public string Name { get; set; } + } + + public class ManagementTokenResponse + { + public ManagementTokenInfo Token { get; set; } + + public static ManagementTokenResponse getManagementToken(JsonSerializerOptions options) + { + string response = File.ReadAllText("./managementTokenInfo.txt"); + return JsonSerializer.Deserialize(response, options); + } + } +} diff --git a/Contentstack.Management.Core/Models/Token/DeliveryTokenModel.cs b/Contentstack.Management.Core/Models/Token/DeliveryTokenModel.cs index 763e0c1..6d9fe53 100644 --- a/Contentstack.Management.Core/Models/Token/DeliveryTokenModel.cs +++ b/Contentstack.Management.Core/Models/Token/DeliveryTokenModel.cs @@ -10,7 +10,7 @@ public class ManagementTokenModel public string Name { get; set; } [JsonPropertyName("description")] public string Description { get; set; } - [JsonPropertyName("Scope")] + [JsonPropertyName("scope")] public List Scope { get; set; } [JsonPropertyName("expires_on")] public string ExpiresOn { get; set; } diff --git a/Contentstack.Management.Core/Models/Token/ManagementToken.cs b/Contentstack.Management.Core/Models/Token/ManagementToken.cs index 83f51b9..a1e5530 100644 --- a/Contentstack.Management.Core/Models/Token/ManagementToken.cs +++ b/Contentstack.Management.Core/Models/Token/ManagementToken.cs @@ -8,7 +8,7 @@ public class ManagementToken : BaseModel internal ManagementToken(Stack stack, string? uid = null) : base(stack, "token", uid) { - resourcePath = uid == null ? "/delivery_tokens" : $"/delivery_tokens/{uid}"; + resourcePath = uid == null ? "stacks/management_tokens" : $"stacks/management_tokens/{uid}"; } /// diff --git a/snyk.json b/snyk.json deleted file mode 100644 index 1c9c23a..0000000 --- a/snyk.json +++ /dev/null @@ -1,650 +0,0 @@ -[ - { - "vulnerabilities": [], - "ok": true, - "dependencyCount": 67, - "org": "contentstack-devex", - "policy": "# Snyk (https://snyk.io) policy file, patches or ignores known vulnerabilities.\nversion: v1.25.1\nignore: {}\npatch: {}\n", - "isPrivate": true, - "licensesPolicy": { - "severities": {}, - "orgLicenseRules": { - "AGPL-1.0": { - "licenseType": "AGPL-1.0", - "severity": "high", - "instructions": "" - }, - "AGPL-3.0": { - "licenseType": "AGPL-3.0", - "severity": "high", - "instructions": "" - }, - "Artistic-1.0": { - "licenseType": "Artistic-1.0", - "severity": "medium", - "instructions": "" - }, - "Artistic-2.0": { - "licenseType": "Artistic-2.0", - "severity": "medium", - "instructions": "" - }, - "CDDL-1.0": { - "licenseType": "CDDL-1.0", - "severity": "medium", - "instructions": "" - }, - "CPOL-1.02": { - "licenseType": "CPOL-1.02", - "severity": "high", - "instructions": "" - }, - "EPL-1.0": { - "licenseType": "EPL-1.0", - "severity": "medium", - "instructions": "" - }, - "GPL-2.0": { - "licenseType": "GPL-2.0", - "severity": "high", - "instructions": "" - }, - "GPL-3.0": { - "licenseType": "GPL-3.0", - "severity": "high", - "instructions": "" - }, - "LGPL-2.0": { - "licenseType": "LGPL-2.0", - "severity": "medium", - "instructions": "" - }, - "LGPL-2.1": { - "licenseType": "LGPL-2.1", - "severity": "medium", - "instructions": "" - }, - "LGPL-3.0": { - "licenseType": "LGPL-3.0", - "severity": "medium", - "instructions": "" - }, - "MPL-1.1": { - "licenseType": "MPL-1.1", - "severity": "medium", - "instructions": "" - }, - "MPL-2.0": { - "licenseType": "MPL-2.0", - "severity": "medium", - "instructions": "" - }, - "MS-RL": { - "licenseType": "MS-RL", - "severity": "medium", - "instructions": "" - }, - "SimPL-2.0": { - "licenseType": "SimPL-2.0", - "severity": "high", - "instructions": "" - } - } - }, - "packageManager": "nuget", - "ignoreSettings": { - "adminOnly": false, - "reasonRequired": false, - "disregardFilesystemIgnores": false - }, - "summary": "No known vulnerabilities", - "filesystemPolicy": false, - "uniqueCount": 0, - "targetFile": "Contentstack.Management.ASPNETCore/obj/project.assets.json", - "projectName": "contentstack-management-dotnet", - "foundProjectCount": 5, - "displayTargetFile": "Contentstack.Management.ASPNETCore/obj/project.assets.json", - "hasUnknownVersions": false, - "path": "/Users/om.pawar/Desktop/SDKs/contentstack-management-dotnet" - }, - { - "vulnerabilities": [], - "ok": true, - "dependencyCount": 121, - "org": "contentstack-devex", - "policy": "# Snyk (https://snyk.io) policy file, patches or ignores known vulnerabilities.\nversion: v1.25.1\nignore: {}\npatch: {}\n", - "isPrivate": true, - "licensesPolicy": { - "severities": {}, - "orgLicenseRules": { - "AGPL-1.0": { - "licenseType": "AGPL-1.0", - "severity": "high", - "instructions": "" - }, - "AGPL-3.0": { - "licenseType": "AGPL-3.0", - "severity": "high", - "instructions": "" - }, - "Artistic-1.0": { - "licenseType": "Artistic-1.0", - "severity": "medium", - "instructions": "" - }, - "Artistic-2.0": { - "licenseType": "Artistic-2.0", - "severity": "medium", - "instructions": "" - }, - "CDDL-1.0": { - "licenseType": "CDDL-1.0", - "severity": "medium", - "instructions": "" - }, - "CPOL-1.02": { - "licenseType": "CPOL-1.02", - "severity": "high", - "instructions": "" - }, - "EPL-1.0": { - "licenseType": "EPL-1.0", - "severity": "medium", - "instructions": "" - }, - "GPL-2.0": { - "licenseType": "GPL-2.0", - "severity": "high", - "instructions": "" - }, - "GPL-3.0": { - "licenseType": "GPL-3.0", - "severity": "high", - "instructions": "" - }, - "LGPL-2.0": { - "licenseType": "LGPL-2.0", - "severity": "medium", - "instructions": "" - }, - "LGPL-2.1": { - "licenseType": "LGPL-2.1", - "severity": "medium", - "instructions": "" - }, - "LGPL-3.0": { - "licenseType": "LGPL-3.0", - "severity": "medium", - "instructions": "" - }, - "MPL-1.1": { - "licenseType": "MPL-1.1", - "severity": "medium", - "instructions": "" - }, - "MPL-2.0": { - "licenseType": "MPL-2.0", - "severity": "medium", - "instructions": "" - }, - "MS-RL": { - "licenseType": "MS-RL", - "severity": "medium", - "instructions": "" - }, - "SimPL-2.0": { - "licenseType": "SimPL-2.0", - "severity": "high", - "instructions": "" - } - } - }, - "packageManager": "nuget", - "ignoreSettings": { - "adminOnly": false, - "reasonRequired": false, - "disregardFilesystemIgnores": false - }, - "summary": "No known vulnerabilities", - "filesystemPolicy": false, - "uniqueCount": 0, - "targetFile": "Contentstack.Management.Core.Tests/obj/project.assets.json", - "projectName": "contentstack-management-dotnet", - "foundProjectCount": 5, - "displayTargetFile": "Contentstack.Management.Core.Tests/obj/project.assets.json", - "hasUnknownVersions": false, - "path": "/Users/om.pawar/Desktop/SDKs/contentstack-management-dotnet" - }, - { - "vulnerabilities": [], - "ok": true, - "dependencyCount": 109, - "org": "contentstack-devex", - "policy": "# Snyk (https://snyk.io) policy file, patches or ignores known vulnerabilities.\nversion: v1.25.1\nignore: {}\npatch: {}\n", - "isPrivate": true, - "licensesPolicy": { - "severities": {}, - "orgLicenseRules": { - "AGPL-1.0": { - "licenseType": "AGPL-1.0", - "severity": "high", - "instructions": "" - }, - "AGPL-3.0": { - "licenseType": "AGPL-3.0", - "severity": "high", - "instructions": "" - }, - "Artistic-1.0": { - "licenseType": "Artistic-1.0", - "severity": "medium", - "instructions": "" - }, - "Artistic-2.0": { - "licenseType": "Artistic-2.0", - "severity": "medium", - "instructions": "" - }, - "CDDL-1.0": { - "licenseType": "CDDL-1.0", - "severity": "medium", - "instructions": "" - }, - "CPOL-1.02": { - "licenseType": "CPOL-1.02", - "severity": "high", - "instructions": "" - }, - "EPL-1.0": { - "licenseType": "EPL-1.0", - "severity": "medium", - "instructions": "" - }, - "GPL-2.0": { - "licenseType": "GPL-2.0", - "severity": "high", - "instructions": "" - }, - "GPL-3.0": { - "licenseType": "GPL-3.0", - "severity": "high", - "instructions": "" - }, - "LGPL-2.0": { - "licenseType": "LGPL-2.0", - "severity": "medium", - "instructions": "" - }, - "LGPL-2.1": { - "licenseType": "LGPL-2.1", - "severity": "medium", - "instructions": "" - }, - "LGPL-3.0": { - "licenseType": "LGPL-3.0", - "severity": "medium", - "instructions": "" - }, - "MPL-1.1": { - "licenseType": "MPL-1.1", - "severity": "medium", - "instructions": "" - }, - "MPL-2.0": { - "licenseType": "MPL-2.0", - "severity": "medium", - "instructions": "" - }, - "MS-RL": { - "licenseType": "MS-RL", - "severity": "medium", - "instructions": "" - }, - "SimPL-2.0": { - "licenseType": "SimPL-2.0", - "severity": "high", - "instructions": "" - } - } - }, - "packageManager": "nuget", - "ignoreSettings": { - "adminOnly": false, - "reasonRequired": false, - "disregardFilesystemIgnores": false - }, - "summary": "No known vulnerabilities", - "filesystemPolicy": false, - "uniqueCount": 0, - "targetFile": "Contentstack.Management.Core.Unit.Tests/obj/project.assets.json", - "projectName": "contentstack-management-dotnet", - "foundProjectCount": 5, - "displayTargetFile": "Contentstack.Management.Core.Unit.Tests/obj/project.assets.json", - "hasUnknownVersions": false, - "path": "/Users/om.pawar/Desktop/SDKs/contentstack-management-dotnet" - }, - { - "vulnerabilities": [], - "ok": true, - "dependencyCount": 63, - "org": "contentstack-devex", - "policy": "# Snyk (https://snyk.io) policy file, patches or ignores known vulnerabilities.\nversion: v1.25.1\nignore: {}\npatch: {}\n", - "isPrivate": true, - "licensesPolicy": { - "severities": {}, - "orgLicenseRules": { - "AGPL-1.0": { - "licenseType": "AGPL-1.0", - "severity": "high", - "instructions": "" - }, - "AGPL-3.0": { - "licenseType": "AGPL-3.0", - "severity": "high", - "instructions": "" - }, - "Artistic-1.0": { - "licenseType": "Artistic-1.0", - "severity": "medium", - "instructions": "" - }, - "Artistic-2.0": { - "licenseType": "Artistic-2.0", - "severity": "medium", - "instructions": "" - }, - "CDDL-1.0": { - "licenseType": "CDDL-1.0", - "severity": "medium", - "instructions": "" - }, - "CPOL-1.02": { - "licenseType": "CPOL-1.02", - "severity": "high", - "instructions": "" - }, - "EPL-1.0": { - "licenseType": "EPL-1.0", - "severity": "medium", - "instructions": "" - }, - "GPL-2.0": { - "licenseType": "GPL-2.0", - "severity": "high", - "instructions": "" - }, - "GPL-3.0": { - "licenseType": "GPL-3.0", - "severity": "high", - "instructions": "" - }, - "LGPL-2.0": { - "licenseType": "LGPL-2.0", - "severity": "medium", - "instructions": "" - }, - "LGPL-2.1": { - "licenseType": "LGPL-2.1", - "severity": "medium", - "instructions": "" - }, - "LGPL-3.0": { - "licenseType": "LGPL-3.0", - "severity": "medium", - "instructions": "" - }, - "MPL-1.1": { - "licenseType": "MPL-1.1", - "severity": "medium", - "instructions": "" - }, - "MPL-2.0": { - "licenseType": "MPL-2.0", - "severity": "medium", - "instructions": "" - }, - "MS-RL": { - "licenseType": "MS-RL", - "severity": "medium", - "instructions": "" - }, - "SimPL-2.0": { - "licenseType": "SimPL-2.0", - "severity": "high", - "instructions": "" - } - } - }, - "packageManager": "nuget", - "ignoreSettings": { - "adminOnly": false, - "reasonRequired": false, - "disregardFilesystemIgnores": false - }, - "summary": "No known vulnerabilities", - "filesystemPolicy": false, - "uniqueCount": 0, - "targetFile": "Contentstack.Management.Core/obj/project.assets.json", - "projectName": "contentstack-management-dotnet", - "foundProjectCount": 5, - "displayTargetFile": "Contentstack.Management.Core/obj/project.assets.json", - "hasUnknownVersions": false, - "path": "/Users/om.pawar/Desktop/SDKs/contentstack-management-dotnet" - }, - { - "vulnerabilities": [], - "ok": true, - "dependencyCount": 0, - "org": "contentstack-devex", - "policy": "# Snyk (https://snyk.io) policy file, patches or ignores known vulnerabilities.\nversion: v1.25.1\nignore: {}\npatch: {}\n", - "isPrivate": true, - "licensesPolicy": { - "severities": {}, - "orgLicenseRules": { - "AGPL-1.0": { - "licenseType": "AGPL-1.0", - "severity": "high", - "instructions": "" - }, - "AGPL-3.0": { - "licenseType": "AGPL-3.0", - "severity": "high", - "instructions": "" - }, - "Artistic-1.0": { - "licenseType": "Artistic-1.0", - "severity": "medium", - "instructions": "" - }, - "Artistic-2.0": { - "licenseType": "Artistic-2.0", - "severity": "medium", - "instructions": "" - }, - "CDDL-1.0": { - "licenseType": "CDDL-1.0", - "severity": "medium", - "instructions": "" - }, - "CPOL-1.02": { - "licenseType": "CPOL-1.02", - "severity": "high", - "instructions": "" - }, - "EPL-1.0": { - "licenseType": "EPL-1.0", - "severity": "medium", - "instructions": "" - }, - "GPL-2.0": { - "licenseType": "GPL-2.0", - "severity": "high", - "instructions": "" - }, - "GPL-3.0": { - "licenseType": "GPL-3.0", - "severity": "high", - "instructions": "" - }, - "LGPL-2.0": { - "licenseType": "LGPL-2.0", - "severity": "medium", - "instructions": "" - }, - "LGPL-2.1": { - "licenseType": "LGPL-2.1", - "severity": "medium", - "instructions": "" - }, - "LGPL-3.0": { - "licenseType": "LGPL-3.0", - "severity": "medium", - "instructions": "" - }, - "MPL-1.1": { - "licenseType": "MPL-1.1", - "severity": "medium", - "instructions": "" - }, - "MPL-2.0": { - "licenseType": "MPL-2.0", - "severity": "medium", - "instructions": "" - }, - "MS-RL": { - "licenseType": "MS-RL", - "severity": "medium", - "instructions": "" - }, - "SimPL-2.0": { - "licenseType": "SimPL-2.0", - "severity": "high", - "instructions": "" - } - } - }, - "packageManager": "nuget", - "ignoreSettings": { - "adminOnly": false, - "reasonRequired": false, - "disregardFilesystemIgnores": false - }, - "summary": "No known vulnerabilities", - "filesystemPolicy": false, - "uniqueCount": 0, - "targetFile": "tools/EnhancedTestReport/obj/project.assets.json", - "projectName": "contentstack-management-dotnet", - "foundProjectCount": 5, - "displayTargetFile": "tools/EnhancedTestReport/obj/project.assets.json", - "hasUnknownVersions": false, - "path": "/Users/om.pawar/Desktop/SDKs/contentstack-management-dotnet" - }, - { - "vulnerabilities": [], - "ok": true, - "dependencyCount": 0, - "org": "contentstack-devex", - "policy": "# Snyk (https://snyk.io) policy file, patches or ignores known vulnerabilities.\nversion: v1.25.1\nignore: {}\npatch: {}\n", - "isPrivate": true, - "licensesPolicy": { - "severities": {}, - "orgLicenseRules": { - "AGPL-1.0": { - "licenseType": "AGPL-1.0", - "severity": "high", - "instructions": "" - }, - "AGPL-3.0": { - "licenseType": "AGPL-3.0", - "severity": "high", - "instructions": "" - }, - "Artistic-1.0": { - "licenseType": "Artistic-1.0", - "severity": "medium", - "instructions": "" - }, - "Artistic-2.0": { - "licenseType": "Artistic-2.0", - "severity": "medium", - "instructions": "" - }, - "CDDL-1.0": { - "licenseType": "CDDL-1.0", - "severity": "medium", - "instructions": "" - }, - "CPOL-1.02": { - "licenseType": "CPOL-1.02", - "severity": "high", - "instructions": "" - }, - "EPL-1.0": { - "licenseType": "EPL-1.0", - "severity": "medium", - "instructions": "" - }, - "GPL-2.0": { - "licenseType": "GPL-2.0", - "severity": "high", - "instructions": "" - }, - "GPL-3.0": { - "licenseType": "GPL-3.0", - "severity": "high", - "instructions": "" - }, - "LGPL-2.0": { - "licenseType": "LGPL-2.0", - "severity": "medium", - "instructions": "" - }, - "LGPL-2.1": { - "licenseType": "LGPL-2.1", - "severity": "medium", - "instructions": "" - }, - "LGPL-3.0": { - "licenseType": "LGPL-3.0", - "severity": "medium", - "instructions": "" - }, - "MPL-1.1": { - "licenseType": "MPL-1.1", - "severity": "medium", - "instructions": "" - }, - "MPL-2.0": { - "licenseType": "MPL-2.0", - "severity": "medium", - "instructions": "" - }, - "MS-RL": { - "licenseType": "MS-RL", - "severity": "medium", - "instructions": "" - }, - "SimPL-2.0": { - "licenseType": "SimPL-2.0", - "severity": "high", - "instructions": "" - } - } - }, - "packageManager": "nuget", - "ignoreSettings": { - "adminOnly": false, - "reasonRequired": false, - "disregardFilesystemIgnores": false - }, - "summary": "No known vulnerabilities", - "filesystemPolicy": false, - "uniqueCount": 0, - "targetFile": "tools/IntegrationTestReportGenerator/obj/project.assets.json", - "projectName": "contentstack-management-dotnet", - "foundProjectCount": 5, - "displayTargetFile": "tools/IntegrationTestReportGenerator/obj/project.assets.json", - "hasUnknownVersions": false, - "path": "/Users/om.pawar/Desktop/SDKs/contentstack-management-dotnet" - } -]