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

Connection string parts validation #276

Merged
merged 5 commits into from
Sep 20, 2024
Merged
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
Original file line number Diff line number Diff line change
@@ -2,6 +2,7 @@
// This source code is licensed under the MIT license.

using Microsoft.Extensions.Configuration;
using System;
using System.Linq;

namespace NBB.MultiTenancy.Abstractions.Configuration;
@@ -43,22 +44,54 @@ private static T getValueOrComplexObject<T>(IConfiguration config, string key)
/// <returns></returns>
public static string GetConnectionString(this ITenantConfiguration config, string name)
{
var splitted = config.GetValue<ConnectionStringDetails>($"ConnectionStrings:{name}");
if (splitted != null)
var connStrBuilder = config.GetValue<TenantConnectionStringBuilder>($"ConnectionStrings:{name}");
if (connStrBuilder != null)
{
return
$"Server={splitted.Server};Database={splitted.Database};User Id={splitted.UserName};Password={splitted.Password};{splitted.OtherParams}";
return connStrBuilder.Build();
}

return config.GetValue<string>($"ConnectionStrings:{name}");
}

private class ConnectionStringDetails
/// <summary>
/// Exception thrown when connection string builder is not properly configured
/// </summary>
public class TenantConnectionStringBuilderException : Exception
{
public TenantConnectionStringBuilderException(string message) : base(message)
{
}
}

private class TenantConnectionStringBuilder
{
public string Server { get; set; }
public string Database { get; set; }
public string UserName { get; set; }
public string Password { get; set; }
public string OtherParams { get; set; }

public string Build()
{
Validate();

return $"Server={Server};Database={Database};User Id={UserName};Password={Password};{OtherParams}";
}

private static void CheckMandatoryField(string fieldValue, string fieldName)
{
if (string.IsNullOrWhiteSpace(fieldValue))
{
throw new TenantConnectionStringBuilderException($"Connection string part {fieldName} is not provided!");
}
}

private void Validate()
{
CheckMandatoryField(Server, nameof(Server));
CheckMandatoryField(Database, nameof(Database));
CheckMandatoryField(UserName, nameof(UserName));
CheckMandatoryField(Password, nameof(Password));
}
}
}
Original file line number Diff line number Diff line change
@@ -12,6 +12,7 @@
using System.IO;
using System.Text;
using Xunit;
using static NBB.MultiTenancy.Abstractions.Configuration.TenantConfigurationExtensions;

namespace NBB.MultiTenancy.Abstractions.Tests
{
@@ -209,6 +210,7 @@ public void load_connectionString_splitted_without_defaults()
""Server"": ""server1"",
""Database"": ""db1"",
""UserName"": ""web"",
""Password"": ""pass"",
""OtherParams"": ""MultipleActiveResultSets=true""
}
}
@@ -242,7 +244,7 @@ public void load_connectionString_splitted_without_defaults()

// Assert
tenantConfig.GetConnectionString("ConnectionString_").Should().BeNull();
tenantConfig.GetConnectionString("Leasing_Database").Should().Be("Server=server1;Database=db1;User Id=web;Password=;MultipleActiveResultSets=true");
tenantConfig.GetConnectionString("Leasing_Database").Should().Be("Server=server1;Database=db1;User Id=web;Password=pass;MultipleActiveResultSets=true");
tenantConfig.GetValue<string>("TenantId").Should().Be("68a448a2-e7d8-4875-8127-f18668217eb6");
}

@@ -258,7 +260,8 @@ public void load_connectionString_splitted_from_default()
""Leasing_Database"": {
""Server"": ""cf-erp17\\mama"",
""Database"": ""db1"",
""UserName"": ""web""
""UserName"": ""web"",
""Password"": ""pass""
}
}
},
@@ -303,7 +306,7 @@ public void load_connectionString_splitted_from_default()

// Assert
tenantConfig.GetConnectionString("ConnectionString_").Should().BeNull();
tenantConfig.GetConnectionString("Leasing_Database").Should().Be("Server=cf-erp17\\mama;Database=db1;User Id=web;Password=;");
tenantConfig.GetConnectionString("Leasing_Database").Should().Be("Server=cf-erp17\\mama;Database=db1;User Id=web;Password=pass;");
tenantConfig.GetValue<string>("TenantId").Should().Be("ef8d5362-9969-4e02-8794-0d1af56816f6");
}

@@ -383,6 +386,7 @@ public void load_connectionString_with_concatenated_defaults()
""Server"": ""server1"",
""Database"": ""db1"",
""UserName"": ""web"",
""Password"": ""pass"",
""OtherParams"": ""MultipleActiveResultSets=true""
}
}
@@ -416,7 +420,7 @@ public void load_connectionString_with_concatenated_defaults()

// Assert
tenantConfig.GetConnectionString("ConnectionString_").Should().BeNull();
tenantConfig.GetConnectionString("Leasing_Database").Should().Be("Server=server1;Database=db1;User Id=web;Password=;MultipleActiveResultSets=true");
tenantConfig.GetConnectionString("Leasing_Database").Should().Be("Server=server1;Database=db1;User Id=web;Password=pass;MultipleActiveResultSets=true");
tenantConfig.GetValue<string>("TenantId").Should().Be("68a448a2-e7d8-4875-8127-f18668217eb6");
}

@@ -476,6 +480,54 @@ public void load_connectionString_concatenated_with_splitted_defaults()
tenantConfig.GetValue<string>("TenantId").Should().Be("68a448a2-e7d8-4875-8127-f18668217eb6");
}


[Fact]
public void load_connectionString_splitted_tenant1_missing_database()
{
// Arrange
var myConfiguration = @"{
""MultiTenancy"": {
""Tenants"": {
""MBFS"": {
""TenantId"": ""68a448a2-e7d8-4875-8127-f18668217eb6"",
""ConnectionStrings"": {
""Leasing_Database"": {
""Server"": ""server1"",
""Database"": """",
""UserName"": ""web"",
""OtherParams"": ""MultipleActiveResultSets=true""
}
}
},
""BCR"": {
""TenantId"": ""ef8d5362-9969-4e02-8794-0d1af56816f6"",
""Code"": ""BCR""
},
""DEV"": {
""TenantId"": ""da84628a-2925-4b69-9116-a90dd5a72b1f"",
""Code"": ""DEV""
}
}
}
}";

var configuration = new ConfigurationBuilder()
.AddInMemoryCollection()
.AddJsonStream(new MemoryStream(Encoding.UTF8.GetBytes(myConfiguration)))
.Build();

var tid = Guid.Parse("68a448a2-e7d8-4875-8127-f18668217eb6");
var tca = new TenantContextAccessor();

tca.TenantContext = new TenantContext(new Tenant(tid, "MBFS"));
var tenantConfig = new TenantConfiguration(configuration,
new OptionsWrapper<TenancyHostingOptions>(new TenancyHostingOptions()
{ TenancyType = TenancyType.MultiTenant }), tca);

// Act
Action act = () => tenantConfig.GetConnectionString("Leasing_Database");

// Assert
act.Should().Throw<TenantConnectionStringBuilderException>().WithMessage("Connection string part Database is not provided!");
}
}
}
Loading