Skip to content

Commit

Permalink
Basic code structure
Browse files Browse the repository at this point in the history
  • Loading branch information
itaihanski committed Mar 3, 2024
1 parent 25a11c0 commit fba3e7f
Show file tree
Hide file tree
Showing 30 changed files with 5,204 additions and 0 deletions.
47 changes: 47 additions & 0 deletions Descope.Test/Descope.Test.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<RestorePackagesWithLockFile>true</RestorePackagesWithLockFile>
</PropertyGroup>

<ItemGroup>
<Compile Remove="Auth\AccessKeyServiceTest.cs" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Configuration" Version="7.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables"
Version="7.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="7.0.0" />
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="7.0.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
<PackageReference Include="Moq" Version="4.20.69" />
<PackageReference Include="NBuilder" Version="6.1.0" />
<PackageReference Include="xunit" Version="2.6.1" />
<PackageReference Include="xunit.assert" Version="2.6.1" />
<PackageReference Include="xunit.extensibility.core" Version="2.6.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.3">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\Descope\Descope.csproj" />
</ItemGroup>

<ItemGroup>
<None Update="appsettingsTest.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>

<ItemGroup>
<Content Include="xunit.runner.json" CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>

</Project>
25 changes: 25 additions & 0 deletions Descope.Test/Descope.Test.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.5.002.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Descope.Test", "Descope.Test.csproj", "{E2E0EF99-CE4C-40BA-8A8E-532F14D47F7A}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{E2E0EF99-CE4C-40BA-8A8E-532F14D47F7A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E2E0EF99-CE4C-40BA-8A8E-532F14D47F7A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E2E0EF99-CE4C-40BA-8A8E-532F14D47F7A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E2E0EF99-CE4C-40BA-8A8E-532F14D47F7A}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {18F8C6D8-027A-45D4-BFFC-ABFF27D9416F}
EndGlobalSection
EndGlobal
151 changes: 151 additions & 0 deletions Descope.Test/IntegrationTests/Authentication/AuthenticationTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
using Xunit;

