Skip to content
Merged
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
2 changes: 1 addition & 1 deletion .github/workflows/build-dotnet.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ jobs:
- run: |
dotnet workload install ios
dotnet restore
dotnet build -c Release /p:IsBrowser=true ./Trinsic
dotnet build -c Release -f net6.0 -p:IsBrowser=true ./Trinsic
dotnet build -c Release
dotnet test -c Release -v n
working-directory: ./dotnet
Expand Down
3 changes: 1 addition & 2 deletions dotnet/.editorconfig
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

[*]
charset = utf-8
end_of_line = lf
Expand All @@ -10,7 +9,7 @@ indent_size = 4
# Microsoft .NET properties
csharp_new_line_before_catch = false
csharp_new_line_before_members_in_object_initializers = false
csharp_new_line_before_open_brace = accessors,control_blocks,events,indexers,properties,types
csharp_new_line_before_open_brace = accessors, control_blocks, events, indexers, properties, types
csharp_preferred_modifier_order = public, private, protected, internal, new, static, abstract, virtual, sealed, readonly, override, extern, unsafe, volatile, async:suggestion
csharp_style_var_elsewhere = true:suggestion
csharp_style_var_for_built_in_types = true:suggestion
Expand Down
46 changes: 23 additions & 23 deletions dotnet/Directory.Build.props
Original file line number Diff line number Diff line change
@@ -1,25 +1,25 @@
<Project>
<!-- Set common properties regarding assembly information and nuget packages -->
<PropertyGroup>
<Authors>Trinsic Engineering Team</Authors>
<Company>Trinsic</Company>
<PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>
<PackageProjectUrl>https://github.com/trinsic-id/sdk</PackageProjectUrl>
<PackageTags>Trinsic</PackageTags>
<Product>Trinsic SDK for NET</Product>
<RepositoryUrl>https://github.com/trinsic-id/sdk.git</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<Version>1.0.0</Version>
<IncludeSymbols>true</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
</PropertyGroup>
<!-- Common compile parameters -->
<PropertyGroup>
<!-- We use full (Windows PDBs) until cross platform support for source link will get better -->
<DebugType>full</DebugType>
<LangVersion>latest</LangVersion>
<NoWarn>$(NoWarn);1591</NoWarn>
<Nullable>enable</Nullable>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
</PropertyGroup>
<!-- Set common properties regarding assembly information and nuget packages -->
<PropertyGroup>
<Authors>Trinsic Engineering Team</Authors>
<Company>Trinsic</Company>
<PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>
<PackageProjectUrl>https://github.com/trinsic-id/sdk</PackageProjectUrl>
<PackageTags>Trinsic</PackageTags>
<Product>Trinsic SDK for NET</Product>
<RepositoryUrl>https://github.com/trinsic-id/sdk.git</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<Version>1.0.0</Version>
<IncludeSymbols>true</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
</PropertyGroup>
<!-- Common compile parameters -->
<PropertyGroup>
<!-- We use full (Windows PDBs) until cross platform support for source link will get better -->
<DebugType>full</DebugType>
<LangVersion>latest</LangVersion>
<NoWarn>$(NoWarn);1591</NoWarn>
<Nullable>enable</Nullable>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
</PropertyGroup>
</Project>
69 changes: 69 additions & 0 deletions dotnet/Tests/HostTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
using System.Threading.Tasks;
using FluentAssertions;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Trinsic;
using Trinsic.Services.Common.V1;
using Xunit;

namespace Tests;

