Skip to content

Commit 14735d1

Browse files
authored
Merge pull request #6 from jamiewinder/cedar-4.5.0
Cedar 4.5.0
2 parents 9e074d1 + 138d05d commit 14735d1

10 files changed

Lines changed: 185 additions & 48 deletions

File tree

src/CedarDotNet/CedarFunctions.cs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
using CedarDotNet.Interop;
22
using CedarDotNet.Models;
3+
using System.Runtime.InteropServices;
4+
using System.Text.Json;
35

46
namespace CedarDotNet;
57

@@ -86,6 +88,30 @@ public static IAuthorizationAnswer IsAuthorized(
8688
inputTypeInfo: CedarJsonSerializerContext.Default.AuthorizationCall,
8789
outputTypeInfo: CedarJsonSerializerContext.Default.IAuthorizationAnswer);
8890

91+
/// <summary>
92+
/// Parses a policy set into its constituent policies.
93+
/// </summary>
94+
/// <param name="policySetText">The policy set text.</param>
95+
/// <returns>The answer.</returns>
96+
public static IPolicySetTextToPartsAnswer PolicySetTextToParts(
97+
string policySetText)
98+
{
99+
var result = CedarFfi.PolicySetTextToParts(policySetText);
100+
101+
try
102+
{
103+
var resultJson = Marshal.PtrToStringUTF8(result)!;
104+
105+
return JsonSerializer.Deserialize(
106+
json: resultJson,
107+
jsonTypeInfo: CedarJsonSerializerContext.Default.IPolicySetTextToPartsAnswer)!;
108+
}
109+
finally
110+
{
111+
CedarFfi.FreeString(result);
112+
}
113+
}
114+
89115
/// <summary>
90116
/// Gets the language version.
91117
/// </summary>

src/CedarDotNet/Interop/CedarFfi.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ internal static partial class CedarFfi
2828
[LibraryImport(CedarNativeLibrary.Name, EntryPoint = "validate", StringMarshalling = StringMarshalling.Utf8)]
2929
public static partial IntPtr Validate(string call);
3030

31+
[LibraryImport(CedarNativeLibrary.Name, EntryPoint = "policy_set_text_to_parts", StringMarshalling = StringMarshalling.Utf8)]
32+
public static partial IntPtr PolicySetTextToParts(string call);
33+
3134
[LibraryImport(CedarNativeLibrary.Name, EntryPoint = "get_lang_version", StringMarshalling = StringMarshalling.Utf8)]
3235
public static partial IntPtr GetLangVersion();
3336

src/CedarDotNet/Models/CedarJsonSerializerContext.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ namespace CedarDotNet.Models;
1010
[JsonSerializable(typeof(IAuthorizationAnswer))]
1111
[JsonSerializable(typeof(ICheckParseAnswer))]
1212
[JsonSerializable(typeof(IFormattingAnswer))]
13+
[JsonSerializable(typeof(IPolicySetTextToPartsAnswer))]
1314
[JsonSourceGenerationOptions(UseStringEnumConverter = true)]
1415
internal sealed partial class CedarJsonSerializerContext
1516
: JsonSerializerContext;
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
using System.Text.Json.Serialization;
2+
3+
namespace CedarDotNet.Models;
4+
5+
/// <summary>
6+
/// The marker interface for 'policy set text to parts' answer.
7+
/// </summary>
8+
[JsonPolymorphic(TypeDiscriminatorPropertyName = "type")]
9+
[JsonDerivedType(typeof(PolicySetTextToPartsAnswerSuccess), "success")]
10+
[JsonDerivedType(typeof(PolicySetTextToPartsAnswerFailure), "failure")]
11+
public interface IPolicySetTextToPartsAnswer;
12+
13+
/// <summary>
14+
/// A successful 'policy set text to parts' answer.
15+
/// </summary>
16+
public sealed record class PolicySetTextToPartsAnswerSuccess
17+
: IPolicySetTextToPartsAnswer
18+
{
19+
/// <summary>
20+
/// The policies.
21+
/// </summary>
22+
[JsonPropertyName("policies")]
23+
public required IReadOnlyCollection<string> Policies { get; init; }
24+
25+
/// <summary>
26+
/// The policy templates.
27+
/// </summary>
28+
[JsonPropertyName("policy_templates")]
29+
public required IReadOnlyCollection<string> PolicyTemplates { get; init; }
30+
}
31+
32+
/// <summary>
33+
/// A failed 'policy set text to parts' answer.
34+
/// </summary>
35+
public sealed record class PolicySetTextToPartsAnswerFailure
36+
: IPolicySetTextToPartsAnswer
37+
{
38+
[JsonPropertyName("errors")]
39+
public required IReadOnlyCollection<DetailedError> Errors { get; init; }
40+
}

