Skip to content

Commit d103cab

Browse files
author
rstam
committed
Implemented CSHARP-402. Added support in MongoServer for providing admin credentials for operations that require them without having to set them as the default credentials. The admin credentials can either be provided by storing them in the new MongoCredentialsStore or by using new overloads of the relevant methods that now have an adminCredentials parameter. Also removed several admin database related properties and methods from MongoServer (they should be rarely needed and can easily be replaced by passing "admin" as the database name to existing properties and methods).
1 parent a13193a commit d103cab

10 files changed

+323
-131
lines changed

Driver/Core/MongoConnectionStringBuilder.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -560,7 +560,7 @@ public override bool ContainsKey(string keyword)
560560
public MongoServerSettings ToServerSettings()
561561
{
562562
var defaultCredentials = MongoCredentials.Create(_username, _password);
563-
return new MongoServerSettings(_connectionMode, _connectTimeout, defaultCredentials, _guidRepresentation, _ipv6,
563+
return new MongoServerSettings(_connectionMode, _connectTimeout, null, defaultCredentials, _guidRepresentation, _ipv6,
564564
_maxConnectionIdleTime, _maxConnectionLifeTime, _maxConnectionPoolSize, _minConnectionPoolSize, _replicaSetName,
565565
_safeMode ?? MongoDefaults.SafeMode, _servers, _slaveOk, _socketTimeout, ComputedWaitQueueSize,_waitQueueTimeout);
566566
}

Driver/Core/MongoCredentialsStore.cs

Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
/* Copyright 2010-2012 10gen Inc.
2+
*
3+
* Licensed under the Apache License, Version 2.0 (the "License");
4+
* you may not use this file except in compliance with the License.
5+
* You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software
10+
* distributed under the License is distributed on an "AS IS" BASIS,
11+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
* See the License for the specific language governing permissions and
13+
* limitations under the License.
14+
*/
15+
16+
using System;
17+
using System.Collections.Generic;
18+
using System.Linq;
19+
using System.Text;
20+
21+
namespace MongoDB.Driver
22+
{
23+
/// <summary>
24+
/// Represents a credentials store that contains credentials for different databases.
25+
/// </summary>
26+
public class MongoCredentialsStore
27+
{
28+
// private fields
29+
private Dictionary<string, MongoCredentials> _credentialsStore = new Dictionary<string,MongoCredentials>();
30+
private int _frozenHashCode;
31+
private bool _isFrozen;
32+
33+
// constructors
34+
/// <summary>
35+
/// Creates a new instance of the MongoCredentialsStore class.
36+
/// </summary>
37+
public MongoCredentialsStore()
38+
{
39+
}
40+
41+
// public methods
42+
/// <summary>
43+
/// Adds the credentials for a database to the store.
44+
/// </summary>
45+
/// <param name="databaseName">The database name.</param>
46+
/// <param name="credentials">The credentials.</param>
47+
public void AddCredentials(string databaseName, MongoCredentials credentials)
48+
{
49+
if (_isFrozen) { throw new InvalidOperationException("MongoCredentialsStore is frozen."); }
50+
if (databaseName == null)
51+
{
52+
throw new ArgumentNullException("databaseName");
53+
}
54+
if (credentials == null)
55+
{
56+
throw new ArgumentNullException("credentials");
57+
}
58+
if (databaseName == "admin" && !credentials.Admin)
59+
{
60+
throw new ArgumentOutOfRangeException("Credentials for the admin database must have the admin flag set to true.");
61+
}
62+
_credentialsStore.Add(databaseName, credentials);
63+
}
64+
65+
/// <summary>
66+
/// Creates a clone of the credentials store.
67+
/// </summary>
68+
/// <returns>A clone of the credentials store.</returns>
69+
public MongoCredentialsStore Clone()
70+
{
71+
var clone = new MongoCredentialsStore();
72+
foreach (var item in _credentialsStore)
73+
{
74+
clone.AddCredentials(item.Key, item.Value);
75+
}
76+
return clone;
77+
}
78+
79+
/// <summary>
80+
/// Compares this credentials store to another credentials store.
81+
/// </summary>
82+
/// <param name="rhs">The other credentials store.</param>
83+
/// <returns>True if the two credentials stores are equal.</returns>
84+
public bool Equals(MongoCredentialsStore rhs)
85+
{
86+
if (object.ReferenceEquals(rhs, null) || GetType() != rhs.GetType()) {
87+
return false;
88+
}
89+
90+
if (_credentialsStore.Count != rhs._credentialsStore.Count)
91+
{
92+
return false;
93+
}
94+
95+
foreach (var key in _credentialsStore.Keys)
96+
{
97+
if (!rhs._credentialsStore.ContainsKey(key))
98+
{
99+
return false;
100+
}
101+
if (!_credentialsStore[key].Equals(rhs._credentialsStore[key]))
102+
{
103+
return false;
104+
}
105+
}
106+
107+
return true;
108+
}
109+
110+
/// <summary>
111+
/// Compares this credentials store to another credentials store.
112+
/// </summary>
113+
/// <param name="obj">The other credentials store.</param>
114+
/// <returns>True if the two credentials stores are equal.</returns>
115+
public override bool Equals(object obj)
116+
{
117+
return Equals(obj as MongoCredentialsStore); // works even if obj is null or of a different type
118+
}
119+
120+
/// <summary>
121+
/// Freezes the credentials store.
122+
/// </summary>
123+
/// <returns>The frozen credentials store.</returns>
124+
public MongoCredentialsStore Freeze()
125+
{
126+
if (!_isFrozen)
127+
{
128+
_frozenHashCode = GetHashCode();
129+
_isFrozen = true;
130+
}
131+
return this;
132+
}
133+
134+
/// <summary>
135+
/// Gets the hashcode for the credentials store.
136+
/// </summary>
137+
/// <returns>The hashcode.</returns>
138+
public override int GetHashCode()
139+
{
140+
if (_isFrozen)
141+
{
142+
return _frozenHashCode;
143+
}
144+
145+
// see Effective Java by Joshua Bloch
146+
int hash = 17;
147+
var keys = _credentialsStore.Keys.ToArray();
148+
Array.Sort(keys);
149+
foreach (var key in keys)
150+
{
151+
hash = 37 * hash + key.GetHashCode();
152+
hash = 37 * hash + _credentialsStore[key].GetHashCode();
153+
}
154+
return hash;
155+
}
156+
157+
/// <summary>
158+
/// Returns a string representation of the credentials store.
159+
/// </summary>
160+
/// <returns>A string representation of the credentials store.</returns>
161+
public override string ToString()
162+
{
163+
var sb = new StringBuilder();
164+
sb.Append("{");
165+
var separator = "";
166+
var keys = _credentialsStore.Keys.ToArray();
167+
Array.Sort(keys);
168+
foreach (var key in keys)
169+
{
170+
var credentials = _credentialsStore[key];
171+
sb.Append(separator);
172+
sb.AppendFormat("{0}@{1}", credentials.ToString(), key);
173+
separator = ",";
174+
}
175+
sb.Append("}");
176+
return sb.ToString();
177+
}
178+
179+
/// <summary>
180+
/// Gets the credentials for a database.
181+
/// </summary>
182+
/// <param name="databaseName">The database name.</param>
183+
/// <param name="credentials">The credentials.</param>
184+
/// <returns>True if the store contained credentials for the database. Otherwise false.</returns>
185+
public bool TryGetCredentials(string databaseName, out MongoCredentials credentials)
186+
{
187+
if (databaseName == null)
188+
{
189+
throw new ArgumentNullException("databaseName");
190+
}
191+
return _credentialsStore.TryGetValue(databaseName, out credentials);
192+
}
193+
}
194+
}

Driver/Core/MongoDatabase.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -364,7 +364,7 @@ public virtual MongoCollectionSettings CreateCollectionSettings(
364364
/// </summary>
365365
public virtual void Drop()
366366
{
367-
_server.DropDatabase(_name);
367+
_server.DropDatabase(_name, _settings.Credentials);
368368
}
369369

370370
/// <summary>
@@ -786,7 +786,8 @@ public virtual CommandResult RenameCollection(
786786
{ "to", string.Format("{0}.{1}", _name, newCollectionName) },
787787
{ "dropTarget", dropTarget, dropTarget } // only added if dropTarget is true
788788
};
789-
return _server.RunAdminCommand(command);
789+
var adminDatabase = _server.GetDatabase("admin");
790+
return adminDatabase.RunCommand(command); // TODO: can we run this command against this database?
790791
}
791792

792793
/// <summary>

Driver/Core/MongoDatabaseSettings.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ public MongoDatabaseSettings(MongoServer server, string databaseName)
4848
{
4949
var serverSettings = server.Settings;
5050
_databaseName = databaseName;
51-
_credentials = serverSettings.DefaultCredentials;
51+
_credentials = serverSettings.GetCredentials(databaseName);
5252
_guidRepresentation = serverSettings.GuidRepresentation;
5353
_safeMode = serverSettings.SafeMode;
5454
_slaveOk = serverSettings.SlaveOk;
@@ -69,6 +69,10 @@ public MongoDatabaseSettings(
6969
SafeMode safeMode,
7070
bool slaveOk)
7171
{
72+
if (databaseName == "admin" && credentials != null && !credentials.Admin)
73+
{
74+
throw new ArgumentOutOfRangeException("Credentials for the admin database must have the admin flag set to true.");
75+
}
7276
_databaseName = databaseName;
7377
_credentials = credentials;
7478
_guidRepresentation = guidRepresentation;

0 commit comments

Comments
 (0)