Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make time based values on JwtClaimsData #12

Merged
merged 5 commits into from
Aug 27, 2024
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
167 changes: 158 additions & 9 deletions NATS.Jwt.Tests/Models/JwtClaimsDataTests.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
// Copyright (c) The NATS Authors.
// Licensed under the Apache License, Version 2.0.

using System;
using System.Text.Json;
using System.Text.Json.Serialization;
using NATS.Jwt.Internal;
using NATS.Jwt.Models;
using Xunit;

Expand All @@ -16,12 +19,12 @@ public void SerializeDeserialize_FullJwtClaimsData_ShouldSucceed()
{
Audience = "test_audience",
Id = "test_id",
IssuedAt = 1609459200, // 2021-01-01
IssuedAt = DateTimeOffset.FromUnixTimeSeconds(1609459200), // 2021-01-01
Issuer = "test_issuer",
Name = "Test JWT",
Subject = "test_subject",
Expires = 1735689600, // 2025-01-01
NotBefore = 1609459200, // 2021-01-01
Expires = DateTimeOffset.FromUnixTimeSeconds(1735689600), // 2025-01-01
NotBefore = DateTimeOffset.FromUnixTimeSeconds(1609459200), // 2021-01-01
};

string json = JsonSerializer.Serialize(claims);
Expand Down Expand Up @@ -53,10 +56,10 @@ public void SerializeDeserialize_MinimalJwtClaimsData_ShouldSucceed()
Assert.Equal(claims.Issuer, deserialized.Issuer);
Assert.Null(deserialized.Audience);
Assert.Null(deserialized.Id);
Assert.Equal(0, deserialized.IssuedAt);
Assert.Null(deserialized.IssuedAt);
Assert.Null(deserialized.Name);
Assert.Equal(0, deserialized.Expires);
Assert.Equal(0, deserialized.NotBefore);
Assert.Null(deserialized.Expires);
Assert.Null(deserialized.NotBefore);
}

[Fact]
Expand All @@ -76,10 +79,10 @@ public void Deserialize_ExtraFields_ShouldIgnore()
Assert.Equal("test_issuer", deserialized.Issuer);
Assert.Null(deserialized.Audience);
Assert.Null(deserialized.Id);
Assert.Equal(0, deserialized.IssuedAt);
Assert.Null(deserialized.IssuedAt);
Assert.Null(deserialized.Name);
Assert.Equal(0, deserialized.Expires);
Assert.Equal(0, deserialized.NotBefore);
Assert.Null(deserialized.Expires);
Assert.Null(deserialized.NotBefore);
}

[Fact]
Expand Down Expand Up @@ -110,4 +113,150 @@ public void Deserialize_InvalidJson_ShouldThrowException()

Assert.Throws<JsonException>(() => JsonSerializer.Deserialize<JwtClaimsData>(invalidJson));
}

[Fact]
public void Deserialize_WithNullValues_ShouldSetPropertiesToNull()
{
// Arrange
var json = "{}";

// Act
var claims = JsonSerializer.Deserialize<JwtClaimsData>(json);

// Assert
Assert.Null(claims.Audience);
Assert.Null(claims.Id);
Assert.Null(claims.IssuedAt);
Assert.Null(claims.Issuer);
Assert.Null(claims.Name);
Assert.Null(claims.Subject);
Assert.Null(claims.Expires);
Assert.Null(claims.NotBefore);
}

[Fact]
public void Serialize_WithNullValues_ShouldOmitNullProperties()
{
// Arrange
var claims = new JwtClaimsData();

// Act
var json = JsonSerializer.Serialize(claims);

// Assert
Assert.Equal("{}", json);
}

[Fact]
public void Deserialize_WithUnixTimestamps_ShouldConvertCorrectly()
{
// Arrange
var json = @"{
""iat"": 1609459200,
""exp"": 1609545600,
""nbf"": 1609372800
}";

// Act
var claims = JsonSerializer.Deserialize<JwtClaimsData>(json);

// Assert
Assert.Equal(new DateTimeOffset(2021, 1, 1, 0, 0, 0, TimeSpan.Zero), claims.IssuedAt);
Assert.Equal(new DateTimeOffset(2021, 1, 2, 0, 0, 0, TimeSpan.Zero), claims.Expires);
Assert.Equal(new DateTimeOffset(2020, 12, 31, 0, 0, 0, TimeSpan.Zero), claims.NotBefore);
}

[Fact]
public void NatsJsonDateTimeOffsetConverter_Read_ValidNumber_ShouldConvertCorrectly()
{
// Arrange
var json = @"{""Timestamp"": 1609459200}";
var options = new JsonSerializerOptions
{
Converters = { new NatsJsonDateTimeOffsetConverter() }
};

// Act
var result = JsonSerializer.Deserialize<TestClass>(json, options);

// Assert
Assert.Equal(new DateTimeOffset(2021, 1, 1, 0, 0, 0, TimeSpan.Zero), result.Timestamp);
}