src/CedarDotNetFfi/Cargo.lock

Lines changed: 51 additions & 42 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/CedarDotNetFfi/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@ edition = "2024"
77
crate-type=["cdylib"]
88

99
[dependencies]
10-
serde_json = "1.0.140"
10+
serde_json = "1.0.141"
1111

1212
[dependencies.cedar-policy]
13-
version = "4.4.0"
13+
version = "4.5.0"
1414
git = "https://github.com/cedar-policy/cedar"
1515
branch = "main"
1616
features = ["partial-eval"]

src/CedarDotNetFfi/src/lib.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ use cedar_policy::ffi::{
1717
is_authorized_partial_json_str,
1818
validate_json_str,
1919
get_lang_version as internal_get_lang_version,
20-
get_sdk_version as internal_get_sdk_version
20+
get_sdk_version as internal_get_sdk_version,
21+
policy_set_text_to_parts as internal_policy_set_text_to_parts
2122
};
2223

2324
#[unsafe(no_mangle)]
@@ -153,4 +154,15 @@ pub fn load_policy_set(text: *const c_char) -> *const c_char {
153154
let result_json_str = serde_json::to_string(&arr).unwrap();
154155

155156
CString::new(result_json_str.to_string()).unwrap().into_raw()
157+
}
158+
159+
#[unsafe(no_mangle)]
160+
pub fn policy_set_text_to_parts(text: *const c_char) -> *const c_char {
161+
let text_str = unsafe { CStr::from_ptr(text).to_str().unwrap() };
162+
163+
let parts = internal_policy_set_text_to_parts(text_str);
164+
165+
let result_json_str = serde_json::to_string(&parts).expect("Could not serialize parts to JSON");
166+
167+
CString::new(result_json_str).unwrap().into_raw()
156168
}

tests/CedarDotNet.UnitTests/CedarDotNet.UnitTests.csproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,10 @@
1313
<PrivateAssets>all</PrivateAssets>
1414
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
1515
</PackageReference>
16-
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.13.0" />
16+
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />
1717
<PackageReference Include="Shouldly" Version="4.3.0" />
1818
<PackageReference Include="xunit" Version="2.9.3" />
19-
<PackageReference Include="xunit.runner.visualstudio" Version="3.0.2">
19+
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.3">
2020
<PrivateAssets>all</PrivateAssets>
2121
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
2222
</PackageReference>
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
using CedarDotNet.Models;
2+
3+
namespace CedarDotNet.UnitTests;
4+
5+
public partial class CedarFunctionTests
6+
{
7+
[Fact]
8+
public void PolicySetTextToParts_ValidPolicySet_ReturnsPoliciesAndTemplates()
9+
{
10+
// Arrange
11+
var policySetText = """
12+
permit(principal, action, resource)
13+
when { principal has "Email" && principal.Email == "a@a.com" };
14+
15+
permit(principal in UserGroup::"DeathRowRecords", action == Action::"pop", resource);
16+
17+
permit(principal in ?principal, action, resource);
18+
""";
19+
20+
// Act
21+
var result = CedarFunctions.PolicySetTextToParts(policySetText);
22+
23+
// Assert
24+
Assert.IsType<PolicySetTextToPartsAnswerSuccess>(result);
25+
26+
var success = (PolicySetTextToPartsAnswerSuccess)result;
27+
28+
Assert.Equal(2, success.Policies.Count);
29+
Assert.Single(success.PolicyTemplates);
30+
}
31+
32+
[Fact]
33+
public void PolicySetTextToParts_InvalidPolicySet_ReturnsFailure()
34+
{
35+
// Arrange
36+
var policySetText = """
37+
invalid
38+
""";
39+
40+
// Act
41+
var result = CedarFunctions.PolicySetTextToParts(policySetText);
42+
43+
// Assert
44+
Assert.IsType<PolicySetTextToPartsAnswerFailure>(result);
45+
}
46+
}

0 commit comments

Comments
 (0)