11// <copyright file="LdapConnectionService.cs" company="Visualisierungsinstitut der Universität Stuttgart">
2- // Copyright © 2021 - 2024 Visualisierungsinstitut der Universität Stuttgart.
2+ // Copyright © 2021 - 2025 Visualisierungsinstitut der Universität Stuttgart.
33// Licensed under the MIT licence. See LICENCE file for details.
44// </copyright>
55// <author>Christoph Müller</author>
1010using System ;
1111using System . Collections . Generic ;
1212using System . Diagnostics ;
13- using System . Net . Http . Headers ;
1413using System . Text . RegularExpressions ;
1514using Visus . LdapAuthentication . Configuration ;
1615using Visus . LdapAuthentication . Properties ;
@@ -41,37 +40,19 @@ public LdapConnectionService(IOptions<LdapOptions> options,
4140 ?? throw new ArgumentNullException ( nameof ( logger ) ) ;
4241 this . _options = options ? . Value
4342 ?? throw new ArgumentNullException ( nameof ( options ) ) ;
44- }
43+ }
4544 #endregion
46-
45+
4746 #region Public methods
4847 /// <inheritdoc />
49- public LdapConnection Connect ( string ? username , string ? password ) {
50- var retval = this . TryConnect ( ) ;
51-
52- if ( ( username != null )
53- && ! string . IsNullOrWhiteSpace ( this . _options . DefaultDomain )
54- && ! GetUpnRegex ( ) . IsMatch ( username ) ) {
55- username = $ "{ username } @{ this . _options . DefaultDomain } ";
56- }
57-
58- this . _logger . LogDebug ( "User name to bind (possibly expanded by the "
59- + "default domain) is {username}." , username ) ;
60-
61- if ( ( username == null ) && ( password == null ) ) {
62- this . _logger . LogInformation ( Resources . InfoBindAnonymous ) ;
63- retval . Bind ( null , null ) ;
64- this . _logger . LogInformation ( Resources . InfoBoundAnonymous ) ;
48+ public LdapConnection Connect ( LdapOptions options )
49+ => this . Connect ( null ,
50+ null ,
51+ options ?? throw new ArgumentNullException ( nameof ( options ) ) ) ;
6552
66- } else {
67- this . _logger . LogInformation ( Resources . InfoBindingAsUser ,
68- username ) ;
69- retval . Bind ( username , password ) ;
70- this . _logger . LogInformation ( Resources . InfoBoundAsUser , username ) ;
71- }
72-
73- return retval ;
74- }
53+ /// <inheritdoc />
54+ public LdapConnection Connect ( string ? username , string ? password )
55+ => this . Connect ( username , password , this . _options ) ;
7556 #endregion
7657
7758 #region Private class methods
@@ -89,18 +70,19 @@ public LdapConnection Connect(string? username, string? password) {
8970 /// Block the <paramref name="server"/> at the specified position for
9071 /// the configured amount of time.
9172 /// </summary>
92- private void Blacklist ( int server ) {
93- Debug . Assert ( server < this . _options . Servers . Length ) ;
73+ private void Blacklist ( int server , LdapOptions options ) {
74+ Debug . Assert ( options is not null ) ;
75+ Debug . Assert ( server < options . Servers . Length ) ;
9476
9577 // Only enter the critical section if a valid timespan was
9678 // specified that actually needs to expire.
97- if ( this . _options . BlacklistFailedServersFor > TimeSpan . Zero ) {
79+ if ( options . BlacklistFailedServersFor > TimeSpan . Zero ) {
9880 lock ( this . _lock ) {
9981 var until = DateTimeOffset . UtcNow ;
100- until += this . _options . BlacklistFailedServersFor ;
82+ until += options . BlacklistFailedServersFor ;
10183 this . _blacklisted [ server ] = until ;
10284 this . _logger . LogWarning ( Resources . WarnServerBlacklisted ,
103- this . _options . Servers [ server ] , until ) ;
85+ options . Servers [ server ] , until ) ;
10486
10587 // If the currently active server is the blacklisted one,
10688 // make sure that we now select another one in the
@@ -109,7 +91,7 @@ private void Blacklist(int server) {
10991 if ( this . _currentServer == server ) {
11092 do {
11193 ++ this . _currentServer ;
112- this . _currentServer %= this . _options . Servers . Length ;
94+ this . _currentServer %= options . Servers . Length ;
11395 } while ( this . IsBlacklistedUnsafe ( this . _currentServer )
11496 && ( this . _currentServer != server ) ) ;
11597
@@ -121,6 +103,43 @@ private void Blacklist(int server) {
121103 } /* if (this._options.BlacklistFailedServersFor > TimeSpan.Zero) */
122104 }
123105
106+ /// <summary>
107+ /// Connect to the server specified in <paramref name="options"/>
108+ /// </summary>
109+ /// <param name="username"></param>
110+ /// <param name="password"></param>
111+ /// <param name="options"></param>
112+ /// <returns></returns>
113+ private LdapConnection Connect ( string ? username ,
114+ string ? password ,
115+ LdapOptions options ) {
116+ Debug . Assert ( options is not null ) ;
117+ var retval = this . TryConnect ( options ) ;
118+
119+ if ( ( username != null )
120+ && ! string . IsNullOrWhiteSpace ( options . DefaultDomain )
121+ && ! GetUpnRegex ( ) . IsMatch ( username ) ) {
122+ username = $ "{ username } @{ options . DefaultDomain } ";
123+ }
124+
125+ this . _logger . LogDebug ( "User name to bind (possibly expanded by the "
126+ + "default domain) is {username}." , username ) ;
127+
128+ if ( ( username == null ) && ( password == null ) ) {
129+ this . _logger . LogInformation ( Resources . InfoBindAnonymous ) ;
130+ retval . Bind ( null , null ) ;
131+ this . _logger . LogInformation ( Resources . InfoBoundAnonymous ) ;
132+
133+ } else {
134+ this . _logger . LogInformation ( Resources . InfoBindingAsUser ,
135+ username ) ;
136+ retval . Bind ( username , password ) ;
137+ this . _logger . LogInformation ( Resources . InfoBoundAsUser , username ) ;
138+ }
139+
140+ return retval ;
141+ }
142+
124143 /// <summary>
125144 /// Checks whether <paramref name="server"/> is on the black list, but
126145 /// does not acquire the <see cref="_lock"/> before doing so. Therefore,
@@ -183,19 +202,20 @@ private int SelectRoundRobin() {
183202 /// <summary>
184203 /// Try connecting to any of the configured servers.
185204 /// </summary>
186- private LdapConnection TryConnect ( ) {
205+ private LdapConnection TryConnect ( LdapOptions options ) {
206+ Debug . Assert ( options is not null ) ;
187207 Exception ? error = null ;
188208
189- for ( int i = 0 ; i < this . _options . Servers . Length ; ++ i ) {
209+ for ( int i = 0 ; i < options . Servers . Length ; ++ i ) {
190210 var selection = this . Select ( ) ;
191- var server = this . _options . Servers [ selection ] ;
211+ var server = options . Servers [ selection ] ;
192212
193213 try {
194214 this . _logger . LogInformation ( Resources . InfoServerSelected ,
195215 server ) ;
196- return this . _options . ToConnection ( server , this . _logger ) ;
216+ return options . ToConnection ( server , this . _logger ) ;
197217 } catch ( Exception ex ) {
198- this . Blacklist ( selection ) ;
218+ this . Blacklist ( selection , options ) ;
199219 error = ex ;
200220 }
201221 }
0 commit comments