Skip to content

Commit

Permalink
Feature: support automate function input secrets in C# SDK (#3324)
Browse files Browse the repository at this point in the history
* introduce and use `SecretAttribute` during schema generation

* format

* format (for real)

* `pragma` and style

* Supressing CS8764 instead of CS8603

---------

Co-authored-by: Jedd Morgan <[email protected]>
  • Loading branch information
cdriesler and JR-Morgan authored May 2, 2024
1 parent 4b9ae23 commit 9854cdc
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace Speckle.Automate.Sdk.DataAnnotations;

/// <summary>
/// If specified, the given function input will be redacted in all contexts.
/// </summary>
[AttributeUsage(AttributeTargets.All)]
public sealed class SecretAttribute : Attribute { }
34 changes: 34 additions & 0 deletions Automate/Speckle.Automate.Sdk/Runner.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
using System.CommandLine;
using System.Diagnostics.CodeAnalysis;
using Newtonsoft.Json;
using Newtonsoft.Json.Schema;
using Newtonsoft.Json.Schema.Generation;
using Newtonsoft.Json.Serialization;
using Speckle.Automate.Sdk.DataAnnotations;
using Speckle.Automate.Sdk.Schema;
using Speckle.Core.Logging;

Expand Down Expand Up @@ -131,6 +133,7 @@ public static async Task<int> Main<TInput>(string[] args, Func<AutomationContext
(schemaFilePath) =>
{
JSchemaGenerator generator = new() { ContractResolver = new CamelCasePropertyNamesContractResolver() };
generator.GenerationProviders.Add(new SpeckleSecretProvider());
JSchema schema = generator.Generate(typeof(TInput));
schema.ToString(global::Newtonsoft.Json.Schema.SchemaVersion.Draft2019_09);
File.WriteAllText(schemaFilePath, schema.ToString());
Expand All @@ -144,3 +147,34 @@ public static async Task<int> Main<TInput>(string[] args, Func<AutomationContext
return returnCode;
}
}

public class SpeckleSecretProvider : JSchemaGenerationProvider
{
// `GetSchema` returning `null` indicates that the given type should not have a customised schema
// Nullability of JSchemaTypeGenerationContext appears to be incorrect.
#pragma warning disable CS8764 // Nullability of return type doesn't match overridden member (possibly because of nullability attributes).
public override JSchema? GetSchema(JSchemaTypeGenerationContext context)
{
var attributes = context.MemberProperty?.AttributeProvider?.GetAttributes(false) ?? new List<Attribute>();
var isSecretString = attributes.Any(att => att is SecretAttribute);

if (isSecretString)
{
return CreateSchemaWithWriteOnly(context.ObjectType, context.Required);
}

return null;
}
#pragma warning restore CS8764 // Nullability of return type doesn't match overridden member (possibly because of nullability attributes).


private JSchema CreateSchemaWithWriteOnly(Type type, Required required)
{
JSchemaGenerator generator = new();
JSchema schema = generator.Generate(type, required != Required.Always);

schema.WriteOnly = true;

return schema;
}
}

0 comments on commit 9854cdc

Please sign in to comment.