[Fact]
public void NatsJsonDateTimeOffsetConverter_Read_NullValue_ShouldReturnNull()
{
// Arrange
var json = @"{""Timestamp"": null}";
var options = new JsonSerializerOptions
{
Converters = { new NatsJsonDateTimeOffsetConverter() }
};

// Act
var result = JsonSerializer.Deserialize<TestClass>(json, options);

// Assert
Assert.Null(result.Timestamp);
}

[Fact]
public void NatsJsonDateTimeOffsetConverter_Read_InvalidTokenType_ShouldThrowException()
{
// Arrange
var json = @"{""Timestamp"": ""not a number""}";
var options = new JsonSerializerOptions
{
Converters = { new NatsJsonDateTimeOffsetConverter() },
};

// Act & Assert
Assert.Throws<InvalidOperationException>(() => JsonSerializer.Deserialize<TestClass>(json, options));
}

[Fact]
public void NatsJsonDateTimeOffsetConverter_Write_ValidValue_ShouldWriteNumber()
{
// Arrange
var testObject = new TestClass
{
Timestamp = new DateTimeOffset(2021, 1, 1, 0, 0, 0, TimeSpan.Zero)
};
var options = new JsonSerializerOptions
{
Converters = { new NatsJsonDateTimeOffsetConverter() }
};

// Act
var json = JsonSerializer.Serialize(testObject, options);

// Assert
Assert.Equal(@"{""Timestamp"":1609459200}", json);
}

[Fact]
public void NatsJsonDateTimeOffsetConverter_Write_NullValue_ShouldWriteNull()
{
// Arrange
var testObject = new TestClass
{
Timestamp = null
};
var options = new JsonSerializerOptions
{
Converters = { new NatsJsonDateTimeOffsetConverter() }
};

// Act
var json = JsonSerializer.Serialize(testObject, options);

// Assert
Assert.Equal(@"{""Timestamp"":null}", json);
}

