Browse Source

Implemented CSHARP-248. Added FindAllUsers and FindUser methods to MongoDatabase. Added new MongoUser class. Found a bunch of unit tests that weren't being run because they were missing the [Test] attribute.

pull/59/merge
rstam 14 years ago
parent
commit
4f47b0a69f
  1. 35
      BsonUnitTests/ObjectModel/BsonValueTests.cs
  2. 70
      Driver/Core/MongoDatabase.cs
  3. 116
      Driver/Core/MongoUser.cs
  4. 1
      Driver/Driver.csproj
  5. 22
      DriverOnlineTests/Core/MongoDatabaseTests.cs

35
BsonUnitTests/ObjectModel/BsonValueTests.cs

@ -34,16 +34,18 @@ namespace MongoDB.BsonUnitTests {
Assert.Throws<InvalidCastException>(() => { var x = s.AsBoolean; });
}
[Test]
public void TestAsBsonArray() {
BsonValue v = new BsonArray { 1, 2 };
BsonValue s = "";
var a = v.AsBsonArray;
Assert.AreEqual(2, a.Count);
Assert.AreEqual(1, a[0]);
Assert.AreEqual(2, a[1]);
Assert.AreEqual(1, a[0].AsInt32);
Assert.AreEqual(2, a[1].AsInt32);
Assert.Throws<InvalidCastException>(() => { var x = s.AsBsonArray; });
}
[Test]
public void TestAsBinaryData() {
BsonValue v = new byte[] { 1, 2 };
BsonValue s = "";
@ -55,6 +57,7 @@ namespace MongoDB.BsonUnitTests {
Assert.Throws<InvalidCastException>(() => { var x = s.AsBsonBinaryData; });
}
[Test]
public void TestAsBsonDocument() {
BsonValue v = new BsonDocument("x", 1);
BsonValue s = "";
@ -65,6 +68,7 @@ namespace MongoDB.BsonUnitTests {
Assert.Throws<InvalidCastException>(() => { var x = s.AsBsonDocument; });
}
[Test]
public void TestAsBsonJavaScript() {
BsonValue v = new BsonJavaScript("code");
BsonValue s = "";
@ -73,6 +77,7 @@ namespace MongoDB.BsonUnitTests {
Assert.Throws<InvalidCastException>(() => { var x = s.AsBsonJavaScript; });
}
[Test]
public void TestAsBsonJavaScriptWithScode() {
var scope = new BsonDocument("x", 1);
BsonValue s = "";
@ -80,12 +85,13 @@ namespace MongoDB.BsonUnitTests {
var js = v.AsBsonJavaScriptWithScope;
Assert.AreEqual("code", js.Code);
Assert.AreEqual(1, js.Scope.ElementCount);
Assert.AreEqual("name", js.Scope.GetElement(0).Name);
Assert.AreEqual(1, js.Scope["name"].AsInt32);
Assert.AreEqual("x", js.Scope.GetElement(0).Name);
Assert.AreEqual(1, js.Scope["x"].AsInt32);
Assert.AreSame(v.AsBsonJavaScript, v.AsBsonJavaScriptWithScope);
Assert.Throws<InvalidCastException>(() => { var x = s.AsBsonJavaScriptWithScope; });
}
[Test]
public void TestAsBsonMaxKey() {
BsonValue v = BsonMaxKey.Value;
BsonValue s = "";
@ -94,6 +100,7 @@ namespace MongoDB.BsonUnitTests {
Assert.Throws<InvalidCastException>(() => { var x = s.AsBsonMaxKey; });
}
[Test]
public void TestAsBsonMinKey() {
BsonValue v = BsonMinKey.Value;
BsonValue s = "";
@ -102,6 +109,7 @@ namespace MongoDB.BsonUnitTests {
Assert.Throws<InvalidCastException>(() => { var x = s.AsBsonMinKey; });
}
[Test]
public void TestAsBsonNull() {
BsonValue v = BsonNull.Value;
BsonValue s = "";
@ -110,6 +118,7 @@ namespace MongoDB.BsonUnitTests {
Assert.Throws<InvalidCastException>(() => { var x = s.AsBsonNull; });
}
[Test]
public void TestAsBsonRegularExpression() {
BsonValue v = new BsonRegularExpression("pattern", "options");
BsonValue s = "";
@ -119,6 +128,7 @@ namespace MongoDB.BsonUnitTests {
Assert.Throws<InvalidCastException>(() => { var x = s.AsBsonRegularExpression; });
}
[Test]
public void TestAsBsonSymbol() {
BsonValue v = BsonSymbol.Create("name");
BsonValue s = "";
@ -127,6 +137,7 @@ namespace MongoDB.BsonUnitTests {
Assert.Throws<InvalidCastException>(() => { var x = s.AsBsonSymbol; });
}
[Test]
public void TestAsBsonTimestamp() {
BsonValue v = new BsonTimestamp(1234);
BsonValue s = "";
@ -135,6 +146,7 @@ namespace MongoDB.BsonUnitTests {
Assert.Throws<InvalidCastException>(() => { var x = s.AsBsonTimestamp; });
}
[Test]
public void TestAsByteArray() {
BsonValue v = new byte[] { 1, 2 };
BsonValue s = "";
@ -145,6 +157,7 @@ namespace MongoDB.BsonUnitTests {
Assert.Throws<InvalidCastException>(() => { var x = s.AsByteArray; });
}
[Test]
public void TestAsDateTime() {
var utcNow = DateTime.UtcNow;
BsonValue v = utcNow;
@ -154,6 +167,7 @@ namespace MongoDB.BsonUnitTests {
Assert.Throws<InvalidCastException>(() => { var x = s.AsDateTime; });
}
[Test]
public void TestAsDouble() {
BsonValue v = 1.5;
BsonValue s = "";
@ -162,6 +176,7 @@ namespace MongoDB.BsonUnitTests {
Assert.Throws<InvalidCastException>(() => { var x = s.AsDouble; });
}
[Test]
public void TestAsGuid() {
var guid = Guid.NewGuid();
BsonValue v = guid;
@ -171,6 +186,7 @@ namespace MongoDB.BsonUnitTests {
Assert.Throws<InvalidCastException>(() => { var x = s.AsGuid; });
}
[Test]
public void TestAsInt32() {
BsonValue v = 1;
BsonValue s = "";
@ -179,6 +195,7 @@ namespace MongoDB.BsonUnitTests {
Assert.Throws<InvalidCastException>(() => { var x = s.AsInt32; });
}
[Test]
public void TestAsInt64() {
BsonValue v = 1L;
BsonValue s = "";
@ -260,6 +277,7 @@ namespace MongoDB.BsonUnitTests {
Assert.Throws<InvalidCastException>(() => { var x = s.AsNullableObjectId; });
}
[Test]
public void TestAsObjectId() {
var objectId = ObjectId.GenerateNewId();
BsonValue v = objectId;
@ -269,14 +287,16 @@ namespace MongoDB.BsonUnitTests {
Assert.Throws<InvalidCastException>(() => { var x = s.AsObjectId; });
}
[Test]
public void TestAsRegexOptionNone() {
BsonValue v = new BsonRegularExpression("xyz");
BsonValue s = "";
var r = v.AsRegex;
Assert.AreEqual(0, r.Options);
Assert.AreEqual(RegexOptions.None, r.Options);
Assert.Throws<InvalidCastException>(() => { var x = s.AsRegex; });
}
[Test]
public void TestAsRegexOptionAll() {
BsonValue v = new BsonRegularExpression("xyz", "imxs");
BsonValue s = "";
@ -285,6 +305,7 @@ namespace MongoDB.BsonUnitTests {
Assert.Throws<InvalidCastException>(() => { var x = s.AsRegex; });
}
[Test]
public void TestAsRegexOptionI() {
BsonValue v = new BsonRegularExpression("xyz", "i");
BsonValue s = "";
@ -293,6 +314,7 @@ namespace MongoDB.BsonUnitTests {
Assert.Throws<InvalidCastException>(() => { var x = s.AsRegex; });
}
[Test]
public void TestAsRegexOptionM() {
BsonValue v = new BsonRegularExpression("xyz", "m");
BsonValue s = "";
@ -301,6 +323,7 @@ namespace MongoDB.BsonUnitTests {
Assert.Throws<InvalidCastException>(() => { var x = s.AsRegex; });
}
[Test]
public void TestAsRegexOptionX() {
BsonValue v = new BsonRegularExpression("xyz", "x");
BsonValue s = "";
@ -309,6 +332,7 @@ namespace MongoDB.BsonUnitTests {
Assert.Throws<InvalidCastException>(() => { var x = s.AsRegex; });
}
[Test]
public void TestAsRegexOptionS() {
BsonValue v = new BsonRegularExpression("xyz", "s");
BsonValue s = "";
@ -317,6 +341,7 @@ namespace MongoDB.BsonUnitTests {
Assert.Throws<InvalidCastException>(() => { var x = s.AsRegex; });
}
[Test]
public void TestAsString() {
BsonValue v = "Hello";
BsonValue i = 1;

70
Driver/Core/MongoDatabase.cs

@ -257,15 +257,26 @@ namespace MongoDB.Driver {
public virtual void AddUser(
MongoCredentials credentials,
bool readOnly
) {
var user = new MongoUser(credentials, readOnly);
AddUser(user);
}
/// <summary>
/// Adds a user to this database.
/// </summary>
/// <param name="user">The user.</param>
public virtual void AddUser(
MongoUser user
) {
var users = GetCollection("system.users");
var user = users.FindOne(Query.EQ("user", credentials.Username));
if (user == null) {
user = new BsonDocument("user", credentials.Username);
var document = users.FindOne(Query.EQ("user", user.Username));
if (document == null) {
document = new BsonDocument("user", user.Username);
}
user["readOnly"] = readOnly;
user["pwd"] = MongoUtils.Hash(credentials.Username + ":mongo:" + credentials.Password);
users.Save(user);
document["readOnly"] = user.IsReadOnly;
document["pwd"] = user.PasswordHash;
users.Save(document);
}
/// <summary>
@ -441,6 +452,43 @@ namespace MongoDB.Driver {
return collection.FindOneAs(documentType, query);
}
/// <summary>
/// Finds all users of this database.
/// </summary>
/// <returns>An array of users.</returns>
public virtual MongoUser[] FindAllUsers() {
var result = new List<MongoUser>();
var users = GetCollection("system.users");
foreach (var document in users.FindAll()) {
var username = document["user"].AsString;
var passwordHash = document["pwd"].AsString;
var readOnly = document["readOnly"].ToBoolean();
var user = new MongoUser(username, passwordHash, readOnly);
result.Add(user);
};
return result.ToArray();
}
/// <summary>
/// Finds a user of this database.
/// </summary>
/// <param name="username">The username.</param>
/// <returns>The user.</returns>
public virtual MongoUser FindUser(
string username
) {
var users = GetCollection("system.users");
var query = Query.EQ("user", username);
var document = users.FindOne(query);
if (document != null) {
var passwordHash = document["pwd"].AsString;
var readOnly = document["readOnly"].ToBoolean();
return new MongoUser(username, passwordHash, readOnly);
} else {
return null;
}
}
/// <summary>
/// Gets a MongoCollection instance representing a collection on this database
/// with a default document type of TDefaultDocument.
@ -637,6 +685,16 @@ namespace MongoDB.Driver {
// TODO: mongo shell has IsMaster at database level?
/// <summary>
/// Removes a user from this database.
/// </summary>
/// <param name="user">The user to remove.</param>
public virtual void RemoveUser(
MongoUser user
) {
RemoveUser(user.Username);
}
/// <summary>
/// Removes a user from this database.
/// </summary>

116
Driver/Core/MongoUser.cs

@ -0,0 +1,116 @@
/* Copyright 2010-2011 10gen Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MongoDB.Driver {
/// <summary>
/// Represents a MongoDB user.
/// </summary>
[Serializable]
public class MongoUser {
#region private fields
private string username;
private string passwordHash;
private bool isReadOnly;
#endregion
#region constructors
/// <summary>
/// Creates a new instance of MongoUser.
/// </summary>
/// <param name="credentials">The user's credentials.</param>
/// <param name="isReadOnly">Whether the user has read-only access.</param>
public MongoUser(
MongoCredentials credentials,
bool isReadOnly
) {
this.username = credentials.Username;
this.passwordHash = HashPassword(credentials.Username, credentials.Password);
this.isReadOnly = isReadOnly;
}
/// <summary>
/// Creates a new instance of MongoUser.
/// </summary>
/// <param name="username">The username.</param>
/// <param name="passwordHash">The password hash.</param>
/// <param name="isReadOnly">Whether the user has read-only access.</param>
public MongoUser(
string username,
string passwordHash,
bool isReadOnly
) {
this.username = username;
this.passwordHash = passwordHash;
this.isReadOnly = isReadOnly;
}
#endregion
#region public properties
/// <summary>
/// Gets or sets the username.
/// </summary>
public string Username {
get { return username; }
set { username = value; }
}
/// <summary>
/// Gets or sets the password hash.
/// </summary>
public string PasswordHash {
get { return passwordHash; }
set { passwordHash = value; }
}
/// <summary>
/// Gets or sets whether the user is a read-only user.
/// </summary>
public bool IsReadOnly {
get { return isReadOnly; }
set { isReadOnly = value; }
}
#endregion
#region public static methods
/// <summary>
/// Calculates the password hash.
/// </summary>
/// <param name="username">The username.</param>
/// <param name="password">The password.</param>
/// <returns></returns>
public static string HashPassword(
string username,
string password
) {
return MongoUtils.Hash(username + ":mongo:" + password);
}
#endregion
#region public methods
/// <summary>
/// Returns a string representation of the credentials.
/// </summary>
/// <returns>A string representation of the user.</returns>
public override string ToString() {
return string.Format("User:{0}", username);
}
#endregion
}
}

1
Driver/Driver.csproj

@ -117,6 +117,7 @@
<Compile Include="Core\MongoServerInstance.cs" />
<Compile Include="Core\MongoServerSettings.cs" />
<Compile Include="Core\MongoUrlBuilder.cs" />
<Compile Include="Core\MongoUser.cs" />
<Compile Include="Core\Wrappers\BaseWrapper.cs" />
<Compile Include="Core\Wrappers\CollectionOptionsDocument.cs" />
<Compile Include="Core\Wrappers\CollectionOptionsWrapper.cs" />

22
DriverOnlineTests/Core/MongoDatabaseTests.cs

@ -133,5 +133,27 @@ namespace MongoDB.DriverOnlineTests {
Assert.IsFalse(database.CollectionExists(collectionName1));
Assert.IsTrue(database.CollectionExists(collectionName2));
}
[Test]
public void TestUserMethods() {
var collection = database["system.users"];
collection.RemoveAll();
database.AddUser(new MongoCredentials("username", "password"), true);
Assert.AreEqual(1, collection.Count());
var user = database.FindUser("username");
Assert.AreEqual("username", user.Username);
Assert.AreEqual(MongoUtils.Hash("username:mongo:password"), user.PasswordHash);
Assert.AreEqual(true, user.IsReadOnly);
var users = database.FindAllUsers();
Assert.AreEqual(1, users.Length);
Assert.AreEqual("username", users[0].Username);
Assert.AreEqual(MongoUtils.Hash("username:mongo:password"), users[0].PasswordHash);
Assert.AreEqual(true, users[0].IsReadOnly);
database.RemoveUser(user);
Assert.AreEqual(0, collection.Count());
}
}
}
Loading…
Cancel
Save