Summary

Class:CBAM.SQL.PostgreSQL.PgSQLDatabaseConfiguration
Assembly:CBAM.SQL.PostgreSQL.Implementation
File(s):/repo-dir/contents/Source/Code/CBAM.SQL.PostgreSQL.Implementation/ConnectionPoolConfiguration.cs
Covered lines:2
Uncovered lines:0
Coverable lines:2
Total lines:308
Line coverage:100%

Coverage History

File(s)

/repo-dir/contents/Source/Code/CBAM.SQL.PostgreSQL.Implementation/ConnectionPoolConfiguration.cs

#LineLine coverage
 1/*
 2 * Copyright 2017 Stanislav Muhametsin. All rights Reserved.
 3 *
 4 * Licensed  under the  Apache License,  Version 2.0  (the "License");
 5 * you may not use  this file  except in  compliance with the License.
 6 * You may obtain a copy of the License at
 7 *
 8 *   http://www.apache.org/licenses/LICENSE-2.0
 9 *
 10 * Unless required by applicable law or agreed to in writing, software
 11 * distributed  under the  License is distributed on an "AS IS" BASIS,
 12 * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
 13 * implied.
 14 *
 15 * See the License for the specific language governing permissions and
 16 * limitations under the License.
 17 */
 18using CBAM.SQL.Implementation;
 19using System;
 20using System.Collections.Generic;
 21using System.IO;
 22using System.Net;
 23using System.Text;
 24using System.Threading.Tasks;
 25using CBAM.SQL.PostgreSQL.Implementation;
 26using UtilPack;
 27using CBAM.Abstractions.Implementation;
 28using CBAM.SQL.PostgreSQL;
 29using IOUtils.Network.Configuration;
 30using FluentCryptography.SASL;
 31using FluentCryptography.SASL.SCRAM;
 32
 33#if !NETSTANDARD1_0
 34using IOUtils.Network.ResourcePooling;
 35#endif
 36
 37namespace CBAM.SQL.PostgreSQL
 38{
 39
 40   /// <summary>
 41   /// This class represents the passive data related to creation of new <see cref="PgSQLConnection"/>.
 42   /// Typically, this class holds the values written in some configuration file on a disk.
 43   /// Use <c>Microsoft.Extensions.Configuration.Binder</c> NuGet package to automatize the creation of this class and p
 44   /// </summary>
 45   /// <remarks>
 46   /// See <see href="https://github.com/CometaSolutions/CBAM/tree/develop/Source/CBAM.SQL.PostgreSQL.Implementation"/> 
 47   /// </remarks>
 48   /// <seealso cref="PgSQLConnectionCreationInfo"/>
 49   public class PgSQLConnectionCreationInfoData : NetworkConnectionCreationInfoData<PgSQLConnectionConfiguration, PgSQLI
 50   {
 51
 52
 53   }
 54
 55   /// <summary>
 56   /// This class contains all passive configuration data related to opening a socket connection when initializing new <
 57   /// </summary>
 58   public class PgSQLConnectionConfiguration : NetworkConnectionConfiguration
 59   {
 60   }
 61
 62   /// <summary>
 63   /// This class contains all passive configuration data related to initialization routine of new <see cref="PgSQLConne
 64   /// </summary>
 65   public class PgSQLInitializationConfiguration : NetworkInitializationConfiguration<PgSQLProtocolConfiguration, PgSQLP
 66   {
 67      /// <summary>
 68      /// Gets or sets the type containing passive configuration data about the database to connect to.
 69      /// </summary>
 70      /// <value>The type containing passive configuration data about the database to connect to.</value>
 71      /// <seealso cref="PgSQLDatabaseConfiguration"/>
 72      public PgSQLDatabaseConfiguration Database { get; set; }
 73
 74   }
 75
 76   /// <summary>
 77   /// This class contains all passive configuration data related to behaviour of PgSQL connections when they are used w
 78   /// </summary>
 79   public class PgSQLPoolingConfiguration : NetworkPoolingConfiguration
 80   {
 81   }
 82
 83   /// <summary>
 84   /// This class contains all passive configuration data related to authentication of new <see cref="PgSQLConnection"/>
 85   /// </summary>
 86   public class PgSQLAuthenticationConfiguration
 87   {
 88
 89      internal static readonly Encoding PasswordByteEncoding = new UTF8Encoding( false, true );
 90
 91      /// <summary>
 92      /// Gets or sets the username to use when connecting to the database.
 93      /// </summary>
 94      /// <value>The username to use when connecting to the database.</value>
 95      public String Username { get; set; }
 96
 97      /// <summary>
 98      /// Gets the textual password as byte array, to use along with <see cref="Username"/> when connecting to the datab
 99      /// </summary>
 100      /// <value>The textual password as byte array, to use along with <see cref="Username"/> when connecting to the dat
 101      /// <seealso cref="PasswordDigest"/>
 102      public Byte[] PasswordBytes { get; private set; }
 103
 104      /// <summary>
 105      /// Gets or sets the digest of the cleartext password.
 106      /// </summary>
 107      /// <value>The digest of the cleartext password.</value>
 108      /// <remarks>
 109      /// This property will *only* be used in SCRAM authentication, if server chooses to perform it.
 110      /// The SCRAM authentication allows to use the digest of the password instead of cleartext password.
 111      /// </remarks>
 112      public Byte[] PasswordDigest { get; set; }
 113
 114      /// <summary>
 115      /// Gets the password, as <see cref="String"/>, to use along with <see cref="Username"/> when connecting to the da
 116      /// </summary>
 117      /// <value>The password, as <see cref="String"/>, to use along with <see cref="Username"/> when connecting to the 
 118      public String Password
 119      {
 120         get
 121         {
 122            var arr = this.PasswordBytes;
 123            return arr == null ? null : PasswordByteEncoding.GetString( arr, 0, arr.Length );
 124         }
 125         set
 126         {
 127            this.PasswordBytes = value == null ? null : PasswordByteEncoding.GetBytes( value );
 128         }
 129      }
 130   }
 131
 132   /// <summary>
 133   /// This class contains all passive configuration data related to selecting which database the <see cref="PgSQLConnec
 134   /// </summary>
 135   public class PgSQLDatabaseConfiguration
 136   {
 137
 138      /// <summary>
 139      /// Gets or sets the name of the database that the <see cref="PgSQLConnection"/> should be connected to.
 140      /// </summary>
 141      /// <value>The name of the database that the <see cref="PgSQLConnection"/> should be connected to.</value>
 72142      public String Name { get; set; }
 143
 144      /// <summary>
 145      /// Gets the search path (<see href="https://www.postgresql.org/docs/current/static/runtime-config-client.html"/>)
 146      /// </summary>
 147      /// <value>The search path (<see href="https://www.postgresql.org/docs/current/static/runtime-config-client.html"/
 52148      public String SearchPath { get; set; }
 149   }
 150
 151   /// <summary>
 152   /// This class contains all passive data configuration related to protocol used to communicate with backend process.
 153   /// </summary>
 154   public class PgSQLProtocolConfiguration
 155   {
 156      /// <summary>
 157      /// Gets or sets the value indicating whether SQL type IDs should be re-read from database, even though they have 
 158      /// </summary>
 159      /// <value>The value indicating whether SQL type IDs should be re-read from database</value>
 160      public Boolean ForceTypeIDLoad { get; set; }
 161
 162      /// <summary>
 163      /// Gets or sets the value indicating whether <see cref="DataFormat.Binary"/> should be disabled when sending data
 164      /// </summary>
 165      /// <value>The value indicating whether <see cref="DataFormat.Binary"/> should be disabled when sending data to th
 166      public Boolean DisableBinaryProtocolSend { get; set; }
 167
 168      /// <summary>
 169      /// Gets or sets the value indicating whether <see cref="DataFormat.Binary"/> should be disabled when receiving da
 170      /// </summary>
 171      /// <value>The value indicating whether <see cref="DataFormat.Binary"/> should be disabled when receiving data fro
 172      public Boolean DisableBinaryProtocolReceive { get; set; }
 173   }
 174
 175   /// <summary>
 176   /// This class binds together the passive configuration data of the <see cref="PgSQLConnectionCreationInfoData"/> and
 177   /// </summary>
 178   public sealed class PgSQLConnectionCreationInfo : NetworkConnectionCreationInfo<PgSQLConnectionCreationInfoData, PgSQ
 179   {
 180      private const String SCRAM_SHA_256 = "SCRAM-SHA-256";
 181      private const String SCRAM_SHA_512 = "SCRAM-SHA-512";
 182
 183      /// <summary>
 184      /// Creates a new instance of <see cref="PgSQLConnectionCreationInfo"/> with given <see cref="PgSQLConnectionCreat
 185      /// </summary>
 186      /// <param name="data">The <see cref="PgSQLConnectionCreationInfoData"/> to use.</param>
 187      /// <exception cref="ArgumentNullException">If <paramref name="data"/> is <c>null</c>.</exception>
 188      /// <remarks>
 189      /// In .NET Core App 1.1+ and .NET Desktop 4.0+ environments this will also set up default values for <see cref="P
 190      /// </remarks>
 191      public PgSQLConnectionCreationInfo(
 192         PgSQLConnectionCreationInfoData data
 193         ) : base( data )
 194      {
 195         this.CreateSASLMechanism = ( names ) =>
 196         {
 197            FluentCryptography.Digest.BlockDigestAlgorithm algorithm;
 198            String mechanismName;
 199
 200            if ( String.IsNullOrEmpty( names ) )
 201            {
 202               algorithm = null;
 203               mechanismName = null;
 204            }
 205            else
 206            {
 207               if ( names.IndexOf( SCRAM_SHA_512 ) >= 0 )
 208               {
 209                  algorithm = new FluentCryptography.Digest.SHA512();
 210                  mechanismName = SCRAM_SHA_512;
 211               }
 212               else if ( names.IndexOf( SCRAM_SHA_256 ) >= 0 )
 213               {
 214                  algorithm = new FluentCryptography.Digest.SHA256();
 215                  mechanismName = SCRAM_SHA_256;
 216               }
 217               else
 218               {
 219                  algorithm = null;
 220                  mechanismName = null;
 221               }
 222            }
 223
 224            return (algorithm?.CreateSASLClientSCRAM(), mechanismName);
 225         };
 226      }
 227      /// <summary>
 228      /// This callback will be used during SCRAM authentication to select the <see cref="SASLMechanism"/> based on the 
 229      /// The constructor will set this to default value which supports SCRAM-SHA-256 and SCRAM-SHA-512, but this may be
 230      /// </summary>
 231      /// <value>The callback to select <see cref="SASLMechanism"/> from a list of SASL mechanisms advertised by backend
 232      /// <remarks>
 233      /// This callback should return a tuple of <see cref="SASLMechanism"/> and the name of it.
 234      /// </remarks>
 235      public Func<String, (SASLMechanism, String)> CreateSASLMechanism { get; set; }
 236
 237      /// <summary>
 238      /// This callback will be used during SCRAM authentication, when the user is successfully authenticated.
 239      /// It will receive a digest of the cleartext password, so that it can be e.g. saved for later purpose.
 240      /// </summary>
 241      /// <value>The callback to call on successful SASL SCRAM authentication, receiving password digest as argument.</v
 242      public Action<Byte[]> OnSASLSCRAMSuccess { get; set; }
 243
 244   }
 245}
 246
 247/// <summary>
 248/// This class contains extension methods for types defined in this assembly.
 249/// </summary>
 250public static partial class E_CBAM
 251{
 252   /// <summary>
 253   /// This is helper method to create a new deep copy of this <see cref="PgSQLConnectionCreationInfoData"/> instance.
 254   /// </summary>
 255   /// <param name="data">This <see cref="PgSQLConnectionCreationInfoData"/>.</param>
 256   /// <returns>A new instance of <see cref="PgSQLConnectionCreationInfoData"/>, with all values deeply copied from this
 257   /// <exception cref="NullReferenceException">If this <see cref="PgSQLConnectionCreationInfoData"/> is <c>null</c>.</e
 258   public static PgSQLConnectionCreationInfoData CreateCopy( this PgSQLConnectionCreationInfoData data )
 259   {
 260
 261#if !NETSTANDARD1_0
 262      var conn = data.Connection;
 263#endif
 264
 265      var init = data.Initialization;
 266      var db = init?.Database;
 267      var protocol = init?.Protocol;
 268      var pool = init?.ConnectionPool;
 269      var auth = init?.Authentication;
 270
 271      return new PgSQLConnectionCreationInfoData()
 272      {
 273#if !NETSTANDARD1_0
 274         Connection = new PgSQLConnectionConfiguration()
 275         {
 276            Host = conn?.Host,
 277            Port = conn?.Port ?? 0,
 278            ConnectionSSLMode = conn?.ConnectionSSLMode ?? ConnectionSSLMode.NotRequired,
 279            SSLProtocols = conn?.SSLProtocols ?? PgSQLConnectionConfiguration.DEFAULT_SSL_PROTOCOL
 280         },
 281#endif
 282         Initialization = new PgSQLInitializationConfiguration()
 283         {
 284            Database = new PgSQLDatabaseConfiguration()
 285            {
 286               Name = db?.Name,
 287               SearchPath = db?.SearchPath
 288            },
 289            Authentication = new PgSQLAuthenticationConfiguration()
 290            {
 291               Username = auth?.Username,
 292               Password = auth?.Password,
 293               PasswordDigest = auth?.PasswordDigest
 294            },
 295            Protocol = new PgSQLProtocolConfiguration()
 296            {
 297               ForceTypeIDLoad = protocol?.ForceTypeIDLoad ?? false,
 298               DisableBinaryProtocolSend = protocol?.DisableBinaryProtocolSend ?? false,
 299               DisableBinaryProtocolReceive = protocol?.DisableBinaryProtocolReceive ?? false
 300            },
 301            ConnectionPool = new PgSQLPoolingConfiguration()
 302            {
 303               ConnectionsOwnStringPool = pool?.ConnectionsOwnStringPool ?? false
 304            }
 305         }
 306      };
 307   }
 308}

Methods/Properties

Name()
SearchPath()