Skip to content

Commit

Permalink
Connection string parts validation (#276)
Browse files Browse the repository at this point in the history
* Connection string parts validation

* Fixed tests

* Refactor

* Documentation

* Tests update
  • Loading branch information
fraliv13 authored Sep 20, 2024
1 parent 2149692 commit 060746c
Show file tree
Hide file tree
Showing 2 changed files with 95 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Up @@ -12,6 +12,7 @@
using System.IO;
using System.Text;
using Xunit;
using static NBB.MultiTenancy.Abstractions.Configuration.TenantConfigurationExtensions;

namespace NBB.MultiTenancy.Abstractions.Tests
{
Expand Down Expand Up @@ -209,6 +210,7 @@ public void load_connectionString_splitted_without_defaults()
""Server"": ""server1"",
""Database"": ""db1"",
""UserName"": ""web"",
""Password"": ""pass"",
""OtherParams"": ""MultipleActiveResultSets=true""
}
}
Expand Down Expand Up @@ -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");
}

Expand All @@ -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""
}
}
},
Expand Down Expand Up @@ -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");
}

Expand Down Expand Up @@ -383,6 +386,7 @@ public void load_connectionString_with_concatenated_defaults()
""Server"": ""server1"",
""Database"": ""db1"",
""UserName"": ""web"",
""Password"": ""pass"",
""OtherParams"": ""MultipleActiveResultSets=true""
}
}
Expand Down Expand Up @@ -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");
}

Expand Down Expand Up @@ -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!");
}
}
}

0 comments on commit 060746c

Please sign in to comment.