SaturnFramework / Saturn

Opinionated, web development framework for F# which implements the server-side, functional MVC pattern
https://saturnframework.org
MIT License
707 stars 108 forks source link

How to access and use user secrets in a saturn application #263

Closed kMutagene closed 4 years ago

kMutagene commented 4 years ago

Hi there, awesome library!

I'm trying to wrap my head around how to access user secrets, but i cant quite translate the example provided by microsoft.

lets say i have Saturn running in a SAFE stack environment (most likely irrelevant in this case). I have a webApp, which takes a connection string and then handles requests using the provided connection string for DB access:

let router connectionString = forward "/api" (webApp connectionString)

and a user secret that contains the connection string that i initiated using dotnet user-secrets set :

{
  "Some:ConnectionString": "Data Source=..."
}

and an application that uses the router:

let app = application {
    url ("https://0.0.0.0:" + port.ToString() + "/")
    use_router (router )
}

What i am trying to do is somehow extract the user secret and pass it to the router. What i dont seem to grasp is where and how to perform the dependency injection that ASP.NetCore usually does (see where the user secret is configured via the Configuration API in the MS Docs example.).

What comes very close to what i am trying to do is this section from the example :


public class Startup
{
    private string _connection = null;

    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    public void ConfigureServices(IServiceCollection services)
    {
        var builder = new SqlConnectionStringBuilder(
            Configuration.GetConnectionString("Movies"));
        builder.Password = Configuration["DbPassword"];
        _connection = builder.ConnectionString;
    }

    public void Configure(IApplicationBuilder app)
    {
        app.Run(async (context) =>
        {
            await context.Response.WriteAsync($"DB Connection: {_connection}");
        });
    }
}

The first problem is that i cant find how to get the Configuration object that contains the GetConnectionStringmethod. But even if i could do that, i would configure this section via the service_config operation in the application monad right? But then I can't use the obtained connection string for the router, because the use_routeroperation is separated from it.

I am using Saturn 0.14.1 on netcoreapp/asp.netcore 3.1 .

Any kind of help would be greatly appreciated!

kMutagene commented 4 years ago

here is the same question on stack overflow, which solved the problem: https://stackoverflow.com/questions/62678187/how-to-access-and-use-user-secrets-in-a-saturn-application

Here is the basic solution:

to add user secrets to the application i used this code, where the ID used by config.AddUserSecrets is the secrets id that gets added to the Server.fsproj by using dotnet user-secrets init.

app
    .ConfigureAppConfiguration(
        System.Action<Microsoft.Extensions.Hosting.HostBuilderContext,IConfigurationBuilder> ( fun ctx config ->
            config.AddUserSecrets("6de80bdf-2a05-4cf7-a1a8-d08581dfa887") |> ignore
        )
)
|> run

The secret can then be consumed in the router via:

 forward "/api" (fun next ctx ->

        let settings = ctx.GetService<IConfiguration>()
        let cString = settings.["Some:ConnectionString"]

        webApp cString next ctx

    )