public class HostTests
{
[Fact(DisplayName = "Test default service host")]
public async Task TestGenericHost() {
var host = Host
.CreateDefaultBuilder()
.ConfigureServices(services => {
services.AddTrinsic();
}).Build();

await host.StartAsync();

var providerService = host.Services.GetService<ProviderService>();
var accountService = host.Services.GetRequiredService<AccountService>();

providerService.Should().NotBeNull();
accountService.Should().NotBeNull();

accountService.Options.ServerEndpoint.Should().Be(ServiceBase.DefaultServerEndpoint);
accountService.Options.ServerPort.Should().Be(ServiceBase.DefaultServerPort);
accountService.Options.ServerUseTls.Should().Be(ServiceBase.DefaultServerUseTls);
accountService.Options.DefaultEcosystem.Should().Be(ServiceBase.DefaultEcosystem);
accountService.Options.AuthToken.Should().Be(string.Empty);
accountService.TokenProvider.Should().BeOfType<FileTokenProvider>();

await host.StopAsync();
}

[Fact(DisplayName = "Test configured service host")]
public async Task TestConfiguredGenericHost() {
var host = Host
.CreateDefaultBuilder()
.ConfigureServices(services => {
services.AddTrinsic(options => {
options.AuthToken = "auth";
options.DefaultEcosystem = "eco";
options.ServerEndpoint = "example.com";
options.ServerPort = 42;
options.ServerUseTls = true;
});
}).Build();

await host.StartAsync();

var providerService = host.Services.GetService<ProviderService>();
var accountService = host.Services.GetRequiredService<AccountService>();

providerService.Should().NotBeNull();
accountService.Should().NotBeNull();

accountService.Options.ServerEndpoint.Should().Be("example.com");
accountService.Options.ServerPort.Should().Be(42);
accountService.Options.ServerUseTls.Should().BeTrue();
accountService.Options.DefaultEcosystem.Should().Be("eco");
accountService.Options.AuthToken.Should().Be("auth");

await host.StopAsync();
}
}
20 changes: 10 additions & 10 deletions dotnet/Tests/Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
using Trinsic.Services.VerifiableCredentials.V1;
using FieldType = Trinsic.Services.VerifiableCredentials.Templates.V1.FieldType;
using JsonSerializer = System.Text.Json.JsonSerializer;

#pragma warning disable CS0618

namespace Tests;
Expand All @@ -32,9 +33,9 @@ public class Tests
const int DefaultPort = 5000;
const bool DefaultUseTls = false;
#else
const string DefaultEndpoint = "staging-internal.trinsic.cloud";
const int DefaultPort = 443;
const bool DefaultUseTls = true;
private const string DefaultEndpoint = "staging-internal.trinsic.cloud";
private const int DefaultPort = 443;
private const bool DefaultUseTls = true;
#endif

private readonly ITestOutputHelper _testOutputHelper;
Expand Down Expand Up @@ -67,9 +68,9 @@ public async Task TestWalletService() {
// SETUP ACTORS
// Create 3 different profiles for each participant in the scenario
// setupActors() {
var allison = await accountService.SignInAsync(new SignInRequest {EcosystemId = ecosystemId});
var clinic = await accountService.SignInAsync(new SignInRequest {EcosystemId = ecosystemId});
var airline = await accountService.SignInAsync(new SignInRequest {EcosystemId = ecosystemId});
var allison = await accountService.SignInAsync(new() {EcosystemId = ecosystemId});
var clinic = await accountService.SignInAsync(new() {EcosystemId = ecosystemId});
var airline = await accountService.SignInAsync(new() {EcosystemId = ecosystemId});
// }

accountService.Options.AuthToken = clinic;
Expand Down Expand Up @@ -251,7 +252,7 @@ public async Task TestInvitationIdSet() {
invitationResponse.Should().NotBeNull();
invitationResponse.InvitationCode.Should().NotBeEmpty();

await Assert.ThrowsAsync<Exception>(async () => await providerService.InvitationStatusAsync(new InvitationStatusRequest()));
await Assert.ThrowsAsync<Exception>(async () => await providerService.InvitationStatusAsync(new()));
}

[Fact(Skip = "Ecosystem support not complete yet")]
Expand All @@ -263,7 +264,7 @@ public async Task TestInviteParticipant() {
var response = await myProviderService.InviteParticipantAsync(invite);
Assert.NotNull(response);

var statusResponse = await myProviderService.InvitationStatusAsync(new InvitationStatusRequest {InvitationId = response.InvitationId});
var statusResponse = await myProviderService.InvitationStatusAsync(new() {InvitationId = response.InvitationId});
Assert.NotNull(statusResponse);
}

Expand Down Expand Up @@ -352,12 +353,11 @@ public async Task DemoTemplatesWithIssuance() {
}
}
}

