Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@

using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using RocketInsights.Contextual;
using RocketInsights.Contextual.Models;
using RocketInsights.DXP.Providers.Contentful.Extensions;
using RocketInsights.DXP.Services;
using System.Globalization;
using System.Reflection;
using System.Security.Claims;
using System.Threading.Tasks;

namespace RocketInsights.DXP.Providers.Contentful.Tests
{
[TestClass]
public class IntegrationTests
{
private static IServiceCollection ServiceCollection { get; set; }

public IntegrationTests()
{
IConfigurationRoot configurationRoot = new ConfigurationBuilder()
.AddUserSecrets(Assembly.GetExecutingAssembly())
.Build();

ServiceCollection = new ServiceCollection()
.AddLogging(logging => logging.SetMinimumLevel(LogLevel.Trace))
.AddHttpContextAccessor()
.AddContextual()
.AddSingleton<IContextStore, DefaultContextStore>()
.AddDXP()
.AddContentful(configurationRoot);

}

//[TestMethod]
public async Task TestRetrievingAContentFragmentFromContentful()
{
var provider = ServiceCollection.BuildServiceProvider();

var contextStore = provider.GetRequiredService<IContextStore>();
contextStore.Set("context", new Context()
{
Culture = new CultureInfo("en-US"),
Identity = new ClaimsIdentity()
});

var experienceService = provider.GetRequiredService<IContentService>();

var fragment = await experienceService.GetFragmentAsync("3EK9sDbFFm69x1azZdd6MJ");
Assert.AreEqual("3EK9sDbFFm69x1azZdd6MJ", fragment.Id);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Please see the readme in `RocketInsights.DXP.Providers.Contentful` project for details about required config settings needed to run this.
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>

<IsPackable>false</IsPackable>

<UserSecretsId>130d7bc1-de18-4c07-9e18-fc49e3ce9cb5</UserSecretsId>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="JunitXml.TestLogger" Version="3.0.98" />
<PackageReference Include="Microsoft.Extensions.Configuration" Version="5.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="5.0.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="5.0.2" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="5.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="5.0.0" />
<PackageReference Include="Microsoft.Extensions.Options" Version="5.0.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.11.0" />
<PackageReference Include="MSTest.TestAdapter" Version="2.2.10" />
<PackageReference Include="MSTest.TestFramework" Version="2.2.10" />
<PackageReference Include="coverlet.collector" Version="3.1.2">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\RocketInsights.Common\RocketInsights.Common.csproj" />
<ProjectReference Include="..\RocketInsights.Contextual.AspNetCore\RocketInsights.Contextual.AspNetCore.csproj" />
<ProjectReference Include="..\RocketInsights.DXP.AspNetCore\RocketInsights.DXP.AspNetCore.csproj" />
<ProjectReference Include="..\RocketInsights.DXP.Providers.Contentful\RocketInsights.DXP.Providers.Contentful.csproj" />
</ItemGroup>

</Project>
48 changes: 48 additions & 0 deletions src/RocketInsights.DXP.Providers.Contentful/ContentService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
using RocketInsights.Common.Models;
using RocketInsights.Contextual.Services;
using RocketInsights.DXP.Models;
using RocketInsights.DXP.Providers.Contentful.Proxy;
using RocketInsights.DXP.Services;
using System;
using System.Threading.Tasks;

namespace RocketInsights.DXP.Providers.Contentful
{
public class ContentService : IContentService
{
private IContextService ContextService { get; }
private IContentfulProxy ContentfulProxy { get; }

public ContentService(IContextService contextService, IContentfulProxy contentfulProxy)
{
ContextService = contextService;
ContentfulProxy = contentfulProxy;
}

public Task<Fragment> GetFragmentAsync(string id)
{
if (ContextService.TryGetContext(out var context))
{
var fragmentEntry = ContentfulProxy.GetEntryByIdAsync<Content>(id, context.Culture?.Name).Result;
if (fragmentEntry != null)
{
var fragment = new Fragment()
{
Id = fragmentEntry.SystemProperties.Id,
ContentType = fragmentEntry.SystemProperties.ContentType.Name,
Content = fragmentEntry.Fields
};
return Task.FromResult(fragment);
}
else
{
throw new Exception($"Unable to fetch Fragment: {id}");
}
}
else
{
throw new Exception("Unable to fetch context");
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using Contentful.Core;
using Contentful.Core.Configuration;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using RocketInsights.DXP.Providers.Contentful.Proxy;
using RocketInsights.DXP.Services;
using System.Net.Http;

namespace RocketInsights.DXP.Providers.Contentful.Extensions
{
public static class DependencyInjectionExtensions
{
public static IServiceCollection AddContentful (this IServiceCollection services, IConfiguration configuration)
{
services.AddSingleton<IContentfulClient>(s => InitContentfulClient(configuration));

services.AddSingleton<IContentService, ContentService>();
services.AddSingleton<IContentfulProxy, ContentfulProxy>();

return services;
}

private static ContentfulClient InitContentfulClient (IConfiguration configuration)
{
var httpClient = new HttpClient();
ContentfulOptions contentfulOptions = configuration.GetSection(nameof(ContentfulOptions)).Get<ContentfulOptions>();

ContentfulClient contentfulClient = new ContentfulClient(httpClient, contentfulOptions);
return contentfulClient;
}
}
}
10 changes: 10 additions & 0 deletions src/RocketInsights.DXP.Providers.Contentful/LayoutService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using System;
using System.Collections.Generic;
using System.Text;

namespace RocketInsights.DXP.Providers.Contentful
{
public class LayoutService
{
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
using Contentful.Core;
using Contentful.Core.Models;
using Contentful.Core.Search;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;

namespace RocketInsights.DXP.Providers.Contentful.Proxy
{
public class ContentfulProxy : IContentfulProxy
{
private IContentfulClient ContentfulClient { get; }

public ContentfulProxy(IContentfulClient contentfulClient)
{
ContentfulClient = contentfulClient;
}

//TODO: Handle API errors, including rate limiting

public async Task<Entry<T>> GetEntryByIdAsync<T>(string entryId, string locale = null)
{
var query = QueryBuilder<Entry<T>>.New;
if (!string.IsNullOrEmpty(locale))
{
query.LocaleIs(locale);
}
var entry = await ContentfulClient.GetEntry<Entry<T>>(entryId, query);
return entry;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using Contentful.Core.Models;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;

namespace RocketInsights.DXP.Providers.Contentful.Proxy
{
public interface IContentfulProxy
{
Task<Entry<T>> GetEntryByIdAsync<T>(string entryId, string locale = "*");
}
}
12 changes: 12 additions & 0 deletions src/RocketInsights.DXP.Providers.Contentful/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
This project relies on configuration settings to be set. These are essentially API keys and related info needed to access the Contentful site.

While the `Environment` and `SpaceId` are not secret and can be stored elsewhere, greater care should be taken for the `API Key` as it should be kept secure.

For Development purpose, it can be simpler to just add the block to `User Secrets` (right click on project and select `Manage User Secrets`)
```JS
{
"ContentfulOptions:DeliveryApiKey": "<API Key>",
"ContentfulOptions:Environment": "<Environment>",
"ContentfulOptions:SpaceId": "<space ID>"
}
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<UserSecretsId>0085a9fb-bf75-4b62-a03f-9d9680f176c9</UserSecretsId>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="contentful.csharp" Version="7.1.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="6.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="6.0.0" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\RocketInsights.Contextual\RocketInsights.Contextual.csproj" />
<ProjectReference Include="..\RocketInsights.DXP.Common\RocketInsights.DXP.csproj" />
</ItemGroup>

</Project>
17 changes: 15 additions & 2 deletions src/RocketInsights.sln
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,11 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RocketInsights.DXP.AspNetCo
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RocketInsights.DXP.Providers.Kontent", "RocketInsights.DXP.Providers.Kontent\RocketInsights.DXP.Providers.Kontent.csproj", "{CB498A41-AB48-40E1-9E59-D25F4FA35305}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RocketInsights.DXP.Providers.Kontent.Tests", "RocketInsights.DXP.Providers.Kontent.Tests\RocketInsights.DXP.Providers.Kontent.Tests.csproj", "{3FB84C80-6D85-4307-BC03-B83304F86400}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RocketInsights.DXP.Providers.Kontent.Tests", "RocketInsights.DXP.Providers.Kontent.Tests\RocketInsights.DXP.Providers.Kontent.Tests.csproj", "{3FB84C80-6D85-4307-BC03-B83304F86400}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RocketInsights.DXP.Providers.Contentful", "RocketInsights.DXP.Providers.Contentful\RocketInsights.DXP.Providers.Contentful.csproj", "{FF78627C-13D2-4093-B06D-10EC46114339}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RocketInsights.DXP.Providers.Contentful.Tests", "RocketInsights.DXP.Providers.Contentful.Tests\RocketInsights.DXP.Providers.Contentful.Tests.csproj", "{C348A0CB-8618-4686-A281-F59F874CE04C}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Expand Down Expand Up @@ -69,6 +73,14 @@ Global
{3FB84C80-6D85-4307-BC03-B83304F86400}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3FB84C80-6D85-4307-BC03-B83304F86400}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3FB84C80-6D85-4307-BC03-B83304F86400}.Release|Any CPU.Build.0 = Release|Any CPU
{FF78627C-13D2-4093-B06D-10EC46114339}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FF78627C-13D2-4093-B06D-10EC46114339}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FF78627C-13D2-4093-B06D-10EC46114339}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FF78627C-13D2-4093-B06D-10EC46114339}.Release|Any CPU.Build.0 = Release|Any CPU
{C348A0CB-8618-4686-A281-F59F874CE04C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C348A0CB-8618-4686-A281-F59F874CE04C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C348A0CB-8618-4686-A281-F59F874CE04C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C348A0CB-8618-4686-A281-F59F874CE04C}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -82,7 +94,8 @@ Global
{A96BA359-7830-4148-916A-10A889ECE470} = {EEBF50A2-9A78-4A59-8D58-FD6EA92FC08E}
{19CC8707-2540-4CFB-9265-D9D774300906} = {EEBF50A2-9A78-4A59-8D58-FD6EA92FC08E}
{CB498A41-AB48-40E1-9E59-D25F4FA35305} = {EEBF50A2-9A78-4A59-8D58-FD6EA92FC08E}
{3FB84C80-6D85-4307-BC03-B83304F86400} = {EEBF50A2-9A78-4A59-8D58-FD6EA92FC08E}
{FF78627C-13D2-4093-B06D-10EC46114339} = {EEBF50A2-9A78-4A59-8D58-FD6EA92FC08E}
{C348A0CB-8618-4686-A281-F59F874CE04C} = {EEBF50A2-9A78-4A59-8D58-FD6EA92FC08E}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {0904E15D-0535-4207-B6B6-83A605BB2590}
Expand Down