namespace Descope.Test.Integration
{
public class AuthenticationTests
{
private readonly DescopeClient _descopeClient = IntegrationTestSetup.InitDescopeClient();

[Fact]
public async Task Authentication_ValidateAndRefresh()
{
string? loginId = null;
try
{
// Create a logged in test user
var testUser = await IntegrationTestSetup.InitTestUser(_descopeClient);
loginId = testUser.User.loginIds.First();

// Make sure the session is valid
var token = await _descopeClient.Auth.ValidateSession(testUser.AuthInfo.sessionJwt);
Assert.Equal(testUser.AuthInfo.sessionJwt, token.Jwt);
Assert.NotEmpty(token.Id);
Assert.NotEmpty(token.ProjectId);

// Refresh and see we got a new token
var refreshedToken = await _descopeClient.Auth.RefreshSession(testUser.AuthInfo.refreshJwt!);
Assert.NotNull(refreshedToken.RefreshExpiration);
Assert.Equal(token.Id, refreshedToken.Id);
Assert.Equal(token.ProjectId, refreshedToken.ProjectId);
}
finally
{
if (!string.IsNullOrEmpty(loginId))
{
try { await _descopeClient.Management.User.Delete(loginId); }
catch { }
}
}
}

[Fact]
public async Task Authentication_ExchangeAccessKeyAndMe()
{
string? loginId = null;
string? accessKeyId = null;
try
{
// Create a logged in test user
var testUser = await IntegrationTestSetup.InitTestUser(_descopeClient);
loginId = testUser.User.loginIds.First();

// Create an access key and exchange it
var accessKeyResponse = await _descopeClient.Management.AccessKey.Create(loginId, userId: testUser.User.userId);
accessKeyId = accessKeyResponse.Key.Id;
var token = await _descopeClient.Auth.ExchangeAccessKey(accessKeyResponse.Cleartext);
Assert.NotEmpty(token.Id);
Assert.NotEmpty(token.ProjectId);
Assert.NotEmpty(token.Jwt);
}
finally
{
if (!string.IsNullOrEmpty(loginId))
{
try { await _descopeClient.Management.User.Delete(loginId); }
catch { }
}
if (!string.IsNullOrEmpty(accessKeyId))
{
try { await _descopeClient.Management.AccessKey.Delete(accessKeyId); }
catch { }
}
}
}

[Fact]
public async Task Authentication_SelectTenant()
{
string? loginId = null;
List<string> tenantIds = new() { };
try
{
// Create a logged in test user
var testUser = await IntegrationTestSetup.InitTestUser(_descopeClient);
loginId = testUser.User.loginIds.First();

// Create a couple of tenants and add to the user
var tenantId = await _descopeClient.Management.Tenant.Create(new TenantOptions { name = Guid.NewGuid().ToString() });
tenantIds.Add(tenantId);
await _descopeClient.Management.User.AddTenant(loginId, tenantId);
tenantId = await _descopeClient.Management.Tenant.Create(new TenantOptions { name = Guid.NewGuid().ToString() });
tenantIds.Add(tenantId);
await _descopeClient.Management.User.AddTenant(loginId, tenantId);
var session = await _descopeClient.Auth.SelectTenant(tenantId, testUser.AuthInfo.refreshJwt!);
Assert.NotEmpty(session.SessionToken.Id);
Assert.NotEmpty(session.SessionToken.ProjectId);
Assert.NotEmpty(session.SessionToken.Jwt);
}
finally
{
if (!string.IsNullOrEmpty(loginId))
{
try { await _descopeClient.Management.User.Delete(loginId); }
catch { }
}
foreach (var tenantId in tenantIds)
{
try { await _descopeClient.Management.Tenant.Delete(tenantId); }
catch { }
}
}
}

// TODO: Test permissions and roles once available on via management

[Theory]
[InlineData(true)]
[InlineData(false)]
public async Task Authentication_MeAndLogout(bool logoutAll)
{
string? loginId = null;
try
{
// Create a logged in test user
var testUser = await IntegrationTestSetup.InitTestUser(_descopeClient);
loginId = testUser.User.loginIds.First();

// Me
var user = await _descopeClient.Auth.Me(testUser.AuthInfo.refreshJwt!);
Assert.Equal(testUser.User.userId, user.userId);

// Logout
if (logoutAll) await _descopeClient.Auth.LogOut(testUser.AuthInfo.refreshJwt!);
else await _descopeClient.Auth.LogOutAll(testUser.AuthInfo.refreshJwt!);

// Try me again
await Task.Delay(200);
async Task Act() => await _descopeClient.Auth.Me(testUser.AuthInfo.refreshJwt!);
DescopeException result = await Assert.ThrowsAsync<DescopeException>(Act);
Assert.Contains("Expired due to logout", result.Message);
}
finally
{
if (!string.IsNullOrEmpty(loginId))
{
try { await _descopeClient.Management.User.Delete(loginId); }
catch { }
}
}
}
}
}
160 changes: 160 additions & 0 deletions Descope.Test/IntegrationTests/Management/AccessKeyTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
using Xunit;