public static class Extensions
{
public static ServiceOptions CloneWithAuthToken(this ServiceOptions options, string authToken) {
var cloned = options.Clone();
cloned.AuthToken = authToken;
return cloned;
}
}
}
25 changes: 13 additions & 12 deletions dotnet/Tests/Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="FluentAssertions" Version="6.2.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.0.0" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="FluentAssertions" Version="6.2.0"/>
<PackageReference Include="Microsoft.Extensions.Hosting" Version="6.0.1"/>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.0.0"/>
<PackageReference Include="xunit" Version="2.4.1"/>
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
Expand All @@ -27,16 +28,16 @@
</PackageReference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Trinsic\Trinsic.csproj" />
<ProjectReference Include="..\Trinsic\Trinsic.csproj"/>
</ItemGroup>
<ItemGroup>
<None Include="..\..\devops\testdata\vaccination-certificate-unsigned.jsonld">
<Link>TestData/vaccination-certificate-unsigned.jsonld</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="..\..\devops\testdata\vaccination-certificate-frame.jsonld">
<Link>TestData/vaccination-certificate-frame.jsonld</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="..\..\devops\testdata\vaccination-certificate-unsigned.jsonld">
<Link>TestData/vaccination-certificate-unsigned.jsonld</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="..\..\devops\testdata\vaccination-certificate-frame.jsonld">
<Link>TestData/vaccination-certificate-frame.jsonld</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>
39 changes: 22 additions & 17 deletions dotnet/Trinsic/AccountService.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
using System;
using System.Threading.Tasks;
using Google.Protobuf;
using Microsoft.Extensions.Options;
using Okapi.Security;
using Okapi.Security.V1;
using Trinsic.Sdk.Options.V1;
using Trinsic.Services.Account.V1;
using AccountServiceClient = Trinsic.Services.Account.V1.Account.AccountClient;

namespace Trinsic;

Expand All @@ -22,11 +22,20 @@ public AccountService(ServiceOptions options)
public AccountService() {
Client = new(Channel);
}


internal AccountService(ITokenProvider tokenProvider) : base(new(), tokenProvider) {
Client = new(Channel);
}

internal AccountService(ITokenProvider tokenProvider, IOptions<ServiceOptions> options)
: base(options.Value, tokenProvider) {
Client = new(Channel);
}

/// <summary>
/// Gets the underlying grpc client
/// </summary>
public AccountServiceClient Client { get; }
private Account.AccountClient Client { get; }

/// <summary>
/// Perform a sign-in to obtain an account profile. If the <see cref="AccountDetails" /> are
Expand All @@ -35,16 +44,12 @@ public AccountService() {
/// <param name="request"></param>
/// <returns></returns>
public async Task<string> SignInAsync(SignInRequest request) {
if (string.IsNullOrWhiteSpace(request.EcosystemId)) {
request.EcosystemId = Options.DefaultEcosystem;
}
if (string.IsNullOrWhiteSpace(request.EcosystemId)) request.EcosystemId = Options.DefaultEcosystem;
var response = await Client.SignInAsync(request);

var authToken = Convert.ToBase64String(response.Profile.ToByteArray());

if (!response.Profile.Protection?.Enabled ?? true) {
Options.AuthToken = authToken;
}

if (!response.Profile.Protection?.Enabled ?? true) await TokenProvider.SaveAsync(authToken);
Comment on lines +51 to +52
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like that this saves the token as a default name and caches it in the concrete implementations - do we want to standardize on a naming scheme? Something like <ecosystemID>.<email>? though there might not always be an email.

Everything gets saved as the default name now, correct? How will users switch to use another token?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The token provider is completely ignored if they pass auth token through the options, this is how they would use multi-user setups.
As you pointed out, the implementation does leave room for named tokens, once we have a clear path on how to do this. I'm curious to dig further on how many use cases there are where multi user tokens would be needed, outside of our unit tests and dev work.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think named tokens will be very useful in the future when developers are integrating multiple trinsic ecosystems together. Having an easy way to work with named tokens now will just be icing on the cake in the future. Also, don't forget our unit tests and dev work (as you mentioned).

I am also envisioning a future in which we are developing the sample applications in conjunction with customers @michaeldboyd can back me up on this, and being able to switch between our ecosystem and our customer's ecosystem would be really handy.

return authToken;
}

Expand All @@ -55,13 +60,13 @@ public async Task<string> SignInAsync(SignInRequest request) {
/// <param name="request"></param>
/// <returns></returns>
public string SignIn(SignInRequest request) {
if (string.IsNullOrWhiteSpace(request.EcosystemId)) {
request.EcosystemId = Options.DefaultEcosystem;
}
if (string.IsNullOrWhiteSpace(request.EcosystemId)) request.EcosystemId = Options.DefaultEcosystem;
var response = Client.SignIn(request);

Options.AuthToken = Convert.ToBase64String(response.Profile.ToByteArray());
return Options.AuthToken;

var authToken = Convert.ToBase64String(response.Profile.ToByteArray());

if (!response.Profile.Protection?.Enabled ?? true) TokenProvider.Save(authToken);
return authToken;
}

/// <summary>
Expand Down Expand Up @@ -150,4 +155,4 @@ public RevokeDeviceResponse RevokeDevice() {
RevokeDeviceRequest request = new();
return Client.RevokeDevice(request, BuildMetadata(request));
}
}
}
Loading