Skip to content

Commit 060746c

Browse files
authored
Connection string parts validation (#276)
* Connection string parts validation * Fixed tests * Refactor * Documentation * Tests update
1 parent 2149692 commit 060746c

File tree

2 files changed

+95
-10
lines changed

2 files changed

+95
-10
lines changed

src/MultiTenancy/NBB.MultiTenancy.Abstractions/Configuration/TenantConfigurationExtensions.cs

Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// This source code is licensed under the MIT license.
33

44
using Microsoft.Extensions.Configuration;
5+
using System;
56
using System.Linq;
67

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

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

56-
private class ConnectionStringDetails
56+
/// <summary>
57+
/// Exception thrown when connection string builder is not properly configured
58+
/// </summary>
59+
public class TenantConnectionStringBuilderException : Exception
60+
{
61+
public TenantConnectionStringBuilderException(string message) : base(message)
62+
{
63+
}
64+
}
65+
66+
private class TenantConnectionStringBuilder
5767
{
5868
public string Server { get; set; }
5969
public string Database { get; set; }
6070
public string UserName { get; set; }
6171
public string Password { get; set; }
6272
public string OtherParams { get; set; }
73+
74+
public string Build()
75+
{
76+
Validate();
77+
78+
return $"Server={Server};Database={Database};User Id={UserName};Password={Password};{OtherParams}";
79+
}
80+
81+
private static void CheckMandatoryField(string fieldValue, string fieldName)
82+
{
83+
if (string.IsNullOrWhiteSpace(fieldValue))
84+
{
85+
throw new TenantConnectionStringBuilderException($"Connection string part {fieldName} is not provided!");
86+
}
87+
}
88+
89+
private void Validate()
90+
{
91+
CheckMandatoryField(Server, nameof(Server));
92+
CheckMandatoryField(Database, nameof(Database));
93+
CheckMandatoryField(UserName, nameof(UserName));
94+
CheckMandatoryField(Password, nameof(Password));
95+
}
6396
}
6497
}

test/UnitTests/MultiTenancy/NBB.MultiTenancy.Configuration.Tests/TenantConfigurationTests.cs

Lines changed: 57 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
using System.IO;
1313
using System.Text;
1414
using Xunit;
15+
using static NBB.MultiTenancy.Abstractions.Configuration.TenantConfigurationExtensions;
1516

1617
namespace NBB.MultiTenancy.Abstractions.Tests
1718
{
@@ -209,6 +210,7 @@ public void load_connectionString_splitted_without_defaults()
209210
""Server"": ""server1"",
210211
""Database"": ""db1"",
211212
""UserName"": ""web"",
213+
""Password"": ""pass"",
212214
""OtherParams"": ""MultipleActiveResultSets=true""
213215
}
214216
}
@@ -242,7 +244,7 @@ public void load_connectionString_splitted_without_defaults()
242244

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

@@ -258,7 +260,8 @@ public void load_connectionString_splitted_from_default()
258260
""Leasing_Database"": {
259261
""Server"": ""cf-erp17\\mama"",
260262
""Database"": ""db1"",
261-
""UserName"": ""web""
263+
""UserName"": ""web"",
264+
""Password"": ""pass""
262265
}
263266
}
264267
},
@@ -303,7 +306,7 @@ public void load_connectionString_splitted_from_default()
303306

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

@@ -383,6 +386,7 @@ public void load_connectionString_with_concatenated_defaults()
383386
""Server"": ""server1"",
384387
""Database"": ""db1"",
385388
""UserName"": ""web"",
389+
""Password"": ""pass"",
386390
""OtherParams"": ""MultipleActiveResultSets=true""
387391
}
388392
}
@@ -416,7 +420,7 @@ public void load_connectionString_with_concatenated_defaults()
416420

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

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

479-
483+
[Fact]
484+
public void load_connectionString_splitted_tenant1_missing_database()
485+
{
486+
// Arrange
487+
var myConfiguration = @"{
488+
""MultiTenancy"": {
489+
""Tenants"": {
490+
""MBFS"": {
491+
""TenantId"": ""68a448a2-e7d8-4875-8127-f18668217eb6"",
492+
""ConnectionStrings"": {
493+
""Leasing_Database"": {
494+
""Server"": ""server1"",
495+
""Database"": """",
496+
""UserName"": ""web"",
497+
""OtherParams"": ""MultipleActiveResultSets=true""
498+
}
499+
}
500+
},
501+
""BCR"": {
502+
""TenantId"": ""ef8d5362-9969-4e02-8794-0d1af56816f6"",
503+
""Code"": ""BCR""
504+
},
505+
""DEV"": {
506+
""TenantId"": ""da84628a-2925-4b69-9116-a90dd5a72b1f"",
507+
""Code"": ""DEV""
508+
}
509+
}
510+
}
511+
}";
512+
513+
var configuration = new ConfigurationBuilder()
514+
.AddInMemoryCollection()
515+
.AddJsonStream(new MemoryStream(Encoding.UTF8.GetBytes(myConfiguration)))
516+
.Build();
517+
518+
var tid = Guid.Parse("68a448a2-e7d8-4875-8127-f18668217eb6");
519+
var tca = new TenantContextAccessor();
520+
521+
tca.TenantContext = new TenantContext(new Tenant(tid, "MBFS"));
522+
var tenantConfig = new TenantConfiguration(configuration,
523+
new OptionsWrapper<TenancyHostingOptions>(new TenancyHostingOptions()
524+
{ TenancyType = TenancyType.MultiTenant }), tca);
525+
526+
// Act
527+
Action act = () => tenantConfig.GetConnectionString("Leasing_Database");
528+
529+
// Assert
530+
act.Should().Throw<TenantConnectionStringBuilderException>().WithMessage("Connection string part Database is not provided!");
531+
}
480532
}
481533
}

0 commit comments

Comments
 (0)