diff --git a/.gitignore b/.gitignore index 81b9783..fe45744 100644 --- a/.gitignore +++ b/.gitignore @@ -107,3 +107,4 @@ _UpgradeReport_Files/ Backup*/ UpgradeLog*.XML MongoDB.AspNet.Identity.csproj.GhostDoc.xml +*.lock.json diff --git a/IdentityDbContext.cs b/IdentityDbContext.cs deleted file mode 100644 index 9100274..0000000 --- a/IdentityDbContext.cs +++ /dev/null @@ -1,125 +0,0 @@ -using System; -using System.Configuration; -using System.Linq; -using MongoDB.Driver; - -namespace MongoDB.AspNet.Identity -{ - public class IdentityDbContext : IdentityDbContext - where TUser : IdentityUser - { - public IdentityDbContext() : this("DefaultConnection") { } - public IdentityDbContext(string nameOrConnectionString) : base(nameOrConnectionString) { } - } - - public class IdentityDbContext : IdentityDbContext - { - public IdentityDbContext() : this("DefaultConnection") { } - public IdentityDbContext(string nameOrConnectionString) : base(nameOrConnectionString) { } - } - - public class IdentityDbContext : IDisposable - where TUser : IdentityUser - where TRole : IdentityRole - where TUserLogin : IdentityUserLogin - where TUserRole : IdentityUserRole - where TUserClaim : IdentityUserClaim - { - - internal readonly MongoDatabase db; - - public MongoDatabase Context { get { return db; } } - - - /// - /// Gets the database from connection string. - /// - /// The connection string. - /// MongoDatabase. - /// No database name specified in connection string - private MongoDatabase GetDatabaseFromSqlStyle(string connectionString) - { - var conString = new MongoConnectionStringBuilder(connectionString); - MongoClientSettings settings = MongoClientSettings.FromConnectionStringBuilder(conString); - MongoServer server = new MongoClient(settings).GetServer(); - if (conString.DatabaseName == null) - { - throw new Exception("No database name specified in connection string"); - } - return server.GetDatabase(conString.DatabaseName); - } - - /// - /// Gets the database from URL. - /// - /// The URL. - /// MongoDatabase. - private MongoDatabase GetDatabaseFromUrl(MongoUrl url) - { - var client = new MongoClient(url); - MongoServer server = client.GetServer(); - if (url.DatabaseName == null) - { - throw new Exception("No database name specified in connection string"); - } - return server.GetDatabase(url.DatabaseName); // WriteConcern defaulted to Acknowledged - } - - /// - /// Uses connectionString to connect to server and then uses databae name specified. - /// - /// The connection string. - /// Name of the database. - /// MongoDatabase. - private MongoDatabase GetDatabase(string connectionString, string dbName) - { - var client = new MongoClient(connectionString); - MongoServer server = client.GetServer(); - return server.GetDatabase(dbName); - } - - public bool RequireUniqueEmail - { - get; - set; - } - - public virtual IQueryable Roles - { - get; - set; - } - - public virtual IQueryable Users - { - get; - set; - } - - public IdentityDbContext() : this("DefaultConnection") { } - public IdentityDbContext(string nameOrConnectionString) - { - if (nameOrConnectionString.ToLower().StartsWith("mongodb://")) - { - db = GetDatabaseFromUrl(new MongoUrl(nameOrConnectionString)); - } - else - { - string connStringFromManager = - ConfigurationManager.ConnectionStrings[nameOrConnectionString].ConnectionString; - if (connStringFromManager.ToLower().StartsWith("mongodb://")) - { - db = GetDatabaseFromUrl(new MongoUrl(connStringFromManager)); - } - else - { - db = GetDatabaseFromSqlStyle(connStringFromManager); - } - } - } - - public void Dispose() - { - } - } -} \ No newline at end of file diff --git a/IdentityRole.cs b/IdentityRole.cs deleted file mode 100644 index 3a6494c..0000000 --- a/IdentityRole.cs +++ /dev/null @@ -1,42 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using Microsoft.AspNet.Identity; - -namespace MongoDB.AspNet.Identity -{ - public class IdentityRole : IdentityRole - { - public IdentityRole() - { - base.Id = Guid.NewGuid().ToString(); - } - - public IdentityRole(string roleName) - : this() - { - base.Name = roleName; - } - } - - - public class IdentityRole : IRole - where TUserRole : IdentityUserRole - { - public TKey Id { get; set; } - public string Name { get; set; } - - public ICollection Users { get; set; } - - public virtual ICollection GetUsers() - { - return Users; - } - - public IdentityRole() - { - Users = new List(); - } - - } -} \ No newline at end of file diff --git a/MongoDB.AspNet.Identity.csproj b/MongoDB.AspNet.Identity.csproj deleted file mode 100644 index f933717..0000000 --- a/MongoDB.AspNet.Identity.csproj +++ /dev/null @@ -1,114 +0,0 @@ - - - - - Debug - AnyCPU - - - 2.0 - {0FF87680-235F-4231-8302-9BF6FCAC7476} - {349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} - Library - Properties - MongoDB.AspNet.Identity - MongoDB.AspNet.Identity - v4.5 - true - - - - - - - - true - full - false - bin\ - DEBUG;TRACE - prompt - 4 - bin\MongoDB.AspNet.Identity.XML - - - pdbonly - true - bin\ - TRACE - prompt - 4 - bin\MongoDB.AspNet.Identity.XML - - - - False - ..\Test.MongoDB.AspNet.Identity\packages\Microsoft.AspNet.Identity.Core.2.0.1\lib\net45\Microsoft.AspNet.Identity.Core.dll - - - False - ..\Test.MongoDB.AspNet.Identity\packages\mongocsharpdriver.1.9.1\lib\net35\MongoDB.Bson.dll - - - False - ..\Test.MongoDB.AspNet.Identity\packages\mongocsharpdriver.1.9.1\lib\net35\MongoDB.Driver.dll - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 10.0 - $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) - - - - - - - - - True - True - 50949 - / - http://localhost:50890/ - False - False - - - False - - - - - - \ No newline at end of file diff --git a/MongoDB.AspNet.Identity.sln b/MongoDB.AspNet.Identity.sln index 0a3afb8..df08888 100644 --- a/MongoDB.AspNet.Identity.sln +++ b/MongoDB.AspNet.Identity.sln @@ -1,9 +1,18 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2013 -VisualStudioVersion = 12.0.21005.1 +# Visual Studio 14 +VisualStudioVersion = 14.0.22310.1 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MongoDB.AspNet.Identity", "MongoDB.AspNet.Identity.csproj", "{0FF87680-235F-4231-8302-9BF6FCAC7476}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{41B2DD81-2BF4-49FD-BCC6-47850D1189AD}" +EndProject +Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "MongoDB.AspNet.Identity", "src\MongoDB.AspNet.Identity\MongoDB.AspNet.Identity.kproj", "{2BE4366F-4B07-47AA-98F6-D09E603A2F11}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{408E6EB1-E05A-408F-92CA-944467BA05C9}" + ProjectSection(SolutionItems) = preProject + global.json = global.json + LICENSE = LICENSE + README.md = README.md + EndProjectSection EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -11,12 +20,15 @@ Global Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {0FF87680-235F-4231-8302-9BF6FCAC7476}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {0FF87680-235F-4231-8302-9BF6FCAC7476}.Debug|Any CPU.Build.0 = Debug|Any CPU - {0FF87680-235F-4231-8302-9BF6FCAC7476}.Release|Any CPU.ActiveCfg = Release|Any CPU - {0FF87680-235F-4231-8302-9BF6FCAC7476}.Release|Any CPU.Build.0 = Release|Any CPU + {2BE4366F-4B07-47AA-98F6-D09E603A2F11}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2BE4366F-4B07-47AA-98F6-D09E603A2F11}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2BE4366F-4B07-47AA-98F6-D09E603A2F11}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2BE4366F-4B07-47AA-98F6-D09E603A2F11}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {2BE4366F-4B07-47AA-98F6-D09E603A2F11} = {41B2DD81-2BF4-49FD-BCC6-47850D1189AD} + EndGlobalSection EndGlobal diff --git a/Properties/AssemblyInfo.cs b/Properties/AssemblyInfo.cs deleted file mode 100644 index d2dbc86..0000000 --- a/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("MongoDB.AspNet.Identity")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("InspectorIT by Jonathan Sheely")] -[assembly: AssemblyProduct("MongoDB.AspNet.Identity")] -[assembly: AssemblyCopyright("Copyright © 2014")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("9e1632ab-d097-465f-a9a6-9285d24d008a")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Revision and Build Numbers -// by using the '*' as shown below: -[assembly: AssemblyVersion("1.0.5.0")] -[assembly: AssemblyFileVersion("1.0.5.0")] diff --git a/README.md b/README.md index 6fee9f9..c127a77 100644 --- a/README.md +++ b/README.md @@ -88,3 +88,41 @@ UserStore(string connectionNameOrUrl) ## Thanks To ## Special thanks to [David Boike](https://github.com/DavidBoike) whos [RavenDB AspNet Identity](https://github.com/ILMServices/RavenDB.AspNet.Identity) project gave me the base for jumpstarting the MongoDB provider + + +## ASP.Net vNext update ## +Simple use with MVC6 (not tested on Mono) + +Instrucitons + +1. create new MVC6 website in VisualStudio 2015 preview (current template does not have full featured Identity Example, it still works - use IdentitySample from aspnet/Identity repo) +2. follow above instruction +3. fix 1.In ~/Models/IdentityModels.cs from above instruction +4. no change to account controller +5. comment/delete entityframework sql and wire up mongodb in startup.cs, use connectionstring in above format (no webconfig here, you can add local json configuration file in asp.net mvc) +* Remove the namespace: Microsoft.AspNet.Identity.EntityFramework +* Add the namespace: MongoDB.AspNet.Identity + +```C# +public void ConfigureServices(IServiceCollection services) +{ + + //services.AddEntityFramework() + // .AddSqlServer() + // .AddDbContext(options => options.UseSqlServer(Configuration.Get("Data:IdentityConnection:ConnectionString"))); + + //services.Configure(options => + //{ + // options.DefaultAdminUserName = Configuration.Get("DefaultAdminUsername"); + // options.DefaultAdminPassword = Configuration.Get("DefaultAdminPassword"); + //}); + + services.UseMongoDB(i => i.ConnectionString = conenctionString); + + //................ + services.AddMvc(); + +} +``` + + diff --git a/RoleStore.cs b/RoleStore.cs deleted file mode 100644 index 74f75aa..0000000 --- a/RoleStore.cs +++ /dev/null @@ -1,119 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Linq; -using System.Runtime.CompilerServices; -using System.Threading.Tasks; -using System.Web; -using Microsoft.AspNet.Identity; -using MongoDB.Bson; -using MongoDB.Driver; -using MongoDB.Driver.Builders; - -namespace MongoDB.AspNet.Identity -{ - - - public class RoleStore : RoleStore, IQueryableRoleStore, IQueryableRoleStore, IRoleStore, IDisposable - where TRole : IdentityRole, new() - { - public RoleStore() : base(new IdentityDbContext().db) { } - } - - public class RoleStore : IQueryableRoleStore, IRoleStore, IDisposable - where TRole : IdentityRole, new() - where TUserRole : IdentityUserRole, new() - { - private bool _disposed; - - private readonly MongoDatabase db; - private const string collectionName = "AspNetRoles"; - - - public RoleStore(MongoDatabase context) - { - db = context; - } - - public bool DisposeContext - { - get; - set; - } - - public IQueryable Roles - { - get { return db.GetCollection(collectionName).FindAll().AsQueryable(); } - } - - - public virtual async Task CreateAsync(TRole role) - { - this.ThrowIfDisposed(); - if (role == null) - { - throw new ArgumentNullException("role"); - } - - db.GetCollection(collectionName).Insert(role); - - } - - public virtual async Task DeleteAsync(TRole role) - { - this.ThrowIfDisposed(); - if (role == null) - { - throw new ArgumentNullException("role"); - } - - db.GetCollection(collectionName).Remove((Query.EQ("_id", ObjectId.Parse(role.Id.ToString())))); - } - - public void Dispose() - { - this.Dispose(true); - GC.SuppressFinalize(this); - } - - protected virtual void Dispose(bool disposing) - { - _disposed = true; - } - - public Task FindByIdAsync(TKey roleId) - { - this.ThrowIfDisposed(); - TRole role = db.GetCollection(collectionName).FindOne((Query.EQ("_id", ObjectId.Parse(roleId.ToString())))); - return Task.FromResult(role); - } - - public Task FindByNameAsync(string roleName) - { - this.ThrowIfDisposed(); - TRole role = db.GetCollection(collectionName).FindOne((Query.EQ("Name", roleName))); - return Task.FromResult(role); - } - - private void ThrowIfDisposed() - { - if (this._disposed) - { - throw new ObjectDisposedException(this.GetType().Name); - } - } - - public virtual async Task UpdateAsync(TRole role) - { - this.ThrowIfDisposed(); - if (role == null) - { - throw new ArgumentNullException("role"); - } - - db.GetCollection(collectionName).Update(Query.EQ("_id", ObjectId.Parse(role.Id.ToString())), Update.Replace(role), UpdateFlags.Upsert); - - - } - } -} \ No newline at end of file diff --git a/UserStore.cs b/UserStore.cs deleted file mode 100644 index bd5dded..0000000 --- a/UserStore.cs +++ /dev/null @@ -1,652 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Security.Claims; -using System.Threading.Tasks; -using Microsoft.AspNet.Identity; -using MongoDB.Bson; -using MongoDB.Driver; -using MongoDB.Driver.Builders; - -namespace MongoDB.AspNet.Identity -{ - - /// - /// Class UserStore. - /// - /// The type of the t user. - public class UserStore : UserStore, IUserStore, IUserStore, IDisposable - where TUser : IdentityUser - { - /// - /// Initializes a new instance of the class. - /// - /// The context. - public UserStore(IdentityDbContext context) : base(context.db) { } - /// - /// Initializes a new instance of the class. - /// - /// The database. - public UserStore(MongoDatabase db) : base(db) { } - } - - - - /// - /// Class UserStore. - /// - /// The type of the t user. - /// The type of the t role. - /// The type of the t key. - /// The type of the t user login. - /// The type of the t user role. - /// The type of the t user claim. - public class UserStore : IUserLoginStore, IUserClaimStore, IUserRoleStore, IUserPasswordStore, IUserSecurityStampStore, IQueryableUserStore, IUserEmailStore, IUserPhoneNumberStore, IUserTwoFactorStore, IUserStore, IDisposable - where TUser : IdentityUser - where TRole : IdentityRole - where TKey : IEquatable - where TUserLogin : IdentityUserLogin, new() - where TUserRole : IdentityUserRole, new() - where TUserClaim : IdentityUserClaim, new() - { - #region Private Methods & Variables - - - - /// - /// The database - /// - private readonly MongoDatabase db; - - /// - /// The _disposed - /// - private bool _disposed; - - /// - /// The AspNetUsers collection name - /// - private const string collectionName = "AspNetUsers"; - - - #endregion - - #region Constructors - - /// - /// Initializes a new instance of the class. - /// - public UserStore(): this(new IdentityDbContext().db) {} - - /// - /// Initializes a new instance of the class. - /// - /// The context. - public UserStore(MongoDatabase context) - { - db = context; - } - - - #endregion - - #region Methods - - /// - /// Adds the claim asynchronous. - /// - /// The user. - /// The claim. - /// Task. - /// user - public Task AddClaimAsync(TUser user, Claim claim) - { - ThrowIfDisposed(); - if (user == null) - throw new ArgumentNullException("user"); - - if (!user.Claims.Any(x => x.ClaimType == claim.Type && x.ClaimValue == claim.Value)) - { - user.Claims.Add(new IdentityUserClaim - { - ClaimType = claim.Type, - ClaimValue = claim.Value - }); - } - - - return Task.FromResult(0); - } - - /// - /// Gets the claims asynchronous. - /// - /// The user. - /// Task{IList{Claim}}. - /// user - public Task> GetClaimsAsync(TUser user) - { - ThrowIfDisposed(); - if (user == null) - throw new ArgumentNullException("user"); - - IList result = user.Claims.Select(c => new Claim(c.ClaimType, c.ClaimValue)).ToList(); - return Task.FromResult(result); - } - - /// - /// Removes the claim asynchronous. - /// - /// The user. - /// The claim. - /// Task. - /// user - public Task RemoveClaimAsync(TUser user, Claim claim) - { - ThrowIfDisposed(); - if (user == null) - throw new ArgumentNullException("user"); - - user.Claims.RemoveAll(x => x.ClaimType == claim.Type && x.ClaimValue == claim.Value); - return Task.FromResult(0); - } - - - /// - /// Creates the user asynchronous. - /// - /// The user. - /// Task. - /// user - public Task CreateAsync(TUser user) - { - ThrowIfDisposed(); - if (user == null) - throw new ArgumentNullException("user"); - - db.GetCollection(collectionName).Insert(user); - - return Task.FromResult(user); - } - - /// - /// Deletes the user asynchronous. - /// - /// The user. - /// Task. - /// user - public Task DeleteAsync(TUser user) - { - ThrowIfDisposed(); - if (user == null) - throw new ArgumentNullException("user"); - - db.GetCollection(collectionName).Remove((Query.EQ("_id", ObjectId.Parse(user.Id.ToString())))); - return Task.FromResult(true); - } - - /// - /// Finds the by identifier asynchronous. - /// - /// The user identifier. - /// Task{`0}. - public Task FindByIdAsync(TKey userId) - { - ThrowIfDisposed(); - TUser user = db.GetCollection(collectionName).FindOne((Query.EQ("_id", ObjectId.Parse(userId.ToString())))); - return Task.FromResult(user); - } - - /// - /// Finds the by identifier asynchronous. - /// - /// The user identifier. - /// Task{`0}. - public Task FindByIdAsync(string userId) - { - ThrowIfDisposed(); - TUser user = db.GetCollection(collectionName).FindOne((Query.EQ("_id", ObjectId.Parse(userId)))); - return Task.FromResult(user); - } - - /// - /// Finds the by name asynchronous. - /// - /// Name of the user. - /// Task{`0}. - public Task FindByNameAsync(string userName) - { - ThrowIfDisposed(); - - TUser user = db.GetCollection(collectionName).FindOne((Query.EQ("UserName", userName))); - return Task.FromResult(user); - } - - /// - /// Sets the email confirmed asynchronous. - /// - /// The user. - /// if set to true [confirmed]. - /// Task. - /// - public Task SetEmailConfirmedAsync(TUser user, bool confirmed) - { - throw new NotImplementedException(); - } - - /// - /// Finds the by email asynchronous. - /// - /// The email. - /// Task{`0}. - public Task FindByEmailAsync(string email) - { - ThrowIfDisposed(); - - TUser user = db.GetCollection(collectionName).FindOne((Query.EQ("Email", email))); - return Task.FromResult(user); - } - - /// - /// Sets the email asynchronous. - /// - /// The user. - /// The email. - /// Task. - /// - public Task SetEmailAsync(TUser user, string email) - { - throw new NotImplementedException(); - } - - /// - /// Gets the email asynchronous. - /// - /// The user. - /// Task{System.String}. - /// user - public Task GetEmailAsync(TUser user) - { - ThrowIfDisposed(); - if (user == null) - { - throw new ArgumentException("user"); - } - return Task.FromResult(user.Email); - } - - /// - /// Gets the email confirmed asynchronous. - /// - /// The user. - /// Task{System.Boolean}. - /// - public Task GetEmailConfirmedAsync(TUser user) - { - throw new NotImplementedException(); - } - - /// - /// Updates the user asynchronous. - /// - /// The user. - /// Task. - /// user - public Task UpdateAsync(TUser user) - { - ThrowIfDisposed(); - if (user == null) - throw new ArgumentNullException("user"); - - db.GetCollection(collectionName).Update(Query.EQ("_id", ObjectId.Parse(user.Id.ToString())), Update.Replace(user), UpdateFlags.Upsert); - - return Task.FromResult(user); - } - - /// - /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. - /// - public void Dispose() - { - _disposed = true; - } - - /// - /// Adds the login asynchronous. - /// - /// The user. - /// The login. - /// Task. - /// user - public Task AddLoginAsync(TUser user, UserLoginInfo login) - { - ThrowIfDisposed(); - if (user == null) - throw new ArgumentNullException("user"); - - if (!user.Logins.Any(x => x.LoginProvider == login.LoginProvider && x.ProviderKey == login.ProviderKey)) - { - user.Logins.Add(login); - } - - return Task.FromResult(true); - } - - /// - /// Finds the user asynchronous. - /// - /// The login. - /// Task{`0}. - public Task FindAsync(UserLoginInfo login) - { - TUser user = null; - user = - db.GetCollection(collectionName) - .FindOne(Query.And(Query.EQ("Logins.LoginProvider", login.LoginProvider), - Query.EQ("Logins.ProviderKey", login.ProviderKey))); - - return Task.FromResult(user); - } - - /// - /// Gets the logins asynchronous. - /// - /// The user. - /// Task{IList{UserLoginInfo}}. - /// user - public Task> GetLoginsAsync(TUser user) - { - ThrowIfDisposed(); - if (user == null) - throw new ArgumentNullException("user"); - - return Task.FromResult(user.Logins.ToIList()); - } - - /// - /// Removes the login asynchronous. - /// - /// The user. - /// The login. - /// Task. - /// user - public Task RemoveLoginAsync(TUser user, UserLoginInfo login) - { - ThrowIfDisposed(); - if (user == null) - throw new ArgumentNullException("user"); - - user.Logins.RemoveAll(x => x.LoginProvider == login.LoginProvider && x.ProviderKey == login.ProviderKey); - - return Task.FromResult(0); - } - - /// - /// Gets the password hash asynchronous. - /// - /// The user. - /// Task{System.String}. - /// user - public Task GetPasswordHashAsync(TUser user) - { - ThrowIfDisposed(); - if (user == null) - throw new ArgumentNullException("user"); - - return Task.FromResult(user.PasswordHash); - } - - /// - /// Determines whether [has password asynchronous] [the specified user]. - /// - /// The user. - /// user - public Task HasPasswordAsync(TUser user) - { - ThrowIfDisposed(); - if (user == null) - throw new ArgumentNullException("user"); - - return Task.FromResult(user.PasswordHash != null); - } - - /// - /// Sets the password hash asynchronous. - /// - /// The user. - /// The password hash. - /// Task. - /// user - public Task SetPasswordHashAsync(TUser user, string passwordHash) - { - ThrowIfDisposed(); - if (user == null) - throw new ArgumentNullException("user"); - - user.PasswordHash = passwordHash; - return Task.FromResult(0); - } - - /// - /// Adds to role asynchronous. - /// - /// The user. - /// The role. - /// Task. - /// user - public Task AddToRoleAsync(TUser user, string role) - { - ThrowIfDisposed(); - if (user == null) - throw new ArgumentNullException("user"); - - if (!user.Roles.Contains(role, StringComparer.InvariantCultureIgnoreCase)) - user.Roles.Add(role); - - return Task.FromResult(true); - } - - /// - /// Gets the roles asynchronous. - /// - /// The user. - /// Task{IList{System.String}}. - /// user - public Task> GetRolesAsync(TUser user) - { - ThrowIfDisposed(); - if (user == null) - throw new ArgumentNullException("user"); - - return Task.FromResult>(user.Roles); - } - - /// - /// Determines whether [is in role asynchronous] [the specified user]. - /// - /// The user. - /// The role. - /// user - public Task IsInRoleAsync(TUser user, string role) - { - ThrowIfDisposed(); - if (user == null) - throw new ArgumentNullException("user"); - - return Task.FromResult(user.Roles.Contains(role, StringComparer.InvariantCultureIgnoreCase)); - } - - /// - /// Removes from role asynchronous. - /// - /// The user. - /// The role. - /// Task. - /// user - public Task RemoveFromRoleAsync(TUser user, string role) - { - ThrowIfDisposed(); - if (user == null) - throw new ArgumentNullException("user"); - - user.Roles.RemoveAll(r => String.Equals(r, role, StringComparison.InvariantCultureIgnoreCase)); - - return Task.FromResult(0); - } - - /// - /// Gets the security stamp asynchronous. - /// - /// The user. - /// Task{System.String}. - /// user - public Task GetSecurityStampAsync(TUser user) - { - ThrowIfDisposed(); - if (user == null) - throw new ArgumentNullException("user"); - - return Task.FromResult(user.SecurityStamp); - } - - /// - /// Sets the security stamp asynchronous. - /// - /// The user. - /// The stamp. - /// Task. - /// user - public Task SetSecurityStampAsync(TUser user, string stamp) - { - ThrowIfDisposed(); - if (user == null) - throw new ArgumentNullException("user"); - - user.SecurityStamp = stamp; - return Task.FromResult(0); - } - - /// - /// Throws if disposed. - /// - /// - private void ThrowIfDisposed() - { - if (_disposed) - throw new ObjectDisposedException(GetType().Name); - } - - #endregion - - /// - /// Gets the users. - /// - /// The users. - public IQueryable Users { get; private set; } - - /// - /// Sets the phone number asynchronous. - /// - /// The user. - /// The phone number. - /// Task. - /// user - public Task SetPhoneNumberAsync(TUser user, string phoneNumber) - { - ThrowIfDisposed(); - if (user == null) - { - throw new ArgumentException("user"); - } - - user.PhoneNumber = phoneNumber; - return Task.FromResult(0); - } - - /// - /// Gets the phone number asynchronous. - /// - /// The user. - /// Task{System.String}. - /// user - public Task GetPhoneNumberAsync(TUser user) - { - ThrowIfDisposed(); - if (user == null) - { - throw new ArgumentNullException("user"); - } - - return Task.FromResult(user.PhoneNumber); - } - - /// - /// Gets the phone number confirmed asynchronous. - /// - /// The user. - /// Task{System.Boolean}. - /// user - public Task GetPhoneNumberConfirmedAsync(TUser user) - { - ThrowIfDisposed(); - if (user == null) - { - throw new ArgumentNullException("user"); - } - return Task.FromResult(user.PhoneNumberConfirmed); - } - - /// - /// Sets the phone number confirmed asynchronous. - /// - /// The user. - /// if set to true [confirmed]. - /// Task. - /// user - public Task SetPhoneNumberConfirmedAsync(TUser user, bool confirmed) - { - ThrowIfDisposed(); - if (user == null) - { - throw new ArgumentNullException("user"); - } - user.PhoneNumberConfirmed = confirmed; - return Task.FromResult(0); - } - - /// - /// Sets the two factor enabled asynchronous. - /// - /// The user. - /// if set to true [enabled]. - /// Task. - /// user - public Task SetTwoFactorEnabledAsync(TUser user, bool enabled) - { - ThrowIfDisposed(); - if (user == null) - { - throw new ArgumentNullException("user"); - } - user.TwoFactorEnabled = enabled; - return Task.FromResult(0); - } - - /// - /// Gets the two factor enabled asynchronous. - /// - /// The user. - /// Task{System.Boolean}. - /// user - public Task GetTwoFactorEnabledAsync(TUser user) - { - ThrowIfDisposed(); - if (user == null) - { - throw new ArgumentNullException("user"); - } - return Task.FromResult(user.TwoFactorEnabled); - } - } -} - \ No newline at end of file diff --git a/global.json b/global.json new file mode 100644 index 0000000..c522a9b --- /dev/null +++ b/global.json @@ -0,0 +1,3 @@ +{ + "sources": [ "src", "test" ] +} diff --git a/nuget/MongoDB.AspNet.Identity.1.0.0.nupkg b/nuget/MongoDB.AspNet.Identity.1.0.0.nupkg deleted file mode 100644 index a251b40..0000000 Binary files a/nuget/MongoDB.AspNet.Identity.1.0.0.nupkg and /dev/null differ diff --git a/nuget/MongoDB.AspNet.Identity.1.0.1.nupkg b/nuget/MongoDB.AspNet.Identity.1.0.1.nupkg deleted file mode 100644 index fc30cc9..0000000 Binary files a/nuget/MongoDB.AspNet.Identity.1.0.1.nupkg and /dev/null differ diff --git a/nuget/MongoDB.AspNet.Identity.1.0.2.nupkg b/nuget/MongoDB.AspNet.Identity.1.0.2.nupkg deleted file mode 100644 index c5a8997..0000000 Binary files a/nuget/MongoDB.AspNet.Identity.1.0.2.nupkg and /dev/null differ diff --git a/nuget/MongoDB.AspNet.Identity.1.0.3.nupkg b/nuget/MongoDB.AspNet.Identity.1.0.3.nupkg deleted file mode 100644 index 019cb46..0000000 Binary files a/nuget/MongoDB.AspNet.Identity.1.0.3.nupkg and /dev/null differ diff --git a/nuget/MongoDB.AspNet.Identity.1.0.4.nupkg b/nuget/MongoDB.AspNet.Identity.1.0.4.nupkg deleted file mode 100644 index 79f1177..0000000 Binary files a/nuget/MongoDB.AspNet.Identity.1.0.4.nupkg and /dev/null differ diff --git a/packages.config b/packages.config deleted file mode 100644 index a0f639e..0000000 --- a/packages.config +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/src/MongoDB.AspNet.Identity/IdentityDbContext.cs b/src/MongoDB.AspNet.Identity/IdentityDbContext.cs new file mode 100644 index 0000000..02bfba0 --- /dev/null +++ b/src/MongoDB.AspNet.Identity/IdentityDbContext.cs @@ -0,0 +1,146 @@ +using System; +using System.Linq; +using MongoDB.Driver; + +namespace MongoDB.AspNet.Identity +{ + public class IdentityDbContext : IdentityDbContext//IdentityDbContext + + { + public IdentityDbContext() : base() { } //: this("DefaultConnection") { } + //public IdentityDbContext(string nameOrConnectionString) : base(nameOrConnectionString) { } + } + + public class IdentityDbContext : IdentityDbContext//IdentityDbContext +where TUser : IdentityUser + { + public IdentityDbContext() : base() { } //: this("DefaultConnection") { } + //public IdentityDbContext(string nameOrConnectionString) : base(nameOrConnectionString) { } + } + + public class IdentityDbContext : IDisposable + where TKey : IEquatable + where TUser : IdentityUser + where TRole : IdentityRole + //where TUserLogin : IdentityUserLogin + //where TUserRole : IdentityUserRole + //where TUserClaim : IdentityUserClaim + { + + private MongoDatabase db; + + public MongoDatabase Database { get { return db ?? GetDatabase(); } } + + public string ConnectionString { get; set; } + + public string DatabaseName { get; set; } + + /// + /// Gets the database from connection string. + /// + /// The connection string. + /// MongoDatabase. + /// No database name specified in connection string + private MongoDatabase GetDatabaseFromSqlStyle(string connectionString) + { + var conString = new MongoUrlBuilder(connectionString); + if (conString.DatabaseName == null) + { + throw new Exception("No database name specified in connection string"); + } + var client = new MongoClient(connectionString); + return client.GetServer().GetDatabase(conString.DatabaseName); + } + + /// + /// Gets the database from URL. + /// + /// The URL. + /// MongoDatabase. + private MongoDatabase GetDatabaseFromUrl(MongoUrl url) + { + var client = new MongoClient(url); + MongoServer server = client.GetServer(); + if (url.DatabaseName == null) + { + throw new Exception("No database name specified in connection string"); + } + return server.GetDatabase(url.DatabaseName); // WriteConcern defaulted to Acknowledged + } + + /// + /// Uses connectionString to connect to server and then uses databae name specified. + /// + /// The connection string. + /// Name of the database. + /// MongoDatabase. + private MongoDatabase GetDatabase(string connectionString, string dbName) + { + var client = new MongoClient(connectionString); + MongoServer server = client.GetServer(); + return server.GetDatabase(dbName); + } + + private MongoDatabase GetDatabase() + { + if (string.IsNullOrEmpty(ConnectionString)) + throw new InvalidOperationException("connection string not provided"); + + if (!String.IsNullOrEmpty(DatabaseName)) + { + db = GetDatabase(ConnectionString, DatabaseName); + } + else if (ConnectionString.ToLower().StartsWith("mongodb://")) + { + db = GetDatabaseFromUrl(new MongoUrl(ConnectionString)); + } + else + { + db = GetDatabaseFromSqlStyle(ConnectionString); + ////todo change this to configuration string + //string connStringFromManager = "Server=localhost:27017;Database=aspnet"; + ////ConfigurationManager.ConnectionStrings[nameOrConnectionString].ConnectionString; + //if (connStringFromManager.ToLower().StartsWith("mongodb://")) + //{ + // db = GetDatabaseFromUrl(new MongoUrl(connStringFromManager)); + //} + //else + //{ + // db = GetDatabaseFromSqlStyle(ConnectionString); + //} + } + + return db; + } + + public bool RequireUniqueEmail + { + get; + set; + } + + public virtual IQueryable Roles + { + get; + set; + } + + public virtual IQueryable Users + { + get; + set; + } + + public IdentityDbContext()//: this("DefaultConnection") { } + { } + //public IdentityDbContext(string nameOrConnectionString) + //{ + + //} + + public void Dispose() + { + //Database.Settings. + } + } +} diff --git a/src/MongoDB.AspNet.Identity/IdentityRole.cs b/src/MongoDB.AspNet.Identity/IdentityRole.cs new file mode 100644 index 0000000..266105d --- /dev/null +++ b/src/MongoDB.AspNet.Identity/IdentityRole.cs @@ -0,0 +1,55 @@ +using System; +using System.Collections.Generic; + +namespace MongoDB.AspNet.Identity +{ + public class IdentityRole : IdentityRole + { + public IdentityRole() + { + + } + + public IdentityRole(string roleName) + : this() + { + base.Name = roleName; + } + } + + + public class IdentityRole where TKey : IEquatable + { + public IdentityRole() { } + + /// + /// Constructor + /// + /// + public IdentityRole(string roleName) : this() + { + Name = roleName; + } + + /// + /// Navigation property for users in the role + /// + public virtual ICollection> Users { get; private set; } = new List>(); + + /// + /// Navigation property for claims in the role + /// + public virtual ICollection> Claims { get; private set; } = new List>(); + + /// + /// Role id + /// + public virtual TKey Id { get; set; } + + /// + /// Role name + /// + public virtual string Name { get; set; } + public virtual string NormalizedName { get; set; } + } +} \ No newline at end of file diff --git a/src/MongoDB.AspNet.Identity/IdentityRoleClaim.cs b/src/MongoDB.AspNet.Identity/IdentityRoleClaim.cs new file mode 100644 index 0000000..ea21199 --- /dev/null +++ b/src/MongoDB.AspNet.Identity/IdentityRoleClaim.cs @@ -0,0 +1,46 @@ +using MongoDB.Bson; +using MongoDB.Bson.Serialization.Attributes; + +namespace MongoDB.AspNet.Identity +{ + + + /// + /// Class IdentityRoleClaim. + /// + public class IdentityRoleClaim : IdentityRoleClaim + { + + } + + /// + /// Class IdentityRoleClaim. + /// + public class IdentityRoleClaim + { + /// + /// Gets or sets the identifier. + /// + /// The identifier. + [BsonId] + [BsonRepresentation(BsonType.ObjectId)] + public virtual string Id { get; set; } + /// + /// Gets or sets the user identifier. + /// + /// The user identifier. + public virtual TKey RoleId { get; set; } + /// + /// Gets or sets the type of the claim. + /// + /// The type of the claim. + public virtual string ClaimType { get; set; } + /// + /// Gets or sets the claim value. + /// + /// The claim value. + public virtual string ClaimValue { get; set; } + + + } +} \ No newline at end of file diff --git a/IdentityUser.cs b/src/MongoDB.AspNet.Identity/IdentityUser.cs similarity index 84% rename from IdentityUser.cs rename to src/MongoDB.AspNet.Identity/IdentityUser.cs index 71ba170..43b1f66 100644 --- a/IdentityUser.cs +++ b/src/MongoDB.AspNet.Identity/IdentityUser.cs @@ -4,19 +4,20 @@ using MongoDB.Bson; using MongoDB.Bson.Serialization.Attributes; - namespace MongoDB.AspNet.Identity { - /// /// Class IdentityUser. /// - public class IdentityUser : IdentityUser, IUser, IUser + public class IdentityUser : IdentityUser { /// /// Initializes a new instance of the class. /// - public IdentityUser() {} + public IdentityUser() + { + + } /// /// Initializes a new instance of the class. @@ -31,10 +32,7 @@ public IdentityUser(string userName) : this() /// /// Class IdentityUser. /// - public class IdentityUser : IUser - where TLogin : IdentityUserLogin - where TRole : IdentityUserRole - where TClaim : IdentityUserClaim + public class IdentityUser where TKey : IEquatable { /// /// Unique key for the user. TKey must be a string. @@ -51,6 +49,12 @@ public class IdentityUser : IUser /// The name of the user. public virtual string UserName { get; set; } + /// + /// Gets or sets the normalized name of the user. + /// + /// The normalized name of the user. + public virtual string NormalizedUserName { get; set; } + /// /// Gets or sets the password hash. /// @@ -111,11 +115,13 @@ public class IdentityUser : IUser /// The email. public virtual string Email { get; set; } - /// - /// Gets or sets a value indicating whether [email confirmed]. - /// - /// true if [email confirmed]; otherwise, false. - public virtual bool EmailConfirmed { get; set; } + public virtual string NormalizedEmail { get; set; } + + /// + /// Gets or sets a value indicating whether [email confirmed]. + /// + /// true if [email confirmed]; otherwise, false. + public virtual bool EmailConfirmed { get; set; } /// /// Gets or sets the access failed count. @@ -130,10 +136,9 @@ public class IdentityUser : IUser public virtual bool LockoutEnabled { get; set; } /// - /// Gets or sets the lockout end date UTC. + /// DateTime in UTC when lockout ends, any time in the past is considered not locked out. /// - /// The lockout end date UTC. - public virtual DateTime? LockoutEndDateUtc { get; set; } + public virtual DateTimeOffset? LockoutEnd { get; set; } /// /// Initializes a new instance of the class. diff --git a/IdentityUserClaim.cs b/src/MongoDB.AspNet.Identity/IdentityUserClaim.cs similarity index 100% rename from IdentityUserClaim.cs rename to src/MongoDB.AspNet.Identity/IdentityUserClaim.cs diff --git a/IdentityUserLogin.cs b/src/MongoDB.AspNet.Identity/IdentityUserLogin.cs similarity index 79% rename from IdentityUserLogin.cs rename to src/MongoDB.AspNet.Identity/IdentityUserLogin.cs index 043b8b2..9b34108 100644 --- a/IdentityUserLogin.cs +++ b/src/MongoDB.AspNet.Identity/IdentityUserLogin.cs @@ -1,4 +1,6 @@ -namespace MongoDB.AspNet.Identity +using System; + +namespace MongoDB.AspNet.Identity { public class IdentityUserLogin : IdentityUserLogin { @@ -7,7 +9,7 @@ public IdentityUserLogin() } } - public class IdentityUserLogin + public class IdentityUserLogin where TKey : IEquatable { public virtual string LoginProvider { diff --git a/IdentityUserRole.cs b/src/MongoDB.AspNet.Identity/IdentityUserRole.cs similarity index 75% rename from IdentityUserRole.cs rename to src/MongoDB.AspNet.Identity/IdentityUserRole.cs index 905a2f8..053b287 100644 --- a/IdentityUserRole.cs +++ b/src/MongoDB.AspNet.Identity/IdentityUserRole.cs @@ -1,4 +1,6 @@ -namespace MongoDB.AspNet.Identity +using System; + +namespace MongoDB.AspNet.Identity { @@ -9,7 +11,7 @@ public IdentityUserRole() } } - public class IdentityUserRole + public class IdentityUserRole where TKey : IEquatable { public virtual TKey RoleId { diff --git a/src/MongoDB.AspNet.Identity/MongoDB.AspNet.Identity.xproj b/src/MongoDB.AspNet.Identity/MongoDB.AspNet.Identity.xproj new file mode 100644 index 0000000..066d93f --- /dev/null +++ b/src/MongoDB.AspNet.Identity/MongoDB.AspNet.Identity.xproj @@ -0,0 +1,18 @@ + + + + 14.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + + + 2be4366f-4b07-47aa-98f6-d09e603a2f11 + MongoDB.AspNet.Identity + ..\..\artifacts\obj\$(MSBuildProjectName) + ..\..\artifacts\bin\$(MSBuildProjectName)\ + + + 2.0 + + + + \ No newline at end of file diff --git a/src/MongoDB.AspNet.Identity/MongoDBServiceCollectionExtension.cs b/src/MongoDB.AspNet.Identity/MongoDBServiceCollectionExtension.cs new file mode 100644 index 0000000..83f8096 --- /dev/null +++ b/src/MongoDB.AspNet.Identity/MongoDBServiceCollectionExtension.cs @@ -0,0 +1,32 @@ +using Microsoft.AspNet.Identity; +using Microsoft.Framework.DependencyInjection; +using MongoDB.Bson.Serialization; +using System; + +namespace MongoDB.AspNet.Identity +{ + public static class MongoDBServiceCollectionExtension + { + public static IServiceCollection UseMongoDB(this IServiceCollection services, Action configure) + where TUser : IdentityUser + { + if (configure == null) + throw new ArgumentNullException("configure"); + + BsonClassMap.LookupClassMap(typeof(ExternalLoginInfo)); + //services.AddTransient, IdentityDbContext>(); + + services.AddScoped(sp => { + var idbc = new IdentityDbContext(); + configure(idbc); + return idbc; + }); + + services.AddScoped, RoleStore>(); + services.AddScoped, UserStore>(); + services.AddIdentity(); + + return services; + } + } +} \ No newline at end of file diff --git a/src/MongoDB.AspNet.Identity/RoleStore.cs b/src/MongoDB.AspNet.Identity/RoleStore.cs new file mode 100644 index 0000000..16cb1e8 --- /dev/null +++ b/src/MongoDB.AspNet.Identity/RoleStore.cs @@ -0,0 +1,227 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Claims; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.AspNet.Identity; +using MongoDB.Bson; +using MongoDB.Driver; +using MongoDB.Driver.Builders; + +namespace MongoDB.AspNet.Identity +{ + public class RoleStore : RoleStore + where TRole : IdentityRole, new() + { + public RoleStore(IdentityDbContext context) : base(context) { } + } + + public class RoleStore : + IQueryableRoleStore, + IRoleClaimStore, + IDisposable + where TKey : IEquatable + where TRole : IdentityRole + //where TClaim : IdentityUserClaim + //where TUserRole : IdentityUserRole, new() + { + private bool _disposed; + + private readonly MongoDatabase db; + private const string collectionName = "AspNetRoles"; + + public RoleStore(IdentityDbContext context) + { + db = context.Database; + } + + public bool DisposeContext + { + get; + set; + } + + public IQueryable Roles + { + get { return db.GetCollection(collectionName).FindAll().AsQueryable(); } + } + + public IQueryable RoleClaims + { + get { return db.GetCollection(collectionName).FindAll().AsQueryable(); } + } + + public virtual Task CreateAsync(TRole role, CancellationToken cancellationToken = default(CancellationToken)) + { + this.ThrowIfDisposed(); + if (role == null) + { + throw new ArgumentNullException("role"); + } + + db.GetCollection(collectionName).Insert(role); + return Task.FromResult(IdentityResult.Success); + } + + public virtual Task DeleteAsync(TRole role, CancellationToken cancellationToken = default(CancellationToken)) + { + this.ThrowIfDisposed(); + if (role == null) + { + throw new ArgumentNullException("role"); + } + + db.GetCollection(collectionName).Remove((Query.EQ("_id", ObjectId.Parse(role.Id.ToString())))); + + return Task.FromResult(IdentityResult.Success); + } + + public void Dispose() + { + this.Dispose(true); + GC.SuppressFinalize(this); + } + + protected virtual void Dispose(bool disposing) + { + _disposed = true; + } + + public Task FindByIdAsync(TKey roleId, CancellationToken cancellationToken = default(CancellationToken)) + { + this.ThrowIfDisposed(); + //TRole role = db.GetCollection(collectionName).FindOne((Query.EQ("_id", ObjectId.Parse(roleId.ToString())))); + TRole role = Roles.FirstOrDefault(i => i.Id.Equals(roleId)); + return Task.FromResult(role); + } + + public Task FindByNameAsync(string roleName, CancellationToken cancellationToken = default(CancellationToken)) + { + this.ThrowIfDisposed(); + //TRole role = db.GetCollection(collectionName).FindOne((Query.EQ("Name", roleName))); + TRole role = Roles.FirstOrDefault(i => i.Name.Equals(roleName)); + return Task.FromResult(role); + } + + private void ThrowIfDisposed() + { + if (this._disposed) + { + throw new ObjectDisposedException(this.GetType().Name); + } + } + + public virtual Task UpdateAsync(TRole role, CancellationToken cancellationToken = default(CancellationToken)) + { + this.ThrowIfDisposed(); + if (role == null) + { + throw new ArgumentNullException("role"); + } + + db.GetCollection(collectionName).Update(Query.EQ("_id", ObjectId.Parse(role.Id.ToString())), Update.Replace(role), UpdateFlags.Upsert); + + return Task.FromResult(IdentityResult.Success); + } + + public Task GetRoleIdAsync(TRole role, CancellationToken cancellationToken = default(CancellationToken)) + { + cancellationToken.ThrowIfCancellationRequested(); + ThrowIfDisposed(); + if (role == null) + { + throw new ArgumentNullException("role"); + } + return Task.FromResult(role.Id.ToString()); + } + + public Task GetRoleNameAsync(TRole role, CancellationToken cancellationToken = default(CancellationToken)) + { + cancellationToken.ThrowIfCancellationRequested(); + ThrowIfDisposed(); + if (role == null) + { + throw new ArgumentNullException("role"); + } + return Task.FromResult(role.Name); + } + + public Task SetRoleNameAsync(TRole role, string roleName, CancellationToken cancellationToken = default(CancellationToken)) + { + cancellationToken.ThrowIfCancellationRequested(); + ThrowIfDisposed(); + if (role == null) + { + throw new ArgumentNullException("role"); + } + role.Name = roleName; + return Task.FromResult(0); + } + + public Task FindByIdAsync(string roleId, CancellationToken cancellationToken = default(CancellationToken)) + { + cancellationToken.ThrowIfCancellationRequested(); + ThrowIfDisposed(); + if (roleId == null) + { + throw new ArgumentNullException("roleId"); + } + //TRole role = db.GetCollection(collectionName).FindOne((Query.EQ("_id", ObjectId.Parse(roleId)))); + TRole role = Roles.FirstOrDefault(i => i.Id.Equals(roleId)); + return Task.FromResult(role); + } + + public Task> GetClaimsAsync(TRole role, CancellationToken cancellationToken = default(CancellationToken)) + { + ThrowIfDisposed(); + if (role == null) + throw new ArgumentNullException("role"); + + var result = RoleClaims.Where(rc => rc.Id.Equals(role.Id)).Select(c => new Claim(c.ClaimType, c.ClaimValue)).ToList(); + return Task.FromResult((IList)result); + } + + public Task AddClaimAsync(TRole role, Claim claim, CancellationToken cancellationToken = default(CancellationToken)) + { + ThrowIfDisposed(); + if (role == null) + { + throw new ArgumentNullException("role"); + } + if (claim == null) + { + throw new ArgumentNullException("claim"); + } + throw new NotImplementedException(); + } + + public Task RemoveClaimAsync(TRole role, Claim claim, CancellationToken cancellationToken = default(CancellationToken)) + { + throw new NotImplementedException(); + } + + public virtual Task GetNormalizedRoleNameAsync(TRole role, CancellationToken cancellationToken = default(CancellationToken)) + { + cancellationToken.ThrowIfCancellationRequested(); + ThrowIfDisposed(); + if (role == null) + { + throw new ArgumentNullException("role"); + } + return Task.FromResult(role.NormalizedName); + } + + public virtual Task SetNormalizedRoleNameAsync(TRole role, string normalizedName, CancellationToken cancellationToken = default(CancellationToken)) + { + cancellationToken.ThrowIfCancellationRequested(); + ThrowIfDisposed(); + if (role == null) + { + throw new ArgumentNullException("role"); + } + role.NormalizedName = normalizedName; + return Task.FromResult(0); + } + } +} \ No newline at end of file diff --git a/src/MongoDB.AspNet.Identity/UserStore.cs b/src/MongoDB.AspNet.Identity/UserStore.cs new file mode 100644 index 0000000..e50514c --- /dev/null +++ b/src/MongoDB.AspNet.Identity/UserStore.cs @@ -0,0 +1,968 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Claims; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.AspNet.Identity; +using MongoDB.Bson; +using MongoDB.Driver; +using MongoDB.Driver.Builders; +using MongoDB.Driver.Linq; + +namespace MongoDB.AspNet.Identity +{ + + /// + /// Class UserStore. + /// + /// The type of the t user. + public class UserStore : UserStore, IDisposable + where TUser : IdentityUser + + + { + /// + /// Initializes a new instance of the class. + /// The context. + /// + public UserStore(IdentityDbContext context) : base(context) + { + + } + } + + /// + /// Class UserStore. + /// + /// The type of the t user. + /// The type of the t role. + /// The type of the t key. + /// The type of the t user login. + /// The type of the t user role. + /// context to access database + + public class UserStore : + + IUserLoginStore, + IUserClaimStore, + IUserRoleStore, + IUserPasswordStore, + IUserSecurityStampStore, + IUserEmailStore, + IUserLockoutStore, + IUserPhoneNumberStore, + IQueryableUserStore, + IUserTwoFactorStore + where TKey : IEquatable + where TUser : IdentityUser + where TRole : IdentityRole + where TContext : IdentityDbContext + where TUserLogin : IdentityUserLogin, new() + where TUserRole : IdentityUserRole, new() + { + #region Private Methods & Variables + + + /// + /// The database + /// + private readonly MongoDatabase db; + + /// + /// The _disposed + /// + private bool _disposed; + + /// + /// The AspNetUsers collection name + /// + private const string collectionName = "AspNetUsers"; + + /// + /// Gets the users. + /// + /// The users. + public IQueryable Users + { + get + { + return db.GetCollection(collectionName).AsQueryable(); + } + } + + + #endregion + + #region Constructors + + /// + /// Initializes a new instance of the class. + /// + /// The context. + public UserStore(TContext context) + { + db = context.Database; + } + + #endregion + + #region Methods + + /// + /// Adds the claim asynchronous. + /// + /// The user. + /// The claim. + /// Task. + /// user + public Task AddClaimsAsync(TUser user, IEnumerable claims, CancellationToken cancellationToken = default(CancellationToken)) + { + ThrowIfDisposed(); + if (user == null) + throw new ArgumentNullException("user"); + foreach (var claim in claims) + { + if (!user.Claims.Any(x => x.ClaimType == claim.Type && x.ClaimValue == claim.Value)) + { + user.Claims.Add(new IdentityUserClaim + { + ClaimType = claim.Type, + ClaimValue = claim.Value + }); + } + } + return Task.FromResult(0); + } + + /// + /// Gets the claims asynchronous. + /// + /// The user. + /// Task{IList{Claim}}. + /// user + public Task> GetClaimsAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken)) + { + ThrowIfDisposed(); + if (user == null) + throw new ArgumentNullException("user"); + + IList result = user.Claims.Select(c => new Claim(c.ClaimType, c.ClaimValue)).ToList(); + return Task.FromResult(result); + } + + public Task ReplaceClaimAsync(TUser user, Claim claim, Claim newClaim, CancellationToken cancellationToken = default(CancellationToken)) + { + ThrowIfDisposed(); + if (user == null) + { + throw new ArgumentNullException("user"); + } + if (claim == null) + { + throw new ArgumentNullException("claim"); + } + if (newClaim == null) + { + throw new ArgumentNullException("newClaim"); + } + + var matchedClaims = user.Claims.Where(uc => uc.ClaimValue == claim.Value && uc.ClaimType == claim.Type).ToList(); + foreach (var matchedClaim in matchedClaims) + { + matchedClaim.ClaimValue = newClaim.Value; + matchedClaim.ClaimType = newClaim.Type; + } + + return Task.FromResult(0); + } + + + /// + /// Removes the claim asynchronous. + /// + /// The user. + /// The claim. + /// Task. + /// user + public Task RemoveClaimsAsync(TUser user, IEnumerable claims, CancellationToken cancellationToken = default(CancellationToken)) + { + ThrowIfDisposed(); + if (user == null) + throw new ArgumentNullException("user"); + + foreach (var claim in claims) + { + var matchedClaims = user.Claims.Where(uc => uc.ClaimValue == claim.Value && uc.ClaimType == claim.Type).ToList(); + foreach (var c in matchedClaims) + { + user.Claims.RemoveAll(x => x.ClaimType == claim.Type && x.ClaimValue == claim.Value); + //user.Claims.Remove(c); + } + } + return Task.FromResult(0); + } + + /// + /// Creates the user asynchronous. + /// + /// The user. + /// Task. + /// user + public Task CreateAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken)) + { + ThrowIfDisposed(); + if (user == null) + throw new ArgumentNullException("user"); + + db.GetCollection(collectionName).Insert(user); + + return Task.FromResult(IdentityResult.Success); + } + + /// + /// Deletes the user asynchronous. + /// + /// The user. + /// Task. + /// user + public Task DeleteAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken)) + { + ThrowIfDisposed(); + if (user == null) + throw new ArgumentNullException("user"); + + db.GetCollection(collectionName).Remove((Query.EQ("_id", ObjectId.Parse(user.Id.ToString())))); + return Task.FromResult(IdentityResult.Success); + } + + /// + /// Finds the by identifier asynchronous. + /// + /// The user identifier. + /// Task{`0}. + public Task FindByIdAsync(TKey userId, CancellationToken cancellationToken = default(CancellationToken)) + { + ThrowIfDisposed(); + //TUser user = db.GetCollection(collectionName).FindOne((Query.EQ("_id", ObjectId.Parse(userId.ToString())))); + TUser user = Users.FirstOrDefault(i => i.Id.Equals(userId)); + return Task.FromResult(user); + } + + /// + /// Finds the by identifier asynchronous. + /// + /// The user identifier. + /// Task{`0}. + public Task FindByIdAsync(string userId, CancellationToken cancellationToken = default(CancellationToken)) + { + ThrowIfDisposed(); + //TUser user = db.GetCollection(collectionName).FindOne((Query.EQ("_id", ObjectId.Parse(userId)))); + TUser user = Users.FirstOrDefault(i => i.Id.Equals(userId)); + return Task.FromResult(user); + } + + /// + /// Finds the by name asynchronous. + /// + /// Name of the user. + /// Task{`0}. + public Task FindByNameAsync(string normalizedUserName, CancellationToken cancellationToken = default(CancellationToken)) + { + ThrowIfDisposed(); + + //TUser user = db.GetCollection(collectionName).FindOne((Query.EQ("NormalizedUserName", normalizedUserName))); + TUser user = Users.AsQueryable().FirstOrDefault(n => n.NormalizedUserName.Equals(normalizedUserName)); + return Task.FromResult(user); + } + + /// + /// Sets the email confirmed asynchronous. + /// + /// The user. + /// if set to true [confirmed]. + /// Task. + + public Task SetEmailConfirmedAsync(TUser user, bool confirmed, CancellationToken cancellationToken = default(CancellationToken)) + { + ThrowIfDisposed(); + + user.EmailConfirmed = true; + return Task.FromResult(0); + } + + /// + /// Finds the by email asynchronous. + /// + /// The email. + /// Task{`0}. + public Task FindByEmailAsync(string email, CancellationToken cancellationToken = default(CancellationToken)) + { + ThrowIfDisposed(); + + //TUser user = db.GetCollection(collectionName).FindOne((Query.EQ("Email", email))); + TUser user = Users.AsQueryable().FirstOrDefault(x => x.Email.Equals(email)); + return Task.FromResult(user); + } + + /// + /// Sets the email asynchronous. + /// + /// The user. + /// The email. + /// Task. + public Task SetEmailAsync(TUser user, string email, CancellationToken cancellationToken = default(CancellationToken)) + { + ThrowIfDisposed(); + if (user == null) + { + throw new ArgumentException("user"); + } + user.Email = email; + return Task.FromResult(0); + } + + /// + /// Gets the email asynchronous. + /// + /// The user. + /// Task{System.String}. + /// user + public Task GetEmailAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken)) + { + ThrowIfDisposed(); + if (user == null) + { + throw new ArgumentException("user"); + } + return Task.FromResult(user.Email); + } + + public virtual Task GetNormalizedEmailAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken)) + { + cancellationToken.ThrowIfCancellationRequested(); + ThrowIfDisposed(); + if (user == null) + { + throw new ArgumentNullException("user"); + } + return Task.FromResult(user.NormalizedEmail); + } + + public virtual Task SetNormalizedEmailAsync(TUser user, string normalizedEmail, CancellationToken cancellationToken = default(CancellationToken)) + { + cancellationToken.ThrowIfCancellationRequested(); + ThrowIfDisposed(); + if (user == null) + { + throw new ArgumentNullException("user"); + } + user.NormalizedEmail = normalizedEmail; + return Task.FromResult(0); + } + + /// + /// Gets the email confirmed asynchronous. + /// + /// The user. + /// Task{System.Boolean}. + + public Task GetEmailConfirmedAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken)) + { + ThrowIfDisposed(); + if (user == null) + { + throw new ArgumentException("user"); + } + return Task.FromResult(user.EmailConfirmed); + } + + /// + /// Updates the user asynchronous. + /// + /// The user. + /// Task. + /// user + public Task UpdateAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken)) + { + ThrowIfDisposed(); + if (user == null) + throw new ArgumentNullException("user"); + + db.GetCollection(collectionName).Update(Query.EQ("_id", ObjectId.Parse(user.Id.ToString())), Update.Replace(user), UpdateFlags.Upsert); + return Task.FromResult(IdentityResult.Success); + } + + /// + /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. + /// + public void Dispose() + { + _disposed = true; + } + + /// + /// Adds the login asynchronous. + /// + /// The user. + /// The login. + /// Task. + /// user + public Task AddLoginAsync(TUser user, UserLoginInfo login, CancellationToken cancellationToken = default(CancellationToken)) + { + ThrowIfDisposed(); + if (user == null) + throw new ArgumentNullException("user"); + + if (!user.Logins.Any(x => x.LoginProvider == login.LoginProvider && x.ProviderKey == login.ProviderKey)) + { + user.Logins.Add(login); + } + + return Task.FromResult(true); + } + + /// + /// Gets the logins asynchronous. + /// + /// The user. + /// Task{IList{UserLoginInfo}}. + /// user + public Task> GetLoginsAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken)) + { + ThrowIfDisposed(); + if (user == null) + throw new ArgumentNullException("user"); + + return Task.FromResult(user.Logins.ToIList()); + } + + /// + /// Removes the login asynchronous. + /// + /// The user. + /// The login. + /// Task. + /// user + //public Task RemoveLoginAsync(TUser user, UserLoginInfo login, CancellationToken cancellationToken = default(CancellationToken)) + //{ + // ThrowIfDisposed(); + // if (user == null) + // throw new ArgumentNullException("user"); + + // user.Logins.RemoveAll(x => x.LoginProvider == login.LoginProvider && x.ProviderKey == login.ProviderKey); + + // return Task.FromResult(0); + //} + public Task RemoveLoginAsync(TUser user, string loginProvider, string providerKey, CancellationToken cancellationToken = default(CancellationToken)) + { + ThrowIfDisposed(); + if (user == null) + throw new ArgumentNullException("user"); + + user.Logins.RemoveAll(x => x.LoginProvider == loginProvider && x.ProviderKey == providerKey); + + return Task.FromResult(0); + } + /// + /// Gets the password hash asynchronous. + /// + /// The user. + /// Task{System.String}. + /// user + public Task GetPasswordHashAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken)) + { + ThrowIfDisposed(); + if (user == null) + throw new ArgumentNullException("user"); + + return Task.FromResult(user.PasswordHash); + } + + /// + /// Determines whether [has password asynchronous] [the specified user]. + /// + /// The user. + /// user + public Task HasPasswordAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken)) + { + ThrowIfDisposed(); + if (user == null) + throw new ArgumentNullException("user"); + + return Task.FromResult(user.PasswordHash != null); + } + + /// + /// Sets the password hash asynchronous. + /// + /// The user. + /// The password hash. + /// Task. + /// user + public Task SetPasswordHashAsync(TUser user, string passwordHash, CancellationToken cancellationToken = default(CancellationToken)) + { + ThrowIfDisposed(); + if (user == null) + throw new ArgumentNullException("user"); + + user.PasswordHash = passwordHash; + return Task.FromResult(0); + } + + /// + /// Adds to role asynchronous. + /// + /// The user. + /// The role. + /// Task. + /// user + public Task AddToRoleAsync(TUser user, string role, CancellationToken cancellationToken = default(CancellationToken)) + { + ThrowIfDisposed(); + if (user == null) + throw new ArgumentNullException("user"); + + if (!user.Roles.Contains(role, StringComparer.InvariantCultureIgnoreCase)) + user.Roles.Add(role); + + return Task.FromResult(true); + } + + /// + /// Gets the roles asynchronous. + /// + /// The user. + /// Task{IList{System.String}}. + /// user + public Task> GetRolesAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken)) + { + ThrowIfDisposed(); + if (user == null) + throw new ArgumentNullException("user"); + + return Task.FromResult>(user.Roles); + } + + /// + /// Determines whether [is in role asynchronous] [the specified user]. + /// + /// The user. + /// The role. + /// user + public Task IsInRoleAsync(TUser user, string role, CancellationToken cancellationToken = default(CancellationToken)) + { + ThrowIfDisposed(); + if (user == null) + throw new ArgumentNullException("user"); + + return Task.FromResult(user.Roles.Contains(role, StringComparer.InvariantCultureIgnoreCase)); + } + + /// + /// Removes from role asynchronous. + /// + /// The user. + /// The role. + /// Task. + /// user + public Task RemoveFromRoleAsync(TUser user, string role, CancellationToken cancellationToken = default(CancellationToken)) + { + ThrowIfDisposed(); + if (user == null) + throw new ArgumentNullException("user"); + + user.Roles.RemoveAll(r => String.Equals(r, role, StringComparison.InvariantCultureIgnoreCase)); + + return Task.FromResult(0); + } + + /// + /// Gets the security stamp asynchronous. + /// + /// The user. + /// Task{System.String}. + /// user + public Task GetSecurityStampAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken)) + { + ThrowIfDisposed(); + if (user == null) + throw new ArgumentNullException("user"); + + return Task.FromResult(user.SecurityStamp); + } + + /// + /// Sets the security stamp asynchronous. + /// + /// The user. + /// The stamp. + /// Task. + /// user + public Task SetSecurityStampAsync(TUser user, string stamp, CancellationToken cancellationToken = default(CancellationToken)) + { + ThrowIfDisposed(); + if (user == null) + throw new ArgumentNullException("user"); + + user.SecurityStamp = stamp; + return Task.FromResult(0); + } + + /// + /// Sets the phone number asynchronous. + /// + /// The user. + /// The phone number. + /// Task. + /// user + public Task SetPhoneNumberAsync(TUser user, string phoneNumber, CancellationToken cancellationToken = default(CancellationToken)) + { + ThrowIfDisposed(); + if (user == null) + { + throw new ArgumentException("user"); + } + + user.PhoneNumber = phoneNumber; + return Task.FromResult(0); + } + + /// + /// Gets the phone number asynchronous. + /// + /// The user. + /// Task{System.String}. + /// user + public Task GetPhoneNumberAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken)) + { + ThrowIfDisposed(); + if (user == null) + { + throw new ArgumentNullException("user"); + } + + return Task.FromResult(user.PhoneNumber); + } + + /// + /// Gets the phone number confirmed asynchronous. + /// + /// The user. + /// Task{System.Boolean}. + /// user + public Task GetPhoneNumberConfirmedAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken)) + { + ThrowIfDisposed(); + if (user == null) + { + throw new ArgumentNullException("user"); + } + return Task.FromResult(user.PhoneNumberConfirmed); + } + + /// + /// Sets the phone number confirmed asynchronous. + /// + /// The user. + /// if set to true [confirmed]. + /// Task. + /// user + public Task SetPhoneNumberConfirmedAsync(TUser user, bool confirmed, CancellationToken cancellationToken = default(CancellationToken)) + { + ThrowIfDisposed(); + if (user == null) + { + throw new ArgumentNullException("user"); + } + user.PhoneNumberConfirmed = confirmed; + return Task.FromResult(0); + } + + /// + /// Sets the two factor enabled asynchronous. + /// + /// The user. + /// if set to true [enabled]. + /// Task. + /// user + public Task SetTwoFactorEnabledAsync(TUser user, bool enabled, CancellationToken cancellationToken = default(CancellationToken)) + { + ThrowIfDisposed(); + if (user == null) + { + throw new ArgumentNullException("user"); + } + user.TwoFactorEnabled = enabled; + return Task.FromResult(0); + } + + /// + /// Gets the two factor enabled asynchronous. + /// + /// The user. + /// Task{System.Boolean}. + /// user + public Task GetTwoFactorEnabledAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken)) + { + ThrowIfDisposed(); + if (user == null) + { + throw new ArgumentNullException("user"); + } + return Task.FromResult(user.TwoFactorEnabled); + } + + /// + /// Get all users with given claim + /// + /// + /// + /// + public async virtual Task> GetUsersForClaimAsync(Claim claim, CancellationToken cancellationToken = default(CancellationToken)) + { + cancellationToken.ThrowIfCancellationRequested(); + ThrowIfDisposed(); + if (claim == null) + { + throw new ArgumentNullException("claim"); + } + + var users = Users.Where(u => u.Claims.Any(c => c.ClaimType == claim.Type && c.ClaimValue == claim.Value)); + + return users.ToList(); + } + + /// + /// Get all users in given role + /// + /// + /// + /// + public async virtual Task> GetUsersInRoleAsync(string roleName, CancellationToken cancellationToken = default(CancellationToken)) + { + cancellationToken.ThrowIfCancellationRequested(); + ThrowIfDisposed(); + if (String.IsNullOrEmpty(roleName)) + { + throw new ArgumentNullException("role"); + } + + var users = Users.Where(u => u.Roles.Any(r => r.Equals(roleName))); + + return users.ToList(); + } + + public Task FindByLoginAsync(string loginProvider, string providerKey, CancellationToken cancellationToken = default(CancellationToken)) + { + cancellationToken.ThrowIfCancellationRequested(); + ThrowIfDisposed(); + // todo: ensure logins loaded + + //var user = db.GetCollection(collectionName).FindOne((Query.And(Query.EQ("Logins.LoginProvider", loginProvider), Query.EQ("Logins.ProviderKey", providerKey)))); + var user = Users.AsQueryable().FirstOrDefault(x => x.Logins.Any(l => l.LoginProvider == loginProvider && l.ProviderKey == providerKey)); + + return Task.FromResult(user); + } + + public Task GetUserIdAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken)) + { + cancellationToken.ThrowIfCancellationRequested(); + ThrowIfDisposed(); + if (user == null) + { + throw new ArgumentNullException("user"); + } + return Task.FromResult(user.Id != null ? user.Id.ToString() : null); + } + + public Task GetUserNameAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken)) + { + cancellationToken.ThrowIfCancellationRequested(); + ThrowIfDisposed(); + if (user == null) + { + throw new ArgumentNullException("user"); + } + return Task.FromResult(user.UserName); + } + + public Task SetUserNameAsync(TUser user, string userName, CancellationToken cancellationToken = default(CancellationToken)) + { + cancellationToken.ThrowIfCancellationRequested(); + ThrowIfDisposed(); + if (user == null) + { + throw new ArgumentNullException("user"); + } + user.UserName = userName; + return Task.FromResult(0); + } + + public Task GetNormalizedUserNameAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken)) + { + cancellationToken.ThrowIfCancellationRequested(); + ThrowIfDisposed(); + if (user == null) + { + throw new ArgumentNullException("user"); + } + return Task.FromResult(user.NormalizedUserName); + } + + public Task SetNormalizedUserNameAsync(TUser user, string userName, CancellationToken cancellationToken = default(CancellationToken)) + { + cancellationToken.ThrowIfCancellationRequested(); + ThrowIfDisposed(); + if (user == null) + { + throw new ArgumentNullException("user"); + } + user.NormalizedUserName = userName; + return Task.FromResult(0); + } + + /// + /// Returns the DateTimeOffset that represents the end of a user's lockout, any time in the past should be considered + /// not locked out. + /// + /// + /// + /// + public virtual Task GetLockoutEndDateAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken)) + { + cancellationToken.ThrowIfCancellationRequested(); + ThrowIfDisposed(); + if (user == null) + { + throw new ArgumentNullException("user"); + } + return Task.FromResult(user.LockoutEnd); + } + + /// + /// Locks a user out until the specified end date (set to a past date, to unlock a user) + /// + /// + /// + /// + /// + public virtual Task SetLockoutEndDateAsync(TUser user, DateTimeOffset? lockoutEnd, CancellationToken cancellationToken = default(CancellationToken)) + { + cancellationToken.ThrowIfCancellationRequested(); + ThrowIfDisposed(); + if (user == null) + { + throw new ArgumentNullException("user"); + } + user.LockoutEnd = lockoutEnd; + return Task.FromResult(0); + } + + /// + /// Used to record when an attempt to access the user has failed + /// + /// + /// + /// + public virtual Task IncrementAccessFailedCountAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken)) + { + cancellationToken.ThrowIfCancellationRequested(); + ThrowIfDisposed(); + if (user == null) + { + throw new ArgumentNullException("user"); + } + user.AccessFailedCount++; + return Task.FromResult(user.AccessFailedCount); + } + + /// + /// Used to reset the account access count, typically after the account is successfully accessed + /// + /// + /// + /// + public virtual Task ResetAccessFailedCountAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken)) + { + cancellationToken.ThrowIfCancellationRequested(); + ThrowIfDisposed(); + if (user == null) + { + throw new ArgumentNullException("user"); + } + user.AccessFailedCount = 0; + return Task.FromResult(0); + } + + /// + /// Returns the current number of failed access attempts. This number usually will be reset whenever the password is + /// verified or the account is locked out. + /// + /// + /// + /// + public virtual Task GetAccessFailedCountAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken)) + { + cancellationToken.ThrowIfCancellationRequested(); + ThrowIfDisposed(); + if (user == null) + { + throw new ArgumentNullException("user"); + } + return Task.FromResult(user.AccessFailedCount); + } + + /// + /// Returns whether the user can be locked out. + /// + /// + /// + /// + public virtual Task GetLockoutEnabledAsync(TUser user, CancellationToken cancellationToken = default(CancellationToken)) + { + cancellationToken.ThrowIfCancellationRequested(); + ThrowIfDisposed(); + if (user == null) + { + throw new ArgumentNullException("user"); + } + return Task.FromResult(user.LockoutEnabled); + } + + /// + /// Sets whether the user can be locked out. + /// + /// + /// + /// + /// + public virtual Task SetLockoutEnabledAsync(TUser user, bool enabled, CancellationToken cancellationToken = default(CancellationToken)) + { + cancellationToken.ThrowIfCancellationRequested(); + ThrowIfDisposed(); + if (user == null) + { + throw new ArgumentNullException("user"); + } + user.LockoutEnabled = enabled; + return Task.FromResult(0); + } + + + + /// + /// Throws if disposed. + /// + /// + private void ThrowIfDisposed() + { + if (_disposed) + throw new ObjectDisposedException(GetType().Name); + } + + #endregion + + + } +} diff --git a/Utils.cs b/src/MongoDB.AspNet.Identity/Utils.cs similarity index 87% rename from Utils.cs rename to src/MongoDB.AspNet.Identity/Utils.cs index 6601cee..49a242d 100644 --- a/Utils.cs +++ b/src/MongoDB.AspNet.Identity/Utils.cs @@ -1,7 +1,5 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.Linq; -using MongoDB.Driver; namespace MongoDB.AspNet.Identity { diff --git a/src/MongoDB.AspNet.Identity/project.json b/src/MongoDB.AspNet.Identity/project.json new file mode 100644 index 0000000..b44d06d --- /dev/null +++ b/src/MongoDB.AspNet.Identity/project.json @@ -0,0 +1,17 @@ +{ + "version": "1.0.0-6", + "dependencies": { + "Microsoft.AspNet.Identity": "3.0.0-beta4", + "mongocsharpdriver": "2.0.0-rc0" + }, + "frameworks": { + "dnx451": { + "dependencies": { + } + }, + "dxcore50": { + "dependencies": { + } + } + } +} \ No newline at end of file