private class TestClass
{
[JsonConverter(typeof(NatsJsonDateTimeOffsetConverter))]
public DateTimeOffset? Timestamp { get; set; }
}
}
9 changes: 5 additions & 4 deletions NATS.Jwt.Tests/Models/NatsAccountClaimsTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ public void SerializeDeserialize_FullNatsAccountClaims_ShouldSucceed()
Issuer = "IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII",
Name = "Full Test Account",
Audience = "test_audience",
Expires = 1735689600, // 2025-01-01
IssuedAt = 1609459200, // 2021-01-01
NotBefore = 1609459200, // 2021-01-01
Expires = DateTimeOffset.FromUnixTimeSeconds(1735689600), // 2025-01-01
IssuedAt = DateTimeOffset.FromUnixTimeSeconds(1609459200), // 2021-01-01
NotBefore = DateTimeOffset.FromUnixTimeSeconds(1609459200), // 2021-01-01
Id = "jti_test",
Account = new NatsAccount
{
Expand Down Expand Up @@ -102,7 +102,8 @@ public void SerializeDeserialize_FullNatsAccountClaims_ShouldSucceed()
{
Pub = new NatsPermission
{
Allow = new List<string> { "allowed.>", }, Deny = new List<string> { "denied.>", },
Allow = new List<string> { "allowed.>", },
Deny = new List<string> { "denied.>", },
},
Sub =
new NatsPermission
Expand Down
7 changes: 4 additions & 3 deletions NATS.Jwt.Tests/Models/NatsActivationClaimsTests.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright (c) The NATS Authors.
// Licensed under the Apache License, Version 2.0.

using System;
using System.Text.Json;
using NATS.Jwt.Models;
using Xunit;
Expand All @@ -18,9 +19,9 @@ public void SerializeDeserialize_FullNatsActivationClaims_ShouldSucceed()
Issuer = "IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII",
Name = "Full Test Activation",
Audience = "test_audience",
Expires = 1735689600, // 2025-01-01
IssuedAt = 1609459200, // 2021-01-01
NotBefore = 1609459200, // 2021-01-01
Expires = DateTimeOffset.FromUnixTimeSeconds(1735689600), // 2025-01-01
IssuedAt = DateTimeOffset.FromUnixTimeSeconds(1609459200), // 2021-01-01
NotBefore = DateTimeOffset.FromUnixTimeSeconds(1609459200), // 2021-01-01
Id = "jti_test",
Activation = new NatsActivation
{
Expand Down
7 changes: 4 additions & 3 deletions NATS.Jwt.Tests/Models/NatsAuthorizationRequestClaimsTests.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright (c) The NATS Authors.
// Licensed under the Apache License, Version 2.0.

using System;
using System.Collections.Generic;
using System.Text.Json;
using NATS.Jwt.Models;
Expand All @@ -19,9 +20,9 @@ public void SerializeDeserialize_FullNatsAuthorizationRequestClaims_ShouldSuccee
Issuer = "IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII",
Name = "Full Test Authorization Request",
Audience = "test_audience",
Expires = 1735689600,
IssuedAt = 1609459200,
NotBefore = 1609459200,
Expires = DateTimeOffset.FromUnixTimeSeconds(1735689600),
IssuedAt = DateTimeOffset.FromUnixTimeSeconds(1609459200),
NotBefore = DateTimeOffset.FromUnixTimeSeconds(1609459200),
Id = "jti_test",
AuthorizationRequest = new NatsAuthorizationRequest
{
Expand Down
7 changes: 4 additions & 3 deletions NATS.Jwt.Tests/Models/NatsAuthorizationResponseClaimsTests.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright (c) The NATS Authors.
// Licensed under the Apache License, Version 2.0.

using System;
using System.Text.Json;
using NATS.Jwt.Models;
using Xunit;
Expand All @@ -18,9 +19,9 @@ public void SerializeDeserialize_FullNatsAuthorizationResponseClaims_ShouldSucce
Issuer = "IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII",
Name = "Full Test Authorization Response",
Audience = "test_audience",
Expires = 1735689600,
IssuedAt = 1609459200,
NotBefore = 1609459200,
Expires = DateTimeOffset.FromUnixTimeSeconds(1735689600),
IssuedAt = DateTimeOffset.FromUnixTimeSeconds(1609459200),
NotBefore = DateTimeOffset.FromUnixTimeSeconds(1609459200),
Id = "jti_test",
AuthorizationResponse = new NatsAuthorizationResponse
{
Expand Down
7 changes: 4 additions & 3 deletions NATS.Jwt.Tests/Models/NatsGenericFieldsClaimsTests.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright (c) The NATS Authors.
// Licensed under the Apache License, Version 2.0.

using System;
using System.Text.Json;
using NATS.Jwt.Models;
using Xunit;
Expand All @@ -18,9 +19,9 @@ public void SerializeDeserialize_FullNatsGenericFieldsClaims_ShouldSucceed()
Issuer = "IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII",
Name = "Full Test Generic Fields",
Audience = "test_audience",
Expires = 1735689600,
IssuedAt = 1609459200,
NotBefore = 1609459200,
Expires = DateTimeOffset.FromUnixTimeSeconds(1735689600),
IssuedAt = DateTimeOffset.FromUnixTimeSeconds(1609459200),
NotBefore = DateTimeOffset.FromUnixTimeSeconds(1609459200),
Id = "jti_test",
GenericFields = new NatsGenericFields
{
Expand Down
76 changes: 76 additions & 0 deletions NATS.Jwt.Tests/Models/NatsJsonDateTimeOffsetConverterTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
// Copyright (c) The NATS Authors.
// Licensed under the Apache License, Version 2.0.

using System;
using System.IO;
using System.Text.Json;
using NATS.Jwt.Internal;
using Xunit;

namespace NATS.Jwt.Tests.Models;

public class NatsJsonDateTimeOffsetConverterTests
{
[Fact]
public void Read_UnsupportedType_ShouldThrowException()
{
// Act & Assert
var ex = Assert.Throws<InvalidOperationException>(() =>
{
// Arrange
var converter = new TestConverter();
var reader = new Utf8JsonReader(JsonSerializer.SerializeToUtf8Bytes(123));
reader.Read(); // Move to the first token
converter.Read(ref reader, typeof(DateTime), new JsonSerializerOptions());
});
Assert.Contains("Reading unknown date type", ex.Message);
}

[Fact]
public void Write_ValidValue_ShouldWriteCorrectly()
{
// Arrange
var converter = new TestConverter();
MemoryStream memoryStream = new();
var writer = new Utf8JsonWriter(memoryStream);
var value = new DateTimeOffset(2021, 1, 1, 0, 0, 0, TimeSpan.Zero);

// Act
converter.Write(writer, value, new JsonSerializerOptions());
writer.Flush();

// Assert
var json = System.Text.Encoding.UTF8.GetString(memoryStream.ToArray());
Assert.Equal("1609459200", json);
}

[Fact]
public void Write_NullValue_ShouldWriteCorrectly()
{
// Arrange
var converter = new TestConverter();
MemoryStream memoryStream = new();
var writer = new Utf8JsonWriter(memoryStream);

// Act
converter.Write(writer, null, new JsonSerializerOptions());
writer.Flush();

// Assert
var json = System.Text.Encoding.UTF8.GetString(memoryStream.ToArray());
Assert.Equal("null", json);
}

private class TestConverter : NatsJsonDateTimeOffsetConverter
{
public new void Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
base.Read(ref reader, typeToConvert, options);
}

public new void Write(Utf8JsonWriter writer, DateTimeOffset? value, JsonSerializerOptions options)
{
base.Write(writer, value, options);
}
}
}
Loading
Loading