namespace Descope.Test.Integration
{
public class AccessKeyTests
{
private readonly DescopeClient _descopeClient = IntegrationTestSetup.InitDescopeClient();

[Fact]
public async Task AccessKey_Create_MissingName()
{
async Task Act() => await _descopeClient.Management.AccessKey.Create(name: "");
DescopeException result = await Assert.ThrowsAsync<DescopeException>(Act);
Assert.Contains("Access key name is required", result.Message);
}

[Fact]
public async Task AccessKey_CreateAndUpdate()
{
string? id = null;
try
{
// Create an access key
var accessKey = await _descopeClient.Management.AccessKey.Create(name: Guid.NewGuid().ToString());
id = accessKey.Key.Id;

// Update and compare
var updatedName = accessKey.Key.Name + "updated";
var updatedKey = await _descopeClient.Management.AccessKey.Update(id: id, name: updatedName);
Assert.Equal(updatedKey.Name, updatedKey.Name);
}
finally
{
if (!string.IsNullOrEmpty(id))
{
try { await _descopeClient.Management.AccessKey.Delete(id); }
catch { }
}
}
}

[Fact]
public async Task AccessKey_Update_MissingId()
{
async Task Act() => await _descopeClient.Management.AccessKey.Update("", "name");
DescopeException result = await Assert.ThrowsAsync<DescopeException>(Act);
Assert.Contains("ID is required", result.Message);
}

[Fact]
public async Task AccessKey_Update_MissingName()
{
async Task Act() => await _descopeClient.Management.AccessKey.Update("someId", "");
DescopeException result = await Assert.ThrowsAsync<DescopeException>(Act);
Assert.Contains("name cannot be updated to empty", result.Message);
}

[Fact]
public async Task Accesskey_ActivateDeactivate()
{
string? id = null;
try
{
// Create an access key
var accessKey = await _descopeClient.Management.AccessKey.Create(name: Guid.NewGuid().ToString());
id = accessKey.Key.Id;

// Deactivate
await _descopeClient.Management.AccessKey.Deactivate(id);
var loadedKey = await _descopeClient.Management.AccessKey.Load(id);
Assert.Equal("inactive", loadedKey.Status);

// Activate
await _descopeClient.Management.AccessKey.Activate(id);
loadedKey = await _descopeClient.Management.AccessKey.Load(id);
Assert.Equal("active", loadedKey.Status);
}
finally
{
if (!string.IsNullOrEmpty(id))
{
try { await _descopeClient.Management.AccessKey.Delete(id); }
catch { }
}
}
}

[Fact]
public async Task AccessKey_Activate_MissingId()
{
async Task Act() => await _descopeClient.Management.AccessKey.Activate("");
DescopeException result = await Assert.ThrowsAsync<DescopeException>(Act);
Assert.Contains("ID is required", result.Message);
}

[Fact]
public async Task AccessKey_Deactivate_MissingId()
{
async Task Act() => await _descopeClient.Management.AccessKey.Deactivate("");
DescopeException result = await Assert.ThrowsAsync<DescopeException>(Act);
Assert.Contains("ID is required", result.Message);
}

[Fact]
public async Task AccessKey_Load_MissingId()
{
async Task Act() => await _descopeClient.Management.AccessKey.Load("");
DescopeException result = await Assert.ThrowsAsync<DescopeException>(Act);
Assert.Contains("Access key ID is required", result.Message);
}

[Fact]
public async Task AccessKey_SearchAll()
{
string? id = null;
try
{
// Create an access key
var accessKey = await _descopeClient.Management.AccessKey.Create(name: Guid.NewGuid().ToString());
id = accessKey.Key.Id;

// Search for it
var accessKeys = await _descopeClient.Management.AccessKey.SearchAll();
var key = accessKeys.Find(key => key.Id == id);
Assert.NotNull(key);
}
finally
{
if (!string.IsNullOrEmpty(id))
{
try { await _descopeClient.Management.AccessKey.Delete(id); }
catch { }
}
}
}

[Fact]
public async Task AccessKey_Delete()
{
// Arrange
var accessKey = await _descopeClient.Management.AccessKey.Create(name: Guid.NewGuid().ToString());

// Act
await _descopeClient.Management.AccessKey.Delete(accessKey.Key.Id);

// Assert
var accessKeys = await _descopeClient.Management.AccessKey.SearchAll(new List<string>() { accessKey.Key.Id });
Assert.Empty(accessKeys);
}

[Fact]
public async Task Accesskey_Delete_MissingId()
{
async Task Act() => await _descopeClient.Management.AccessKey.Delete("");
DescopeException result = await Assert.ThrowsAsync<DescopeException>(Act);
Assert.Contains("Access key ID is required", result.Message);
}

}
}
Loading

0 comments on commit fba3e7f

Please sign in to comment.