first commit

This commit is contained in:
alexandre-spieser
2017-10-22 00:24:46 +00:00
commit 0dc4240d2c
69 changed files with 17455 additions and 0 deletions
@@ -0,0 +1,39 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.0</TargetFramework>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<DocumentationFile>bin\Release\netcoreapp2.0\AspNetCore.Identity.MongoDbCore.xml</DocumentationFile>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DocumentationFile>bin\Debug\netcoreapp2.0\AspNetCore.Identity.MongoDbCore.xml</DocumentationFile>
</PropertyGroup>
<ItemGroup>
<!--<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.0" />-->
<PackageReference Include="Microsoft.AspNetCore.Identity" Version="2.0.0" />
<PackageReference Include="Microsoft.Extensions.Identity.Stores" Version="2.0.0" />
<PackageReference Include="MongoDB.Driver" Version="2.4.4" />
<PackageReference Include="MongoDbGenericRepository" Version="1.3.0" />
</ItemGroup>
<ItemGroup>
<Compile Update="Resources.Designer.cs">
<DependentUpon>Resources.resx</DependentUpon>
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
</Compile>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Update="Resources.resx">
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
<Generator>ResXFileCodeGenerator</Generator>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</EmbeddedResource>
</ItemGroup>
</Project>
@@ -0,0 +1,20 @@
<?xml version="1.0"?>
<package >
<metadata>
<id>AspNetCore.Identity.MongoDbCore</id>
<version>1.0.3</version>
<title>AspNetCore.Identity.MongoDbCore</title>
<authors>Alexandre Spieser</authors>
<owners>Alexandre Spieser</owners>
<licenseUrl>http://www.opensource.org/licenses/mit-license.php</licenseUrl>
<projectUrl>https://github.com/alexandre-spieser/AspNetCore.Identity.MongoDbCore</projectUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>A MongoDb UserStore and RoleStore adapter for Microsoft.AspNetCore.Identity 2.0.</description>
<releaseNotes>First release.</releaseNotes>
<copyright>Copyright 2017 (c) Alexandre Spieser. All rights reserved.</copyright>
<tags>aspnetcore mongo mongodb identity membership</tags>
</metadata>
<files>
<file src="lib\**" target="lib" />
</files>
</package>
+122
View File
@@ -0,0 +1,122 @@
using AspNetCore.Identity.MongoDbCore.Interfaces;
using AspNetCore.Identity.MongoDbCore.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
namespace AspNetCore.Identity.MongoDbCore.Extensions
{
/// <summary>
/// The extensions for an object that holds claims.
/// </summary>
public static class ClaimHolderExtensions
{
public static MongoClaim ToMongoClaim(this Claim claim)
{
return new MongoClaim
{
Type = claim.Type,
Value = claim.Value,
Issuer = claim.Issuer
};
}
public static Claim ToClaim(this MongoClaim claim)
{
return new Claim(claim.Type, claim.Value, null, claim.Issuer);
}
/// <summary>
/// Adds a claim to a claim holder, implementing <see cref="IClaimHolder"/>.
/// </summary>
/// <param name="claimHolder">The object holding claims.</param>
/// <param name="claim">The claim you want to add.</param>
/// <returns>Returns true if the claim was added.</returns>
public static bool AddClaim(this IClaimHolder claimHolder, Claim claim)
{
if (claim == null)
{
throw new ArgumentNullException(nameof(claim));
}
// prevent adding duplicate claims
if (claimHolder.HasClaim(claim))
{
return false;
}
claimHolder.Claims.Add(claim.ToMongoClaim());
return true;
}
/// <summary>
/// Replaces a claim on a claim holder, implementing <see cref="IClaimHolder"/>.
/// </summary>
/// <param name="claimHolder">The object holding claims.</param>
/// <param name="claim">The claim you want to replace.</param>
/// <param name="newClaim">The new claim you want to set.</param>
/// <returns>Returns true if the claim was replaced.</returns>
public static bool ReplaceClaim(this IClaimHolder claimHolder, Claim claim, Claim newClaim)
{
var replaced = false;
claimHolder.Claims.Where(uc => uc.Value == claim.Value && uc.Type == claim.Type).ToList()
.ForEach(oldClaim => {
oldClaim.Type = newClaim.Type;
oldClaim.Value = newClaim.Value;
oldClaim.Issuer = newClaim.Issuer;
replaced |= true;
});
return replaced;
}
/// <summary>
/// Checks if an object implementing <see cref="IClaimHolder"/> has a claim.
/// </summary>
/// <param name="claimHolder">The object holding claims.</param>
/// <param name="claim">The claim you want to replace.</param>
/// <returns>Returns true if the claim is present, false otherwise.</returns>
public static bool HasClaim(this IClaimHolder claimHolder, Claim claim)
{
if(claimHolder.Claims == null)
{
claimHolder.Claims = new List<MongoClaim>();
}
return claimHolder.Claims.Any(e => e.Value == claim.Value && e.Type == claim.Type);
}
public static bool RemoveClaim(this IClaimHolder claimHolder, Claim claim)
{
if (claim == null)
{
throw new ArgumentNullException(nameof(claim));
}
var exists = claimHolder.Claims
.FirstOrDefault(e => e.Value == claim.Value
&& e.Type == claim.Type);
if (exists != null)
{
claimHolder.Claims.Remove(exists);
return true;
}
return false;
}
public static bool RemoveClaims(this IClaimHolder claimHolder, IEnumerable<Claim> claims)
{
var someClaimsRemoved = false;
foreach (var claim in claims)
{
var matchedClaims = claimHolder.Claims.Where(uc => uc.Value == claim.Value && uc.Type == claim.Type)
.ToList();
foreach (var c in matchedClaims)
{
claimHolder.Claims.Remove(c);
someClaimsRemoved |= true;
}
}
return someClaimsRemoved;
}
}
}
@@ -0,0 +1,94 @@
using AspNetCore.Identity.MongoDbCore.Infrastructure;
using AspNetCore.Identity.MongoDbCore.Models;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.DependencyInjection;
using MongoDbGenericRepository;
using System;
namespace AspNetCore.Identity.MongoDbCore.Extensions
{
public class MongoDbSettings
{
public string ConnectionString { get; set; }
public string DatabaseName { get; set; }
}
public class MongoDbIdentityConfiguration
{
public MongoDbSettings MongoDbSettings { get; set; }
public Action<IdentityOptions> IdentityOptionsAction { get; set; }
}
public static class ServiceCollectionExtension
{
public static void ConfigureMongoDbIdentity<TUser, TKey>(
this IServiceCollection services,
MongoDbIdentityConfiguration mongoDbIdentityConfiguration,
IMongoRepository mongoRepository = null)
where TUser : MongoIdentityUser<TKey>, new()
where TKey : IEquatable<TKey>
{
services.AddSingleton<MongoDbSettings>(mongoDbIdentityConfiguration.MongoDbSettings);
services.AddSingleton<IMongoRepository>(provider =>
{
var options = provider.GetService<MongoDbSettings>();
return mongoRepository ?? new MongoRepository(options.ConnectionString, options.DatabaseName);
});
CommonMongoDbSetup<TUser, MongoIdentityRole<TKey>, TKey>(services, mongoDbIdentityConfiguration);
}
public static void ConfigureMongoDbIdentity<TUser>(this IServiceCollection services, MongoDbIdentityConfiguration mongoDbIdentityConfiguration)
where TUser : MongoIdentityUser, new()
{
services.AddSingleton<MongoDbSettings>(mongoDbIdentityConfiguration.MongoDbSettings);
services.AddSingleton<IMongoRepository>(provider =>
{
var options = provider.GetService<MongoDbSettings>();
return new MongoRepository(options.ConnectionString, options.DatabaseName);
});
CommonMongoDbSetup<TUser, MongoIdentityRole, Guid>(services, mongoDbIdentityConfiguration);
}
public static void ConfigureMongoDbIdentity<TUser, TRole, TKey>(this IServiceCollection services, MongoDbIdentityConfiguration mongoDbIdentityConfiguration,
IMongoDbContext mongoDbContext = null)
where TUser : MongoIdentityUser<TKey>, new()
where TRole : MongoIdentityRole<TKey>, new()
where TKey : IEquatable<TKey>
{
services.AddSingleton<MongoDbSettings>(mongoDbIdentityConfiguration.MongoDbSettings);
services.AddSingleton<IMongoRepository>(provider =>
{
var options = provider.GetService<MongoDbSettings>();
return mongoDbContext == null ? new MongoRepository(options.ConnectionString, options.DatabaseName) : new MongoRepository(mongoDbContext);
});
CommonMongoDbSetup<TUser, TRole, TKey>(services, mongoDbIdentityConfiguration);
}
private static void CommonMongoDbSetup<TUser, TRole, TKey>(this IServiceCollection services, MongoDbIdentityConfiguration mongoDbIdentityConfiguration)
where TUser : MongoIdentityUser<TKey>, new()
where TRole : MongoIdentityRole<TKey>, new()
where TKey : IEquatable<TKey>
{
services.AddScoped<IUserStore<TUser>>(provider =>
{
var userStore = new MongoUserStore<TUser, TRole, IMongoDbContext, TKey>(provider.GetService<IMongoRepository>().Context);
return userStore;
});
services.AddScoped<IRoleStore<TRole>>(provider =>
{
return new MongoRoleStore<TRole, IMongoDbContext, TKey>(provider.GetService<IMongoRepository>().Context);
});
services.AddIdentity<TUser, TRole>()
.AddDefaultTokenProviders();
services.Configure<IdentityOptions>(mongoDbIdentityConfiguration.IdentityOptionsAction);
}
}
}
+9
View File
@@ -0,0 +1,9 @@
using System;
namespace AspNetCore.Identity.MongoDbCore
{
public static class GlobalVariables
{
public static Random Random = new Random();
}
}
+35
View File
@@ -0,0 +1,35 @@
using MongoDbGenericRepository;
namespace AspNetCore.Identity.MongoDbCore.Infrastructure
{
public interface IMongoRepository : IBaseMongoRepository
{
void DropCollection<TDocument>();
void DropCollection<TDocument>(string partitionKey);
IMongoDbContext Context { get; }
}
public class MongoRepository : BaseMongoRepository, IMongoRepository
{
public MongoRepository(string connectionString, string databaseName) : base(connectionString, databaseName)
{
}
public MongoRepository(IMongoDbContext mongoDbContext) : base(mongoDbContext)
{
}
public void DropCollection<TDocument>()
{
MongoDbContext.DropCollection<TDocument>();
}
public void DropCollection<TDocument>(string partitionKey)
{
MongoDbContext.DropCollection<TDocument>(partitionKey);
}
public IMongoDbContext Context => MongoDbContext;
}
}
+13
View File
@@ -0,0 +1,13 @@
using AspNetCore.Identity.MongoDbCore.Models;
using System.Collections.Generic;
namespace AspNetCore.Identity.MongoDbCore.Interfaces
{
/// <summary>
/// The interface for an object that holds claims.
/// </summary>
public interface IClaimHolder
{
List<MongoClaim> Claims { get; set; }
}
}
+84
View File
@@ -0,0 +1,84 @@
using AspNetCore.Identity.MongoDbCore.Interfaces;
using Microsoft.AspNetCore.Identity;
using MongoDbGenericRepository.Models;
using System;
using System.Collections.Generic;
using System.Security.Claims;
namespace AspNetCore.Identity.MongoDbCore.Models
{
public class MongoDbIdentityRole : MongoIdentityRole<string>
{
public MongoDbIdentityRole() : base()
{
}
public MongoDbIdentityRole(string roleName) : base(roleName)
{
}
}
public class MongoIdentityRole : MongoIdentityRole<Guid>
{
public MongoIdentityRole() : base()
{
}
public MongoIdentityRole(string roleName) : base(roleName)
{
}
}
public class MongoIdentityRole<TKey> : IdentityRole<TKey>, IDocument<TKey>, IClaimHolder
where TKey : IEquatable<TKey>
{
private void InitializeFields()
{
Version = 1;
Claims = new List<MongoClaim>();
Guid guidValue = Guid.NewGuid();
var idTypeName = typeof(TKey).Name;
switch (idTypeName)
{
case "Guid":
Id = (TKey)(object)guidValue;
break;
case "Int32":
Id = (TKey)(object)GlobalVariables.Random.Next(1, int.MaxValue);
break;
case "String":
Id = (TKey)(object)guidValue.ToString();
break;
}
}
public MongoIdentityRole()
{
InitializeFields();
}
public MongoIdentityRole(string roleName)
{
Name = roleName;
InitializeFields();
}
public MongoIdentityRole(string name, TKey key)
{
InitializeFields();
Id = key;
Name = Name;
}
/// <summary>
/// The version of the role schema
/// </summary>
public int Version { get; set; }
/// <summary>
/// The claims associated to the role
/// </summary>
public List<MongoClaim> Claims { get; set; }
}
}
+398
View File
@@ -0,0 +1,398 @@
using System;
using System.Collections.Generic;
using MongoDbGenericRepository.Models;
using System.Linq;
using MongoDB.Driver;
using AspNetCore.Identity.MongoDbCore.Interfaces;
using Microsoft.AspNetCore.Identity;
namespace AspNetCore.Identity.MongoDbCore.Models
{
public class Token
{
/// <summary>
/// Gets or sets the LoginProvider this token is from.
/// </summary>
public string LoginProvider { get; set; }
/// <summary>
/// Gets or sets the name of the token.
public string Name { get; set; }
/// <summary>
/// Gets or sets the token value.
/// </summary>
public string Value { get; set; }
}
public class MongoClaim {
public string Type { get; set; }
public string Value { get; set; }
public string Issuer { get; set; }
}
public class UserRole
{
public object UserId { get; set; }
public object RoleId { get; set; }
}
public class MongoDbIdentityUser : MongoIdentityUser<string>
{
public MongoDbIdentityUser() : base()
{
}
public MongoDbIdentityUser(string userName) : base(userName)
{
}
public MongoDbIdentityUser(string userName, string email) : base(userName, email)
{
}
}
public class MongoIdentityUser : MongoIdentityUser<Guid>
{
public MongoIdentityUser() : base()
{
}
public MongoIdentityUser(string userName) : base(userName)
{
}
public MongoIdentityUser(string userName, string email) : base(userName, email)
{
}
}
public class MongoIdentityUser<TKey> : IdentityUser<TKey>, IDocument<TKey>, IClaimHolder
where TKey : IEquatable<TKey>
{
public int Version { get; set; }
public DateTime CreatedOn { get; private set; }
public DateTime? LockoutEndDate { get; private set; }
public DateTime? DeletedOn { get; private set; }
public List<MongoClaim> Claims { get; set; }
public List<TKey> Roles { get; set; }
public List<UserLoginInfo> Logins { get; set; }
public List<Token> Tokens { get; set; }
private void InitializeFields()
{
Claims = new List<MongoClaim>();
Logins = new List<UserLoginInfo>();
Roles = new List<TKey>();
Tokens = new List<Token>();
Guid guidValue = Guid.NewGuid();
var idTypeName = typeof(TKey).Name;
switch (idTypeName)
{
case "Guid":
Id = (TKey)(object)guidValue;
break;
case "Int32":
Id = (TKey)(object)GlobalVariables.Random.Next(1, int.MaxValue);
break;
case "String":
Id = (TKey)(object)guidValue.ToString();
break;
}
}
public MongoIdentityUser()
{
CreatedOn = DateTime.UtcNow;
SetVersion(1);
InitializeFields();
}
public MongoIdentityUser(string userName, string email) : this(userName)
{
if (email != null)
{
Email = email.ToLowerInvariant().Trim();
}
}
public MongoIdentityUser(string userName)
{
UserName = userName ?? throw new ArgumentNullException(nameof(userName));
CreatedOn = DateTime.UtcNow;
SetVersion(1);
InitializeFields();
Roles = new List<TKey>();
}
public virtual MongoIdentityUser<TKey> SetId(TKey key)
{
Id = key;
return this;
}
public virtual MongoIdentityUser<TKey> SetVersion(int version)
{
Version = 1;
return this;
}
public virtual void EnableTwoFactorAuthentication()
{
TwoFactorEnabled = true;
}
public virtual void DisableTwoFactorAuthentication()
{
TwoFactorEnabled = false;
}
public virtual void EnableLockout()
{
LockoutEnabled = true;
}
public virtual void DisableLockout()
{
LockoutEnabled = false;
}
public virtual void SetEmail(string email)
{
Email = email ?? throw new ArgumentNullException(nameof(email));
}
public virtual void SetNormalizedUserName(string normalizedUserName)
{
NormalizedUserName = normalizedUserName ?? throw new ArgumentNullException(nameof(normalizedUserName));
}
public virtual void SetPhoneNumber(string phoneNumber)
{
PhoneNumber = phoneNumber;
}
public virtual void SetPasswordHash(string passwordHash)
{
PasswordHash = passwordHash;
}
public virtual void SetSecurityStamp(string securityStamp)
{
SecurityStamp = securityStamp;
}
public virtual void SetAccessFailedCount(int accessFailedCount)
{
AccessFailedCount = accessFailedCount;
}
public virtual void ResetAccessFailedCount()
{
AccessFailedCount = 0;
}
public virtual void LockUntil(DateTime lockoutEndDate)
{
LockoutEndDate = lockoutEndDate;
}
public void Delete()
{
if (DeletedOn != null)
{
throw new InvalidOperationException($"User '{Id}' has already been deleted.");
}
DeletedOn = DateTime.UtcNow;
}
#region Role Management
public virtual IdentityUserRole<TKey> GetUserRole(TKey roleId)
{
var foundRoleId = Roles.FirstOrDefault(e => e.Equals(roleId));
if (!foundRoleId.Equals(default(TKey)))
{
return new IdentityUserRole<TKey>
{
UserId = Id,
RoleId = foundRoleId
};
}
return default(IdentityUserRole<TKey>);
}
public virtual bool RemoveRole(TKey roleId)
{
var roleClaim = Roles.FirstOrDefault(e => e.Equals(roleId));
if (!roleClaim.Equals(default(TKey)))
{
Roles.Remove(roleId);
return true;
}
return false;
}
public virtual bool AddRole(TKey roleId)
{
if (!Roles.Contains(roleId))
{
Roles.Add(roleId);
return true;
}
return false;
}
#endregion
#region Login Management
public virtual bool AddLogin(UserLoginInfo mongoUserLogin)
{
if (mongoUserLogin == null)
{
throw new ArgumentNullException(nameof(mongoUserLogin));
}
if (HasLogin(mongoUserLogin))
{
return false;
}
Logins.Add(mongoUserLogin);
return true;
}
public virtual bool HasLogin(UserLoginInfo login)
{
return Logins.Any(e => e.LoginProvider == login.LoginProvider && e.ProviderKey == e.ProviderKey);
}
public virtual void RemoveLogin(UserLoginInfo mongoUserLogin)
{
if (mongoUserLogin == null)
{
throw new ArgumentNullException(nameof(mongoUserLogin));
}
Logins.Remove(mongoUserLogin);
}
public virtual IdentityUserLogin<TKey> GetUserLogin(string loginProvider, string providerKey)
{
var login = Logins.FirstOrDefault(e => e.LoginProvider == loginProvider && e.ProviderKey == providerKey);
if (login != null)
{
return new IdentityUserLogin<TKey>
{
UserId = Id,
LoginProvider = login.LoginProvider,
ProviderDisplayName = login.ProviderDisplayName,
ProviderKey = login.ProviderKey
};
}
return default(IdentityUserLogin<TKey>);
}
#endregion
#region Token Management
/// <summary>
/// Replaces a claim on a claim holder, implementing <see cref="IClaimHolder"/>.
/// </summary>
/// <param name="claimHolder">The object holding claims.</param>
/// <param name="claim">The claim you want to replace.</param>
/// <param name="newClaim">The new claim you want to set.</param>
/// <returns>Returns true if the claim was replaced.</returns>
public bool SetToken(IdentityUserToken<TKey> tokenToset, string value)
{
var token = Tokens.FirstOrDefault(e => e.LoginProvider == tokenToset.LoginProvider && e.Name == tokenToset.Name);
if (token != null)
{
token.Value = value;
return true;
}
return false;
}
public IdentityUserToken<TKey> GetToken(string loginProvider, string name)
{
var token = Tokens.FirstOrDefault(e => e.LoginProvider == loginProvider && e.Name == name);
if (token != null)
{
return new IdentityUserToken<TKey>
{
UserId = Id,
LoginProvider = token.LoginProvider,
Name = token.Name,
Value = token.Value
};
}
return default(IdentityUserToken<TKey>);
}
public bool HasToken(IdentityUserToken<TKey> token)
{
return Tokens.Any(e => e.LoginProvider == token.LoginProvider
&& e.Name == token.Name
&& e.Value == token.Value);
}
public bool AddOrSet(IdentityUserToken<TKey> token)
{
var exists = GetToken(token.LoginProvider, token.Name);
if (exists != null && exists.Value != token.Value)
{
return SetToken(exists, token.Value);
}
if (exists == null)
{
Tokens.Add(new Token
{
LoginProvider = token.LoginProvider,
Name = token.Name,
Value = token.Value
});
return true;
}
return false;
}
public bool AddUserToken<TUserToken>(TUserToken token) where TUserToken : IdentityUserToken<TKey>
{
if (HasToken(token))
{
return false;
}
Tokens.Add(new Token
{
LoginProvider = token.LoginProvider,
Name = token.Name,
Value = token.Value
});
return true;
}
public bool RemoveUserToken<TUserToken>(TUserToken token) where TUserToken : IdentityUserToken<TKey>
{
var exists = Tokens.FirstOrDefault(e => e.LoginProvider == token.LoginProvider && e.Name == token.Name);
if (exists == null)
{
return false;
}
Tokens.Remove(exists);
return true;
}
#endregion Token Management
}
}
+49
View File
@@ -0,0 +1,49 @@
using AspNetCore.Identity.MongoDbCore.Models;
using MongoDB.Bson.Serialization.Conventions;
using System;
using System.Threading;
namespace AspNetCore.Identity.MongoDbCore
{
internal static class MongoConfig
{
private static bool _initialized = false;
private static object _initializationLock = new object();
private static object _initializationTarget;
public static void EnsureConfigured()
{
EnsureConfiguredImpl();
}
private static void EnsureConfiguredImpl()
{
LazyInitializer.EnsureInitialized(ref _initializationTarget, ref _initialized, ref _initializationLock, () =>
{
Configure();
return null;
});
}
private static void Configure()
{
RegisterConventions();
}
private static void RegisterConventions()
{
var pack = new ConventionPack
{
new IgnoreIfNullConvention(false),
new CamelCaseElementNameConvention(),
};
ConventionRegistry.Register("AspNetCore.Identity.MongoDB", pack, IsConventionApplicable);
}
private static bool IsConventionApplicable(Type type)
{
return type == typeof(MongoIdentityUser<>);
}
}
}
+89
View File
@@ -0,0 +1,89 @@
using AspNetCore.Identity.MongoDbCore.Infrastructure;
using AspNetCore.Identity.MongoDbCore.Models;
using MongoDB.Driver;
using MongoDbGenericRepository;
using System;
namespace AspNetCore.Identity.MongoDbCore
{
public class MongoIdentityDbContext : MongoDbContext
{
public MongoIdentityDbContext(string connectionString, string databaseName) : base(connectionString, databaseName)
{
}
public IMongoRepository MongoRepository { get; }
public IMongoCollection<MongoIdentityUser> Users
{
get
{
return GetCollection<MongoIdentityUser>();
}
}
public IMongoCollection<MongoIdentityRole> Roles
{
get
{
return GetCollection<MongoIdentityRole>();
}
}
}
public class MongoIdentityDbContext<TUser> : MongoDbContext
where TUser : MongoIdentityUser
{
public MongoIdentityDbContext(string connectionString, string databaseName) : base(connectionString, databaseName)
{
}
public IMongoRepository MongoRepository { get; }
public IMongoCollection<TUser> Users
{
get
{
return GetCollection<TUser>();
}
}
public IMongoCollection<MongoIdentityRole> Roles
{
get
{
return GetCollection<MongoIdentityRole>();
}
}
}
public class MongoIdentityDbContext<TUser, TRole, TKey> : MongoDbContext
where TUser : MongoIdentityUser<TKey>
where TRole : MongoIdentityRole<TKey>
where TKey : IEquatable<TKey>
{
public MongoIdentityDbContext(string connectionString, string databaseName) : base(connectionString, databaseName)
{
}
public IMongoCollection<TUser> Users
{
get
{
return GetCollection<TUser>();
}
}
public IMongoCollection<TRole> Roles
{
get
{
return GetCollection<TRole>();
}
}
}
}
@@ -0,0 +1,59 @@
using System;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Options;
using Microsoft.AspNetCore.Identity;
namespace AspNetCore.Identity.MongoDbCore
{
/// <summary>
/// Represents the password hashing options
/// </summary>
public sealed class PasswordHasherOptionsAccessor : IOptions<PasswordHasherOptions>
{
/// <summary>
/// Gets options which use the IdentityV3 compat mode, and set the iteration count to 200000 PBKDF2-SHA256 iterations
/// (roughly 200ms of work)
/// </summary>
public PasswordHasherOptions Value { get; } = new PasswordHasherOptions
{
CompatibilityMode = PasswordHasherCompatibilityMode.IdentityV3,
IterationCount = 200000
};
}
public static class MongoIdentityServiceCollectionExtensions
{
public static IdentityBuilder AddIdentity<TUser>(this IServiceCollection services)
where TUser : class => services.AddIdentity<TUser>(null);
public static IdentityBuilder AddIdentity<TUser>(this IServiceCollection services, Action<IdentityOptions> setupAction)
where TUser : class
{
// Hosting doesn't add IHttpContextAccessor by default
services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>();
// Identity services
services.TryAddScoped<IUserValidator<TUser>, UserValidator<TUser>>();
services.TryAddScoped<IPasswordValidator<TUser>, PasswordValidator<TUser>>();
services.TryAddScoped<IPasswordHasher<TUser>, PasswordHasher<TUser>>();
services.TryAddScoped<ILookupNormalizer, UpperInvariantLookupNormalizer>();
// No interface for the error describer so we can add errors without rev'ing the interface
services.TryAddScoped<IdentityErrorDescriber>();
services.TryAddScoped<ISecurityStampValidator, SecurityStampValidator<TUser>>();
services.TryAddScoped<IUserClaimsPrincipalFactory<TUser>, UserClaimsPrincipalFactory<TUser>>();
services.TryAddScoped<UserManager<TUser>, AspNetUserManager<TUser>>();
services.TryAddScoped<SignInManager<TUser>, SignInManager<TUser>>();
if (setupAction != null)
{
services.Configure(setupAction);
}
return new IdentityBuilder(typeof(TUser), services);
}
}
}
+463
View File
@@ -0,0 +1,463 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Security.Claims;
using System.Threading;
using System.Threading.Tasks;
using MongoDbGenericRepository;
using MongoDB.Driver;
using AspNetCore.Identity.MongoDbCore.Extensions;
using AspNetCore.Identity.MongoDbCore.Models;
using AspNetCore.Identity.MongoDbCore.Infrastructure;
using Microsoft.AspNetCore.Identity;
namespace AspNetCore.Identity.MongoDbCore
{
/// <summary>
/// Creates a new instance of a persistence store for roles.
/// </summary>
/// <typeparam name="TRole">The type of the class representing a role</typeparam>
public class MongoRoleStore<TRole> : MongoRoleStore<TRole, MongoDbContext, string>
where TRole : MongoIdentityRole<string>
{
/// <summary>
/// Constructs a new instance of <see cref="MongoRoleStore{TRole}"/>.
/// </summary>
/// <param name="context">The <see cref="IMongoDbContext"/>.</param>
/// <param name="describer">The <see cref="IdentityErrorDescriber"/>.</param>
public MongoRoleStore(IMongoDbContext context, IdentityErrorDescriber describer = null) : base(context, describer) { }
}
/// <summary>
/// Creates a new instance of a persistence store for roles.
/// </summary>
/// <typeparam name="TRole">The type of the class representing a role.</typeparam>
/// <typeparam name="TContext">The type of the data context class used to access the store.</typeparam>
public class MongoRoleStore<TRole, TContext> : MongoRoleStore<TRole, TContext, string>
where TRole : MongoIdentityRole<string>
where TContext : IMongoDbContext
{
/// <summary>
/// Constructs a new instance of <see cref="MongoRoleStore{TRole, TContext}"/>.
/// </summary>
/// <param name="context">The <see cref="IMongoDbContext"/>.</param>
/// <param name="describer">The <see cref="IdentityErrorDescriber"/>.</param>
public MongoRoleStore(TContext context, IdentityErrorDescriber describer = null) : base(context, describer) { }
}
/// <summary>
/// Creates a new instance of a persistence store for roles.
/// </summary>
/// <typeparam name="TRole">The type of the class representing a role.</typeparam>
/// <typeparam name="TContext">The type of the data context class used to access the store.</typeparam>
/// <typeparam name="TKey">The type of the primary key for a role.</typeparam>
public class MongoRoleStore<TRole, TContext, TKey> : MongoRoleStore<TRole, TContext, TKey, IdentityUserRole<TKey>, IdentityRoleClaim<TKey>>,
IQueryableRoleStore<TRole>,
IRoleClaimStore<TRole>
where TRole : MongoIdentityRole<TKey>
where TKey : IEquatable<TKey>
where TContext : IMongoDbContext
{
/// <summary>
/// Constructs a new instance of <see cref="MongoRoleStore{TRole, TContext, TKey}"/>.
/// </summary>
/// <param name="context">The <see cref="IMongoDbContext"/>.</param>
/// <param name="describer">The <see cref="IdentityErrorDescriber"/>.</param>
public MongoRoleStore(IMongoDbContext context, IdentityErrorDescriber describer = null) : base(context, describer) { }
}
/// <summary>
/// Creates a new instance of a persistence store for roles.
/// </summary>
/// <typeparam name="TRole">The type of the class representing a role.</typeparam>
/// <typeparam name="TContext">The type of the data context class used to access the store.</typeparam>
/// <typeparam name="TKey">The type of the primary key for a role.</typeparam>
/// <typeparam name="TUserRole">The type of the class representing a user role.</typeparam>
/// <typeparam name="TRoleClaim">The type of the class representing a role claim.</typeparam>
public class MongoRoleStore<TRole, TContext, TKey, TUserRole, TRoleClaim> :
IQueryableRoleStore<TRole>,
IRoleClaimStore<TRole>
where TRole : MongoIdentityRole<TKey>
where TKey : IEquatable<TKey>
where TContext : IMongoDbContext
where TUserRole : IdentityUserRole<TKey>, new()
where TRoleClaim : IdentityRoleClaim<TKey>, new()
{
/// <summary>
/// Constructs a new instance of <see cref="MongoRoleStore{TRole, TContext, TKey, TUserRole, TRoleClaim}"/>.
/// </summary>
/// <param name="context">The <see cref="IMongoDbContext"/>.</param>
/// <param name="describer">The <see cref="IdentityErrorDescriber"/>.</param>
public MongoRoleStore(IMongoDbContext context, IdentityErrorDescriber describer = null)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
Context = context;
ErrorDescriber = describer ?? new IdentityErrorDescriber();
}
private bool _disposed;
/// <summary>
/// Gets the database context for this store.
/// </summary>
private static IMongoDbContext Context { get; set; }
private static IMongoRepository _mongoRepository;
private static IMongoRepository MongoRepository
{
get
{
if (_mongoRepository == null)
{
_mongoRepository = new MongoRepository(Context);
}
return _mongoRepository;
}
}
/// <summary>
/// Gets or sets the <see cref="IdentityErrorDescriber"/> for any error that occurred with the current operation.
/// </summary>
public IdentityErrorDescriber ErrorDescriber { get; set; }
/// <summary>
/// Gets or sets a flag indicating if changes should be persisted after CreateAsync, UpdateAsync and DeleteAsync are called.
/// </summary>
/// <value>
/// True if changes should be automatically persisted, otherwise false.
/// </value>
public bool AutoSaveChanges { get; set; } = true;
/// <summary>
/// Creates a new role in a store as an asynchronous operation.
/// </summary>
/// <param name="role">The role to create in the store.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>A <see cref="Task{TResult}"/> that represents the <see cref="IdentityResult"/> of the asynchronous query.</returns>
public async virtual Task<IdentityResult> CreateAsync(TRole role, CancellationToken cancellationToken = default(CancellationToken))
{
cancellationToken.ThrowIfCancellationRequested();
ThrowIfDisposed();
if (role == null)
{
throw new ArgumentNullException(nameof(role));
}
await MongoRepository.AddOneAsync<TRole, TKey>(role);
return IdentityResult.Success;
}
/// <summary>
/// Updates a role in a store as an asynchronous operation.
/// </summary>
/// <param name="role">The role to update in the store.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>A <see cref="Task{TResult}"/> that represents the <see cref="IdentityResult"/> of the asynchronous query.</returns>
public async virtual Task<IdentityResult> UpdateAsync(TRole role, CancellationToken cancellationToken = default(CancellationToken))
{
cancellationToken.ThrowIfCancellationRequested();
ThrowIfDisposed();
if (role == null)
{
throw new ArgumentNullException(nameof(role));
}
var oldStamp = role.ConcurrencyStamp;
role.ConcurrencyStamp = Guid.NewGuid().ToString();
var collection = MongoRepository.Context.GetCollection<TRole>();
var updateRes = await collection.ReplaceOneAsync(x => x.Id.Equals(role.Id)
&& x.ConcurrencyStamp.Equals(oldStamp),
role);
if (updateRes.ModifiedCount == 0)
{
return IdentityResult.Failed(ErrorDescriber.ConcurrencyFailure());
}
return IdentityResult.Success;
}
/// <summary>
/// Deletes a role from the store as an asynchronous operation.
/// </summary>
/// <param name="role">The role to delete from the store.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>A <see cref="Task{TResult}"/> that represents the <see cref="IdentityResult"/> of the asynchronous query.</returns>
public async virtual Task<IdentityResult> DeleteAsync(TRole role, CancellationToken cancellationToken = default(CancellationToken))
{
cancellationToken.ThrowIfCancellationRequested();
ThrowIfDisposed();
if (role == null)
{
throw new ArgumentNullException(nameof(role));
}
var oldStamp = role.ConcurrencyStamp;
role.ConcurrencyStamp = Guid.NewGuid().ToString();
var collection = MongoRepository.Context.GetCollection<TRole>();
var deleteRes = await collection.DeleteOneAsync(x => x.Id.Equals(role.Id)
&& x.ConcurrencyStamp.Equals(oldStamp));
if (deleteRes.DeletedCount == 0)
{
return IdentityResult.Failed(ErrorDescriber.ConcurrencyFailure());
}
return IdentityResult.Success;
}
/// <summary>
/// Gets the ID for a role from the store as an asynchronous operation.
/// </summary>
/// <param name="role">The role whose ID should be returned.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>A <see cref="Task{TResult}"/> that contains the ID of the role.</returns>
public virtual Task<string> GetRoleIdAsync(TRole role, CancellationToken cancellationToken = default(CancellationToken))
{
cancellationToken.ThrowIfCancellationRequested();
ThrowIfDisposed();
if (role == null)
{
throw new ArgumentNullException(nameof(role));
}
return Task.FromResult(ConvertIdToString(role.Id));
}
/// <summary>
/// Gets the name of a role from the store as an asynchronous operation.
/// </summary>
/// <param name="role">The role whose name should be returned.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>A <see cref="Task{TResult}"/> that contains the name of the role.</returns>
public virtual Task<string> GetRoleNameAsync(TRole role, CancellationToken cancellationToken = default(CancellationToken))
{
cancellationToken.ThrowIfCancellationRequested();
ThrowIfDisposed();
if (role == null)
{
throw new ArgumentNullException(nameof(role));
}
return Task.FromResult(role.Name);
}
/// <summary>
/// Sets the name of a role in the store as an asynchronous operation.
/// </summary>
/// <param name="role">The role whose name should be set.</param>
/// <param name="roleName">The name of the role.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>The <see cref="Task"/> that represents the asynchronous operation.</returns>
public virtual Task SetRoleNameAsync(TRole role, string roleName, CancellationToken cancellationToken = default(CancellationToken))
{
cancellationToken.ThrowIfCancellationRequested();
ThrowIfDisposed();
if (role == null)
{
throw new ArgumentNullException(nameof(role));
}
if (role.Name != roleName)
{
role.Name = roleName;
return MongoRepository.UpdateOneAsync<TRole, TKey, string>(role, x => x.Name, role.Name);
}
return Task.CompletedTask;
}
/// <summary>
/// Converts the provided <paramref name="id"/> to a strongly typed key object.
/// </summary>
/// <param name="id">The id to convert.</param>
/// <returns>An instance of <typeparamref name="TKey"/> representing the provided <paramref name="id"/>.</returns>
public virtual TKey ConvertIdFromString(string id)
{
if (id == null)
{
return default(TKey);
}
return (TKey)TypeDescriptor.GetConverter(typeof(TKey)).ConvertFromInvariantString(id);
}
/// <summary>
/// Converts the provided <paramref name="id"/> to its string representation.
/// </summary>
/// <param name="id">The id to convert.</param>
/// <returns>An <see cref="string"/> representation of the provided <paramref name="id"/>.</returns>
public virtual string ConvertIdToString(TKey id)
{
if (id == null)
{
return null;
}
if (id.Equals(default(TKey)))
{
return null;
}
return id.ToString();
}
/// <summary>
/// Finds the role who has the specified ID as an asynchronous operation.
/// </summary>
/// <param name="id">The role ID to look for.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>A <see cref="Task{TResult}"/> that result of the look up.</returns>
public virtual Task<TRole> FindByIdAsync(string id, CancellationToken cancellationToken = default(CancellationToken))
{
cancellationToken.ThrowIfCancellationRequested();
ThrowIfDisposed();
var roleId = ConvertIdFromString(id);
return MongoRepository.GetOneAsync<TRole, TKey>(u => u.Id.Equals(roleId));
}
/// <summary>
/// Finds the role who has the specified normalized name as an asynchronous operation.
/// </summary>
/// <param name="normalizedName">The normalized role name to look for.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>A <see cref="Task{TResult}"/> that result of the look up.</returns>
public virtual Task<TRole> FindByNameAsync(string normalizedName, CancellationToken cancellationToken = default(CancellationToken))
{
cancellationToken.ThrowIfCancellationRequested();
ThrowIfDisposed();
return MongoRepository.GetOneAsync<TRole, TKey>(r => r.NormalizedName == normalizedName);
}
/// <summary>
/// Get a role's normalized name as an asynchronous operation.
/// </summary>
/// <param name="role">The role whose normalized name should be retrieved.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>A <see cref="Task{TResult}"/> that contains the name of the role.</returns>
public virtual Task<string> GetNormalizedRoleNameAsync(TRole role, CancellationToken cancellationToken = default(CancellationToken))
{
cancellationToken.ThrowIfCancellationRequested();
ThrowIfDisposed();
if (role == null)
{
throw new ArgumentNullException(nameof(role));
}
return Task.FromResult(role.NormalizedName);
}
/// <summary>
/// Set a role's normalized name as an asynchronous operation.
/// </summary>
/// <param name="role">The role whose normalized name should be set.</param>
/// <param name="normalizedName">The normalized name to set</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>The <see cref="Task"/> that represents the asynchronous operation.</returns>
public virtual Task SetNormalizedRoleNameAsync(TRole role, string normalizedName, CancellationToken cancellationToken = default(CancellationToken))
{
cancellationToken.ThrowIfCancellationRequested();
ThrowIfDisposed();
if (role == null)
{
throw new ArgumentNullException(nameof(role));
}
if (role.NormalizedName != normalizedName)
{
role.NormalizedName = normalizedName;
return MongoRepository.UpdateOneAsync<TRole, TKey, string>(role, x => x.NormalizedName, role.NormalizedName);
}
return Task.CompletedTask;
}
/// <summary>
/// Throws if this class has been disposed.
/// </summary>
protected void ThrowIfDisposed()
{
if (_disposed)
{
throw new ObjectDisposedException(GetType().Name);
}
}
/// <summary>
/// Dispose the stores
/// </summary>
public void Dispose() => _disposed = true;
/// <summary>
/// Get the claims associated with the specified <paramref name="role"/> as an asynchronous operation.
/// </summary>
/// <param name="role">The role whose claims should be retrieved.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>A <see cref="Task{TResult}"/> that contains the claims granted to a role.</returns>
public async virtual Task<IList<Claim>> GetClaimsAsync(TRole role, CancellationToken cancellationToken = default(CancellationToken))
{
ThrowIfDisposed();
if (role == null)
{
throw new ArgumentNullException(nameof(role));
}
return role.Claims.Select(e => e.ToClaim()).ToList();
}
/// <summary>
/// Adds the <paramref name="claim"/> given to the specified <paramref name="role"/>.
/// </summary>
/// <param name="role">The role to add the claim to.</param>
/// <param name="claim">The claim to add to the role.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>The <see cref="Task"/> that represents the asynchronous operation.</returns>
public virtual Task AddClaimAsync(TRole role, Claim claim, CancellationToken cancellationToken = default(CancellationToken))
{
ThrowIfDisposed();
if (role == null)
{
throw new ArgumentNullException(nameof(role));
}
if (claim == null)
{
throw new ArgumentNullException(nameof(claim));
}
if (role.AddClaim(claim))
{
MongoRepository.UpdateOne<TRole, TKey, List<MongoClaim>>(role, e => e.Claims, role.Claims);
}
return Task.FromResult(false);
}
/// <summary>
/// Removes the <paramref name="claim"/> given from the specified <paramref name="role"/>.
/// </summary>
/// <param name="role">The role to remove the claim from.</param>
/// <param name="claim">The claim to remove from the role.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>The <see cref="Task"/> that represents the asynchronous operation.</returns>
public async virtual Task RemoveClaimAsync(TRole role, Claim claim, CancellationToken cancellationToken = default(CancellationToken))
{
ThrowIfDisposed();
if (role == null)
{
throw new ArgumentNullException(nameof(role));
}
if (claim == null)
{
throw new ArgumentNullException(nameof(claim));
}
if (role.RemoveClaim(claim))
{
await MongoRepository.UpdateOneAsync<TRole, TKey, List<MongoClaim>>(role, e => e.Claims, role.Claims);
}
}
/// <summary>
/// A navigation property for the roles the store contains.
/// </summary>
public virtual IQueryable<TRole> Roles => Context.GetCollection<TRole>().AsQueryable();
/// <summary>
/// Creates a entity representing a role claim.
/// </summary>
/// <param name="role">The associated role.</param>
/// <param name="claim">The associated claim.</param>
/// <returns>The role claim entity.</returns>
protected virtual TRoleClaim CreateRoleClaim(TRole role, Claim claim)
=> new TRoleClaim { RoleId = role.Id, ClaimType = claim.Type, ClaimValue = claim.Value };
}
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+99
View File
@@ -0,0 +1,99 @@
//------------------------------------------------------------------------------
// <auto-generated>
// Ce code a été généré par un outil.
// Version du runtime :4.0.30319.42000
//
// Les modifications apportées à ce fichier peuvent provoquer un comportement incorrect et seront perdues si
// le code est régénéré.
// </auto-generated>
//------------------------------------------------------------------------------
namespace AspNetCore.Identity.MongoDbCore {
using System;
/// <summary>
/// Une classe de ressource fortement typée destinée, entre autres, à la consultation des chaînes localisées.
/// </summary>
// Cette classe a été générée automatiquement par la classe StronglyTypedResourceBuilder
// à l'aide d'un outil, tel que ResGen ou Visual Studio.
// Pour ajouter ou supprimer un membre, modifiez votre fichier .ResX, puis réexécutez ResGen
// avec l'option /str ou régénérez votre projet VS.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources() {
}
/// <summary>
/// Retourne l'instance ResourceManager mise en cache utilisée par cette classe.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("AspNetCore.Identity.MongoDbCore.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Remplace la propriété CurrentUICulture du thread actuel pour toutes
/// les recherches de ressources à l'aide de cette classe de ressource fortement typée.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
/// <summary>
/// Recherche une chaîne localisée semblable à AddEntityFrameworkStores can only be called with a role that derives from IdentityRole&lt;TKey, TUserRole, TRoleClaim&gt;..
/// </summary>
internal static string NotIdentityRole {
get {
return ResourceManager.GetString("NotIdentityRole", resourceCulture);
}
}
/// <summary>
/// Recherche une chaîne localisée semblable à AddEntityFrameworkStores can only be called with a user that derives from IdentityUser&lt;TKey, TUserClaim, TUserRole, TUserLogin, TUserToken&gt;..
/// </summary>
internal static string NotIdentityUser {
get {
return ResourceManager.GetString("NotIdentityUser", resourceCulture);
}
}
/// <summary>
/// Recherche une chaîne localisée semblable à Role {0} does not exist..
/// </summary>
internal static string RoleNotFound {
get {
return ResourceManager.GetString("RoleNotFound", resourceCulture);
}
}
/// <summary>
/// Recherche une chaîne localisée semblable à Value cannot be null or empty..
/// </summary>
internal static string ValueCannotBeNullOrEmpty {
get {
return ResourceManager.GetString("ValueCannotBeNullOrEmpty", resourceCulture);
}
}
}
}
+136
View File
@@ -0,0 +1,136 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="NotIdentityRole" xml:space="preserve">
<value>AddEntityFrameworkStores can only be called with a role that derives from IdentityRole&lt;TKey, TUserRole, TRoleClaim&gt;.</value>
<comment>error when the role does not derive from IdentityRole</comment>
</data>
<data name="NotIdentityUser" xml:space="preserve">
<value>AddEntityFrameworkStores can only be called with a user that derives from IdentityUser&lt;TKey, TUserClaim, TUserRole, TUserLogin, TUserToken&gt;.</value>
<comment>error when the user does not derive from IdentityUser</comment>
</data>
<data name="RoleNotFound" xml:space="preserve">
<value>Role {0} does not exist.</value>
<comment>error when a role does not exist</comment>
</data>
<data name="ValueCannotBeNullOrEmpty" xml:space="preserve">
<value>Value cannot be null or empty.</value>
<comment>error when something cannot be null or empty</comment>
</data>
</root>
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+136
View File
@@ -0,0 +1,136 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="NotIdentityRole" xml:space="preserve">
<value>AddEntityFrameworkStores can only be called with a role that derives from IdentityRole&lt;TKey, TUserRole, TRoleClaim&gt;.</value>
<comment>error when the role does not derive from IdentityRole</comment>
</data>
<data name="NotIdentityUser" xml:space="preserve">
<value>AddEntityFrameworkStores can only be called with a user that derives from IdentityUser&lt;TKey, TUserClaim, TUserRole, TUserLogin, TUserToken&gt;.</value>
<comment>error when the user does not derive from IdentityUser</comment>
</data>
<data name="RoleNotFound" xml:space="preserve">
<value>Role {0} does not exist.</value>
<comment>error when a role does not exist</comment>
</data>
<data name="ValueCannotBeNullOrEmpty" xml:space="preserve">
<value>Value cannot be null or empty.</value>
<comment>error when something cannot be null or empty</comment>
</data>
</root>