Browse Source

Temp

pull/107/head
Sebastian Stehle 9 years ago
parent
commit
def6fe218c
  1. 2
      src/Squidex.Domain.Apps.Core/Squidex.Domain.Apps.Core.csproj
  2. 2
      src/Squidex.Domain.Apps.Read.MongoDb/Squidex.Domain.Apps.Read.MongoDb.csproj
  3. 28
      src/Squidex.Domain.Users.MongoDb/MongoRole.cs
  4. 67
      src/Squidex.Domain.Users.MongoDb/MongoRoleStore.cs
  5. 199
      src/Squidex.Domain.Users.MongoDb/MongoUser.cs
  6. 34
      src/Squidex.Domain.Users.MongoDb/MongoUserClaim.cs
  7. 43
      src/Squidex.Domain.Users.MongoDb/MongoUserLogin.cs
  8. 279
      src/Squidex.Domain.Users.MongoDb/MongoUserStore.cs
  9. 27
      src/Squidex.Domain.Users.MongoDb/MongoUserToken.cs
  10. 1
      src/Squidex.Domain.Users.MongoDb/Squidex.Domain.Users.MongoDb.csproj
  11. 16
      src/Squidex.Domain.Users.MongoDb/WrappedIdentityRole.cs
  12. 46
      src/Squidex.Domain.Users.MongoDb/WrappedIdentityUser.cs
  13. 3
      src/Squidex.Domain.Users/UserManagerExtensions.cs
  14. 8
      src/Squidex.Infrastructure/CollectionExtensions.cs
  15. 3
      src/Squidex/Squidex.csproj

2
src/Squidex.Domain.Apps.Core/Squidex.Domain.Apps.Core.csproj

@ -10,7 +10,7 @@
<ProjectReference Include="..\Squidex.Infrastructure\Squidex.Infrastructure.csproj" /> <ProjectReference Include="..\Squidex.Infrastructure\Squidex.Infrastructure.csproj" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.OData.Core" Version="7.3.1" /> <PackageReference Include="Microsoft.OData.Core" Version="7.2.0" />
<PackageReference Include="NJsonSchema" Version="9.5.0" /> <PackageReference Include="NJsonSchema" Version="9.5.0" />
<PackageReference Include="NodaTime" Version="2.2.0" /> <PackageReference Include="NodaTime" Version="2.2.0" />
<PackageReference Include="System.Collections.Immutable" Version="1.4.0" /> <PackageReference Include="System.Collections.Immutable" Version="1.4.0" />

2
src/Squidex.Domain.Apps.Read.MongoDb/Squidex.Domain.Apps.Read.MongoDb.csproj

@ -14,7 +14,7 @@
<ProjectReference Include="..\Squidex.Domain.Apps.Read\Squidex.Domain.Apps.Read.csproj" /> <ProjectReference Include="..\Squidex.Domain.Apps.Read\Squidex.Domain.Apps.Read.csproj" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.OData.Core" Version="7.3.1" /> <PackageReference Include="Microsoft.OData.Core" Version="7.2.0" />
<PackageReference Include="MongoDB.Driver" Version="2.4.4" /> <PackageReference Include="MongoDB.Driver" Version="2.4.4" />
<PackageReference Include="System.ValueTuple" Version="4.4.0" /> <PackageReference Include="System.ValueTuple" Version="4.4.0" />
</ItemGroup> </ItemGroup>

28
src/Squidex.Domain.Users.MongoDb/MongoRole.cs

@ -0,0 +1,28 @@
// ==========================================================================
// MongoRole.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes;
namespace Squidex.Domain.Users.MongoDb
{
public sealed class MongoRole : IRole
{
[BsonRepresentation(BsonType.ObjectId)]
[BsonElement]
public string Id { get; set; }
[BsonRequired]
[BsonElement]
public string Name { get; set; }
[BsonRequired]
[BsonElement]
public string NormalizedName { get; set; }
}
}

67
src/Squidex.Domain.Users.MongoDb/MongoRoleStore.cs

@ -9,82 +9,101 @@
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.MongoDB;
using MongoDB.Driver; using MongoDB.Driver;
using Squidex.Infrastructure.MongoDb;
using Squidex.Infrastructure.Tasks;
namespace Squidex.Domain.Users.MongoDb namespace Squidex.Domain.Users.MongoDb
{ {
public sealed class MongoRoleStore : IRoleStore<IRole>, IRoleFactory public sealed class MongoRoleStore : MongoRepositoryBase<MongoRole>, IRoleStore<IRole>, IRoleFactory
{ {
private readonly RoleStore<WrappedIdentityRole> innerStore;
public MongoRoleStore(IMongoDatabase database) public MongoRoleStore(IMongoDatabase database)
: base(database)
{ {
var rolesCollection = database.GetCollection<WrappedIdentityRole>("Identity_Roles"); }
IndexChecks.EnsureUniqueIndexOnNormalizedRoleName(rolesCollection); protected override string CollectionName()
{
return "Identity_Roles";
}
innerStore = new RoleStore<WrappedIdentityRole>(rolesCollection); protected override Task SetupCollectionAsync(IMongoCollection<MongoRole> collection)
{
return collection.Indexes.CreateOneAsync(Index.Ascending(x => x.NormalizedName), new CreateIndexOptions { Unique = true });
}
protected override MongoCollectionSettings CollectionSettings()
{
return new MongoCollectionSettings { WriteConcern = WriteConcern.WMajority };
} }
public void Dispose() public void Dispose()
{ {
innerStore.Dispose();
} }
public IRole Create(string name) public IRole Create(string name)
{ {
return new WrappedIdentityRole { Name = name }; return new MongoRole { Name = name };
} }
public async Task<IRole> FindByIdAsync(string roleId, CancellationToken cancellationToken) public async Task<IRole> FindByIdAsync(string roleId, CancellationToken cancellationToken)
{ {
return await innerStore.FindByIdAsync(roleId, cancellationToken); return await Collection.Find(x => x.Id == roleId).FirstOrDefaultAsync(cancellationToken);
} }
public async Task<IRole> FindByNameAsync(string normalizedRoleName, CancellationToken cancellationToken) public async Task<IRole> FindByNameAsync(string normalizedRoleName, CancellationToken cancellationToken)
{ {
return await innerStore.FindByNameAsync(normalizedRoleName, cancellationToken); return await Collection.Find(x => x.NormalizedName == normalizedRoleName).FirstOrDefaultAsync(cancellationToken);
} }
public Task<IdentityResult> CreateAsync(IRole role, CancellationToken cancellationToken) public async Task<IdentityResult> CreateAsync(IRole role, CancellationToken cancellationToken)
{ {
return innerStore.CreateAsync((WrappedIdentityRole)role, cancellationToken); await Collection.InsertOneAsync((MongoRole)role, null, cancellationToken);
return IdentityResult.Success;
} }
public Task<IdentityResult> UpdateAsync(IRole role, CancellationToken cancellationToken) public async Task<IdentityResult> UpdateAsync(IRole role, CancellationToken cancellationToken)
{ {
return innerStore.UpdateAsync((WrappedIdentityRole)role, cancellationToken); await Collection.ReplaceOneAsync(x => x.Id == ((MongoRole)role).Id, (MongoRole)role, null, cancellationToken);
return IdentityResult.Success;
} }
public Task<IdentityResult> DeleteAsync(IRole role, CancellationToken cancellationToken) public async Task<IdentityResult> DeleteAsync(IRole role, CancellationToken cancellationToken)
{ {
return innerStore.DeleteAsync((WrappedIdentityRole)role, cancellationToken); await Collection.DeleteOneAsync(x => x.Id == ((MongoRole)role).Id, null, cancellationToken);
return IdentityResult.Success;
} }
public Task<string> GetRoleIdAsync(IRole role, CancellationToken cancellationToken) public Task<string> GetRoleIdAsync(IRole role, CancellationToken cancellationToken)
{ {
return innerStore.GetRoleIdAsync((WrappedIdentityRole)role, cancellationToken); return Task.FromResult(((MongoRole)role).Id);
} }
public Task<string> GetRoleNameAsync(IRole role, CancellationToken cancellationToken) public Task<string> GetRoleNameAsync(IRole role, CancellationToken cancellationToken)
{ {
return innerStore.GetRoleNameAsync((WrappedIdentityRole)role, cancellationToken); return Task.FromResult(((MongoRole)role).Name);
} }
public Task SetRoleNameAsync(IRole role, string roleName, CancellationToken cancellationToken) public Task<string> GetNormalizedRoleNameAsync(IRole role, CancellationToken cancellationToken)
{ {
return innerStore.SetRoleNameAsync((WrappedIdentityRole)role, roleName, cancellationToken); return Task.FromResult(((MongoRole)role).NormalizedName);
} }
public Task<string> GetNormalizedRoleNameAsync(IRole role, CancellationToken cancellationToken) public Task SetRoleNameAsync(IRole role, string roleName, CancellationToken cancellationToken)
{ {
return innerStore.GetNormalizedRoleNameAsync((WrappedIdentityRole)role, cancellationToken); ((MongoRole)role).Name = roleName;
return TaskHelper.Done;
} }
public Task SetNormalizedRoleNameAsync(IRole role, string normalizedName, CancellationToken cancellationToken) public Task SetNormalizedRoleNameAsync(IRole role, string normalizedName, CancellationToken cancellationToken)
{ {
return innerStore.SetNormalizedRoleNameAsync((WrappedIdentityRole)role, normalizedName, cancellationToken); ((MongoRole)role).NormalizedName = normalizedName;
return TaskHelper.Done;
} }
} }
} }

199
src/Squidex.Domain.Users.MongoDb/MongoUser.cs

@ -0,0 +1,199 @@
// ==========================================================================
// MongoUser.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using Microsoft.AspNetCore.Identity;
using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes;
using Squidex.Infrastructure;
using Squidex.Shared.Users;
namespace Squidex.Domain.Users.MongoDb
{
public sealed class MongoUser : IUser
{
[BsonRepresentation(BsonType.ObjectId)]
[BsonElement]
public string Id { get; set; }
[BsonIgnoreIfNull]
[BsonElement]
public string SecurityStamp { get; set; }
[BsonRequired]
[BsonElement]
public string UserName { get; set; }
[BsonRequired]
[BsonElement]
public string NormalizedUserName { get; set; }
[BsonRequired]
[BsonElement]
public string Email { get; set; }
[BsonRequired]
[BsonElement]
public string NormalizedEmail { get; set; }
[BsonIgnoreIfNull]
[BsonElement]
public string PhoneNumber { get; set; }
[BsonIgnoreIfNull]
[BsonElement]
public string PasswordHash { get; set; }
[BsonRequired]
[BsonElement]
public bool EmailConfirmed { get; set; }
[BsonIgnoreIfDefault]
[BsonElement]
public bool PhoneNumberConfirmed { get; set; }
[BsonIgnoreIfDefault]
[BsonElement]
public bool TwoFactorEnabled { get; set; }
[BsonIgnoreIfDefault]
[BsonElement]
public bool LockoutEnabled { get; set; }
[BsonIgnoreIfNull]
[BsonElement]
public DateTime? LockoutEndDateUtc { get; set; }
[BsonIgnoreIfDefault]
[BsonElement]
public int AccessFailedCount { get; set; }
[BsonRequired]
[BsonElement]
public List<string> Roles { get; set; } = new List<string>();
[BsonRequired]
[BsonElement]
public List<MongoUserClaim> Claims { get; set; } = new List<MongoUserClaim>();
[BsonRequired]
[BsonElement]
public List<MongoUserToken> Tokens { get; set; } = new List<MongoUserToken>();
[BsonRequired]
[BsonElement]
public List<MongoUserLogin> Logins { get; set; } = new List<MongoUserLogin>();
public bool IsLocked
{
get { return LockoutEndDateUtc != null && LockoutEndDateUtc.Value > DateTime.UtcNow; }
}
IReadOnlyList<Claim> IUser.Claims
{
get { return Claims.Select(x => new Claim(x.Type, x.Value)).ToList(); }
}
IReadOnlyList<ExternalLogin> IUser.Logins
{
get { return Logins.Select(x => new ExternalLogin(x.LoginProvider, x.ProviderKey, x.ProviderDisplayName)).ToList(); }
}
public MongoUser()
{
Id = ObjectId.GenerateNewId().ToString();
}
public void UpdateEmail(string email)
{
Email = UserName = email;
}
public void AddRole(string role)
{
Roles.Add(role);
}
public void RemoveRole(string role)
{
Roles.Remove(role);
}
public void AddLogin(UserLoginInfo login)
{
Logins.Add(login);
}
public void RemoveLogin(string loginProvider, string providerKey)
{
Logins.RemoveAll(l => l.LoginProvider == loginProvider && l.ProviderKey == providerKey);
}
public void AddClaim(Claim claim)
{
Claims.Add(claim);
}
public void AddClaims(IEnumerable<Claim> claims)
{
claims.Foreach(AddClaim);
}
public void RemoveClaim(Claim claim)
{
Claims.RemoveAll(c => c.Type == claim.Type && c.Value == claim.Value);
}
public void RemoveClaims(IEnumerable<Claim> claims)
{
claims.Foreach(RemoveClaim);
}
public void SetClaim(string type, string value)
{
SetClaim(new Claim(type, value));
}
public void SetClaim(Claim claim)
{
ReplaceClaim(claim, claim);
}
public string GetToken(string loginProider, string name)
{
return Tokens.FirstOrDefault(t => t.LoginProvider == loginProider && t.Name == name)?.Value;
}
public void AddToken(string loginProvider, string name, string value)
{
Tokens.Add(new MongoUserToken { LoginProvider = loginProvider, Name = name, Value = value });
}
public void RemoveToken(string loginProvider, string name)
{
Tokens.RemoveAll(t => t.LoginProvider == loginProvider && t.Name == name);
}
public void ReplaceClaim(Claim existingClaim, Claim newClaim)
{
RemoveClaim(existingClaim);
AddClaim(newClaim);
}
public void SetToken(string loginProider, string name, string value)
{
RemoveToken(loginProider, name);
AddToken(loginProider, name, value);
}
}
}

34
src/Squidex.Domain.Users.MongoDb/MongoUserClaim.cs

@ -0,0 +1,34 @@
// ==========================================================================
// MongoUserClaim.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
using System.Security.Claims;
using MongoDB.Bson.Serialization.Attributes;
namespace Squidex.Domain.Users.MongoDb
{
public sealed class MongoUserClaim
{
[BsonRequired]
[BsonElement]
public string Type { get; set; }
[BsonRequired]
[BsonElement]
public string Value { get; set; }
public static implicit operator MongoUserClaim(Claim claim)
{
return new MongoUserClaim { Type = claim.Type, Value = claim.Value };
}
public static implicit operator Claim(MongoUserClaim userClaim)
{
return new Claim(userClaim.Type, userClaim.Value);
}
}
}

43
src/Squidex.Domain.Users.MongoDb/MongoUserLogin.cs

@ -0,0 +1,43 @@
// ==========================================================================
// MongoUserLogin.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
using Microsoft.AspNetCore.Identity;
using MongoDB.Bson.Serialization.Attributes;
namespace Squidex.Domain.Users.MongoDb
{
public sealed class MongoUserLogin
{
[BsonRequired]
[BsonElement]
public string LoginProvider { get; set; }
[BsonRequired]
[BsonElement]
public string ProviderDisplayName { get; set; }
[BsonRequired]
[BsonElement]
public string ProviderKey { get; set; }
public static implicit operator MongoUserLogin(UserLoginInfo login)
{
return new MongoUserLogin
{
LoginProvider = login.LoginProvider,
ProviderKey = login.ProviderKey,
ProviderDisplayName = login.ProviderDisplayName
};
}
public static implicit operator UserLoginInfo(MongoUserLogin userLogin)
{
return new UserLoginInfo(userLogin.LoginProvider, userLogin.ProviderKey, userLogin.ProviderDisplayName);
}
}
}

279
src/Squidex.Domain.Users.MongoDb/MongoUserStore.cs

@ -13,13 +13,15 @@ using System.Security.Claims;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.MongoDB;
using MongoDB.Driver; using MongoDB.Driver;
using Squidex.Infrastructure.MongoDb;
using Squidex.Infrastructure.Tasks;
using Squidex.Shared.Users; using Squidex.Shared.Users;
namespace Squidex.Domain.Users.MongoDb namespace Squidex.Domain.Users.MongoDb
{ {
public sealed class MongoUserStore : public sealed class MongoUserStore :
MongoRepositoryBase<MongoUser>,
IUserPasswordStore<IUser>, IUserPasswordStore<IUser>,
IUserRoleStore<IUser>, IUserRoleStore<IUser>,
IUserLoginStore<IUser>, IUserLoginStore<IUser>,
@ -34,296 +36,357 @@ namespace Squidex.Domain.Users.MongoDb
IUserResolver, IUserResolver,
IQueryableUserStore<IUser> IQueryableUserStore<IUser>
{ {
private readonly UserStore<WrappedIdentityUser> innerStore;
public MongoUserStore(IMongoDatabase database) public MongoUserStore(IMongoDatabase database)
: base(database)
{
}
protected override string CollectionName()
{ {
var usersCollection = database.GetCollection<WrappedIdentityUser>("Identity_Users"); return "Identity_Users";
}
IndexChecks.EnsureUniqueIndexOnNormalizedEmail(usersCollection); protected override Task SetupCollectionAsync(IMongoCollection<MongoUser> collection)
IndexChecks.EnsureUniqueIndexOnNormalizedUserName(usersCollection); {
return Task.WhenAll(
collection.Indexes.CreateOneAsync(Index.Ascending(x => x.NormalizedUserName), new CreateIndexOptions { Unique = true }),
collection.Indexes.CreateOneAsync(Index.Ascending(x => x.NormalizedEmail), new CreateIndexOptions { Unique = true }));
}
innerStore = new UserStore<WrappedIdentityUser>(usersCollection); protected override MongoCollectionSettings CollectionSettings()
{
return new MongoCollectionSettings { WriteConcern = WriteConcern.WMajority };
} }
public void Dispose() public void Dispose()
{ {
innerStore.Dispose();
} }
public IQueryable<IUser> Users public IQueryable<IUser> Users
{ {
get { return innerStore.Users; } get { return Collection.AsQueryable(); }
} }
public IUser Create(string email) public IUser Create(string email)
{ {
return new WrappedIdentityUser { Email = email, UserName = email }; return new MongoUser { Email = email, UserName = email };
} }
public async Task<IUser> FindByIdAsync(string userId) public async Task<IUser> FindByIdAsync(string id)
{ {
return await innerStore.FindByIdAsync(userId, CancellationToken.None); return await Collection.Find(x => x.Id == id).FirstOrDefaultAsync();
} }
public async Task<IUser> FindByIdAsync(string userId, CancellationToken cancellationToken) public async Task<IUser> FindByIdAsync(string userId, CancellationToken cancellationToken)
{ {
return await innerStore.FindByIdAsync(userId, cancellationToken); return await Collection.Find(x => x.Id == userId).FirstOrDefaultAsync(cancellationToken);
} }
public async Task<IUser> FindByEmailAsync(string normalizedEmail, CancellationToken cancellationToken) public async Task<IUser> FindByEmailAsync(string normalizedEmail, CancellationToken cancellationToken)
{ {
return await innerStore.FindByEmailAsync(normalizedEmail, cancellationToken); return await Collection.Find(x => x.NormalizedEmail == normalizedEmail).FirstOrDefaultAsync(cancellationToken);
} }
public async Task<IUser> FindByNameAsync(string normalizedUserName, CancellationToken cancellationToken) public async Task<IUser> FindByNameAsync(string normalizedUserName, CancellationToken cancellationToken)
{ {
return await innerStore.FindByNameAsync(normalizedUserName, cancellationToken); return await Collection.Find(x => x.NormalizedEmail == normalizedUserName).FirstOrDefaultAsync(cancellationToken);
} }
public async Task<IUser> FindByLoginAsync(string loginProvider, string providerKey, CancellationToken cancellationToken) public async Task<IUser> FindByLoginAsync(string loginProvider, string providerKey, CancellationToken cancellationToken)
{ {
return await innerStore.FindByLoginAsync(loginProvider, providerKey, cancellationToken); return await Collection.Find(x => x.Logins.Any(y => y.LoginProvider == loginProvider && y.ProviderKey == providerKey)).FirstOrDefaultAsync(cancellationToken);
} }
public async Task<IList<IUser>> GetUsersForClaimAsync(Claim claim, CancellationToken cancellationToken) public async Task<IList<IUser>> GetUsersForClaimAsync(Claim claim, CancellationToken cancellationToken)
{ {
return (await innerStore.GetUsersForClaimAsync(claim, cancellationToken)).OfType<IUser>().ToList(); return (await Collection.Find(x => x.Claims.Any(y => y.Type == claim.Type && y.Value == claim.Value)).ToListAsync(cancellationToken)).OfType<IUser>().ToList();
} }
public async Task<IList<IUser>> GetUsersInRoleAsync(string roleName, CancellationToken cancellationToken) public async Task<IList<IUser>> GetUsersInRoleAsync(string roleName, CancellationToken cancellationToken)
{ {
return (await innerStore.GetUsersInRoleAsync(roleName, cancellationToken)).OfType<IUser>().ToList(); return (await Collection.Find(x => x.Roles.Contains(roleName)).ToListAsync(cancellationToken)).OfType<IUser>().ToList();
} }
public Task<IdentityResult> CreateAsync(IUser user, CancellationToken cancellationToken) public async Task<IdentityResult> CreateAsync(IUser user, CancellationToken cancellationToken)
{ {
return innerStore.CreateAsync((WrappedIdentityUser)user, cancellationToken); await Collection.InsertOneAsync((MongoUser)user, null, cancellationToken);
return IdentityResult.Success;
} }
public Task<IdentityResult> UpdateAsync(IUser user, CancellationToken cancellationToken) public async Task<IdentityResult> UpdateAsync(IUser user, CancellationToken cancellationToken)
{ {
return innerStore.UpdateAsync((WrappedIdentityUser)user, cancellationToken); await Collection.ReplaceOneAsync(x => x.Id == user.Id, (MongoUser)user, null, cancellationToken);
return IdentityResult.Success;
} }
public Task<IdentityResult> DeleteAsync(IUser user, CancellationToken cancellationToken) public async Task<IdentityResult> DeleteAsync(IUser user, CancellationToken cancellationToken)
{ {
return innerStore.DeleteAsync((WrappedIdentityUser)user, cancellationToken); await Collection.DeleteOneAsync(x => x.Id == user.Id, null, cancellationToken);
return IdentityResult.Success;
} }
public Task<string> GetUserIdAsync(IUser user, CancellationToken cancellationToken) public Task<string> GetUserIdAsync(IUser user, CancellationToken cancellationToken)
{ {
return innerStore.GetUserIdAsync((WrappedIdentityUser)user, cancellationToken); return Task.FromResult(((MongoUser)user).Id);
} }
public Task<string> GetUserNameAsync(IUser user, CancellationToken cancellationToken) public Task<string> GetUserNameAsync(IUser user, CancellationToken cancellationToken)
{ {
return innerStore.GetUserNameAsync((WrappedIdentityUser)user, cancellationToken); return Task.FromResult(((MongoUser)user).UserName);
} }
public Task SetUserNameAsync(IUser user, string userName, CancellationToken cancellationToken) public Task<string> GetNormalizedUserNameAsync(IUser user, CancellationToken cancellationToken)
{ {
return innerStore.SetUserNameAsync((WrappedIdentityUser)user, userName, cancellationToken); return Task.FromResult(((MongoUser)user).NormalizedUserName);
} }
public Task<string> GetNormalizedUserNameAsync(IUser user, CancellationToken cancellationToken) public Task<string> GetPasswordHashAsync(IUser user, CancellationToken cancellationToken)
{ {
return innerStore.GetNormalizedUserNameAsync((WrappedIdentityUser)user, cancellationToken); return Task.FromResult(((MongoUser)user).PasswordHash);
} }
public Task SetNormalizedUserNameAsync(IUser user, string normalizedName, CancellationToken cancellationToken) public Task<IList<string>> GetRolesAsync(IUser user, CancellationToken cancellationToken)
{ {
return innerStore.SetNormalizedUserNameAsync((WrappedIdentityUser)user, normalizedName, cancellationToken); return Task.FromResult<IList<string>>(((MongoUser)user).Roles);
} }
public Task<string> GetPasswordHashAsync(IUser user, CancellationToken cancellationToken) public Task<bool> IsInRoleAsync(IUser user, string roleName, CancellationToken cancellationToken)
{ {
return innerStore.GetPasswordHashAsync((WrappedIdentityUser)user, cancellationToken); return Task.FromResult(((MongoUser)user).Roles.Contains(roleName));
} }
public Task SetPasswordHashAsync(IUser user, string passwordHash, CancellationToken cancellationToken) public Task<IList<UserLoginInfo>> GetLoginsAsync(IUser user, CancellationToken cancellationToken)
{ {
return innerStore.SetPasswordHashAsync((WrappedIdentityUser)user, passwordHash, cancellationToken); return Task.FromResult<IList<UserLoginInfo>>(((MongoUser)user).Logins.Select(x => (UserLoginInfo)x).ToList());
} }
public Task AddToRoleAsync(IUser user, string roleName, CancellationToken cancellationToken) public Task<string> GetSecurityStampAsync(IUser user, CancellationToken cancellationToken)
{ {
return innerStore.AddToRoleAsync((WrappedIdentityUser)user, roleName, cancellationToken); return Task.FromResult(((MongoUser)user).SecurityStamp);
} }
public Task RemoveFromRoleAsync(IUser user, string roleName, CancellationToken cancellationToken) public Task<string> GetEmailAsync(IUser user, CancellationToken cancellationToken)
{ {
return innerStore.RemoveFromRoleAsync((WrappedIdentityUser)user, roleName, cancellationToken); return Task.FromResult(((MongoUser)user).Email);
} }
public Task<IList<string>> GetRolesAsync(IUser user, CancellationToken cancellationToken) public Task<bool> GetEmailConfirmedAsync(IUser user, CancellationToken cancellationToken)
{ {
return innerStore.GetRolesAsync((WrappedIdentityUser)user, cancellationToken); return Task.FromResult(((MongoUser)user).EmailConfirmed);
} }
public Task<bool> IsInRoleAsync(IUser user, string roleName, CancellationToken cancellationToken) public Task<string> GetNormalizedEmailAsync(IUser user, CancellationToken cancellationToken)
{ {
return innerStore.IsInRoleAsync((WrappedIdentityUser)user, roleName, cancellationToken); return Task.FromResult(((MongoUser)user).NormalizedEmail);
} }
public Task AddLoginAsync(IUser user, UserLoginInfo login, CancellationToken cancellationToken) public Task<IList<Claim>> GetClaimsAsync(IUser user, CancellationToken cancellationToken)
{ {
return innerStore.AddLoginAsync((WrappedIdentityUser)user, login, cancellationToken); return Task.FromResult<IList<Claim>>(((MongoUser)user).Claims.Select(x => (Claim)x).ToList());
} }
public Task RemoveLoginAsync(IUser user, string loginProvider, string providerKey, CancellationToken cancellationToken) public Task<string> GetPhoneNumberAsync(IUser user, CancellationToken cancellationToken)
{ {
return innerStore.RemoveLoginAsync((WrappedIdentityUser)user, loginProvider, providerKey, cancellationToken); return Task.FromResult(((MongoUser)user).PhoneNumber);
} }
public Task<IList<UserLoginInfo>> GetLoginsAsync(IUser user, CancellationToken cancellationToken) public Task<bool> GetPhoneNumberConfirmedAsync(IUser user, CancellationToken cancellationToken)
{ {
return innerStore.GetLoginsAsync((WrappedIdentityUser)user, cancellationToken); return Task.FromResult(((MongoUser)user).PhoneNumberConfirmed);
} }
public Task<string> GetSecurityStampAsync(IUser user, CancellationToken cancellationToken) public Task<bool> GetTwoFactorEnabledAsync(IUser user, CancellationToken cancellationToken)
{ {
return innerStore.GetSecurityStampAsync((WrappedIdentityUser)user, cancellationToken); return Task.FromResult(((MongoUser)user).TwoFactorEnabled);
} }
public Task SetSecurityStampAsync(IUser user, string stamp, CancellationToken cancellationToken) public Task<DateTimeOffset?> GetLockoutEndDateAsync(IUser user, CancellationToken cancellationToken)
{ {
return innerStore.SetSecurityStampAsync((WrappedIdentityUser)user, stamp, cancellationToken); return Task.FromResult<DateTimeOffset?>(((MongoUser)user).LockoutEndDateUtc);
} }
public Task<string> GetEmailAsync(IUser user, CancellationToken cancellationToken) public Task<int> GetAccessFailedCountAsync(IUser user, CancellationToken cancellationToken)
{ {
return innerStore.GetEmailAsync((WrappedIdentityUser)user, cancellationToken); return Task.FromResult(((MongoUser)user).AccessFailedCount);
} }
public Task SetEmailAsync(IUser user, string email, CancellationToken cancellationToken) public Task<bool> GetLockoutEnabledAsync(IUser user, CancellationToken cancellationToken)
{ {
return innerStore.SetEmailAsync((WrappedIdentityUser)user, email, cancellationToken); return Task.FromResult(((MongoUser)user).LockoutEnabled);
} }
public Task<bool> GetEmailConfirmedAsync(IUser user, CancellationToken cancellationToken) public Task<string> GetTokenAsync(IUser user, string loginProvider, string name, CancellationToken cancellationToken)
{ {
return innerStore.GetEmailConfirmedAsync((WrappedIdentityUser)user, cancellationToken); return Task.FromResult(((MongoUser)user).GetToken(loginProvider, name));
} }
public Task SetEmailConfirmedAsync(IUser user, bool confirmed, CancellationToken cancellationToken) public Task<bool> HasPasswordAsync(IUser user, CancellationToken cancellationToken)
{ {
return innerStore.SetEmailConfirmedAsync((WrappedIdentityUser)user, confirmed, cancellationToken); return Task.FromResult(!string.IsNullOrWhiteSpace(((MongoUser)user).PasswordHash));
} }
public Task<string> GetNormalizedEmailAsync(IUser user, CancellationToken cancellationToken) public Task SetUserNameAsync(IUser user, string userName, CancellationToken cancellationToken)
{ {
return innerStore.GetNormalizedEmailAsync((WrappedIdentityUser)user, cancellationToken); ((MongoUser)user).UserName = userName;
return TaskHelper.Done;
} }
public Task SetNormalizedEmailAsync(IUser user, string normalizedEmail, CancellationToken cancellationToken) public Task SetNormalizedUserNameAsync(IUser user, string normalizedName, CancellationToken cancellationToken)
{ {
return innerStore.SetNormalizedEmailAsync((WrappedIdentityUser)user, normalizedEmail, cancellationToken); ((MongoUser)user).NormalizedUserName = normalizedName;
return TaskHelper.Done;
} }
public Task<IList<Claim>> GetClaimsAsync(IUser user, CancellationToken cancellationToken) public Task SetPasswordHashAsync(IUser user, string passwordHash, CancellationToken cancellationToken)
{ {
return innerStore.GetClaimsAsync((WrappedIdentityUser)user, cancellationToken); ((MongoUser)user).PasswordHash = passwordHash;
return TaskHelper.Done;
} }
public Task AddClaimsAsync(IUser user, IEnumerable<Claim> claims, CancellationToken cancellationToken) public Task AddToRoleAsync(IUser user, string roleName, CancellationToken cancellationToken)
{ {
return innerStore.AddClaimsAsync((WrappedIdentityUser)user, claims, cancellationToken); ((MongoUser)user).AddRole(roleName);
return TaskHelper.Done;
} }
public Task ReplaceClaimAsync(IUser user, Claim claim, Claim newClaim, CancellationToken cancellationToken) public Task RemoveFromRoleAsync(IUser user, string roleName, CancellationToken cancellationToken)
{ {
return innerStore.ReplaceClaimAsync((WrappedIdentityUser)user, claim, newClaim, cancellationToken); ((MongoUser)user).RemoveRole(roleName);
return TaskHelper.Done;
} }
public Task RemoveClaimsAsync(IUser user, IEnumerable<Claim> claims, CancellationToken cancellationToken) public Task AddLoginAsync(IUser user, UserLoginInfo login, CancellationToken cancellationToken)
{ {
return innerStore.RemoveClaimsAsync((WrappedIdentityUser)user, claims, cancellationToken); ((MongoUser)user).AddLogin(login);
return TaskHelper.Done;
} }
public Task<string> GetPhoneNumberAsync(IUser user, CancellationToken cancellationToken) public Task RemoveLoginAsync(IUser user, string loginProvider, string providerKey, CancellationToken cancellationToken)
{ {
return innerStore.GetPhoneNumberAsync((WrappedIdentityUser)user, cancellationToken); ((MongoUser)user).RemoveLogin(loginProvider, providerKey);
return TaskHelper.Done;
} }
public Task SetPhoneNumberAsync(IUser user, string phoneNumber, CancellationToken cancellationToken) public Task SetSecurityStampAsync(IUser user, string stamp, CancellationToken cancellationToken)
{ {
return innerStore.SetPhoneNumberAsync((WrappedIdentityUser)user, phoneNumber, cancellationToken); ((MongoUser)user).SecurityStamp = stamp;
return TaskHelper.Done;
} }
public Task<bool> GetPhoneNumberConfirmedAsync(IUser user, CancellationToken cancellationToken) public Task SetEmailAsync(IUser user, string email, CancellationToken cancellationToken)
{ {
return innerStore.GetPhoneNumberConfirmedAsync((WrappedIdentityUser)user, cancellationToken); ((MongoUser)user).Email = email;
return TaskHelper.Done;
} }
public Task SetPhoneNumberConfirmedAsync(IUser user, bool confirmed, CancellationToken cancellationToken) public Task SetEmailConfirmedAsync(IUser user, bool confirmed, CancellationToken cancellationToken)
{ {
return innerStore.SetPhoneNumberConfirmedAsync((WrappedIdentityUser)user, confirmed, cancellationToken); ((MongoUser)user).EmailConfirmed = confirmed;
return TaskHelper.Done;
} }
public Task<bool> GetTwoFactorEnabledAsync(IUser user, CancellationToken cancellationToken) public Task SetNormalizedEmailAsync(IUser user, string normalizedEmail, CancellationToken cancellationToken)
{ {
return innerStore.GetTwoFactorEnabledAsync((WrappedIdentityUser)user, cancellationToken); ((MongoUser)user).NormalizedEmail = normalizedEmail;
return TaskHelper.Done;
} }
public Task SetTwoFactorEnabledAsync(IUser user, bool enabled, CancellationToken cancellationToken) public Task AddClaimsAsync(IUser user, IEnumerable<Claim> claims, CancellationToken cancellationToken)
{ {
return innerStore.SetTwoFactorEnabledAsync((WrappedIdentityUser)user, enabled, cancellationToken); ((MongoUser)user).AddClaims(claims);
return TaskHelper.Done;
} }
public Task<DateTimeOffset?> GetLockoutEndDateAsync(IUser user, CancellationToken cancellationToken) public Task ReplaceClaimAsync(IUser user, Claim claim, Claim newClaim, CancellationToken cancellationToken)
{ {
return innerStore.GetLockoutEndDateAsync((WrappedIdentityUser)user, cancellationToken); ((MongoUser)user).ReplaceClaim(claim, newClaim);
return TaskHelper.Done;
} }
public Task SetLockoutEndDateAsync(IUser user, DateTimeOffset? lockoutEnd, CancellationToken cancellationToken) public Task RemoveClaimsAsync(IUser user, IEnumerable<Claim> claims, CancellationToken cancellationToken)
{ {
return innerStore.SetLockoutEndDateAsync((WrappedIdentityUser)user, lockoutEnd, cancellationToken); ((MongoUser)user).RemoveClaims(claims);
return TaskHelper.Done;
} }
public Task<int> GetAccessFailedCountAsync(IUser user, CancellationToken cancellationToken) public Task SetPhoneNumberAsync(IUser user, string phoneNumber, CancellationToken cancellationToken)
{ {
return innerStore.GetAccessFailedCountAsync((WrappedIdentityUser)user, cancellationToken); ((MongoUser)user).PhoneNumber = phoneNumber;
return TaskHelper.Done;
} }
public Task<int> IncrementAccessFailedCountAsync(IUser user, CancellationToken cancellationToken) public Task SetPhoneNumberConfirmedAsync(IUser user, bool confirmed, CancellationToken cancellationToken)
{ {
return innerStore.IncrementAccessFailedCountAsync((WrappedIdentityUser)user, cancellationToken); ((MongoUser)user).PhoneNumberConfirmed = confirmed;
return TaskHelper.Done;
} }
public Task ResetAccessFailedCountAsync(IUser user, CancellationToken cancellationToken) public Task SetTwoFactorEnabledAsync(IUser user, bool enabled, CancellationToken cancellationToken)
{ {
return innerStore.ResetAccessFailedCountAsync((WrappedIdentityUser)user, cancellationToken); ((MongoUser)user).TwoFactorEnabled = enabled;
return TaskHelper.Done;
} }
public Task<bool> GetLockoutEnabledAsync(IUser user, CancellationToken cancellationToken) public Task SetLockoutEndDateAsync(IUser user, DateTimeOffset? lockoutEnd, CancellationToken cancellationToken)
{ {
return innerStore.GetLockoutEnabledAsync((WrappedIdentityUser)user, cancellationToken); ((MongoUser)user).LockoutEndDateUtc = lockoutEnd?.UtcDateTime;
return TaskHelper.Done;
} }
public Task SetLockoutEnabledAsync(IUser user, bool enabled, CancellationToken cancellationToken) public Task<int> IncrementAccessFailedCountAsync(IUser user, CancellationToken cancellationToken)
{ {
return innerStore.SetLockoutEnabledAsync((WrappedIdentityUser)user, enabled, cancellationToken); ((MongoUser)user).AccessFailedCount++;
return Task.FromResult(((MongoUser)user).AccessFailedCount);
} }
public Task SetTokenAsync(IUser user, string loginProvider, string name, string value, CancellationToken cancellationToken) public Task ResetAccessFailedCountAsync(IUser user, CancellationToken cancellationToken)
{ {
return innerStore.SetTokenAsync((WrappedIdentityUser)user, loginProvider, name, value, cancellationToken); ((MongoUser)user).AccessFailedCount = 0;
return TaskHelper.Done;
} }
public Task RemoveTokenAsync(IUser user, string loginProvider, string name, CancellationToken cancellationToken) public Task SetLockoutEnabledAsync(IUser user, bool enabled, CancellationToken cancellationToken)
{ {
return innerStore.RemoveTokenAsync((WrappedIdentityUser)user, loginProvider, name, cancellationToken); ((MongoUser)user).LockoutEnabled = enabled;
return TaskHelper.Done;
} }
public Task<string> GetTokenAsync(IUser user, string loginProvider, string name, CancellationToken cancellationToken) public Task SetTokenAsync(IUser user, string loginProvider, string name, string value, CancellationToken cancellationToken)
{ {
return innerStore.GetTokenAsync((WrappedIdentityUser)user, loginProvider, name, cancellationToken); ((MongoUser)user).SetToken(loginProvider, name, value);
return TaskHelper.Done;
} }
public Task<bool> HasPasswordAsync(IUser user, CancellationToken cancellationToken) public Task RemoveTokenAsync(IUser user, string loginProvider, string name, CancellationToken cancellationToken)
{ {
return Task.FromResult(!string.IsNullOrWhiteSpace(((WrappedIdentityUser)user).PasswordHash)); ((MongoUser)user).RemoveToken(loginProvider, name);
return TaskHelper.Done;
} }
} }
} }

27
src/Squidex.Domain.Users.MongoDb/MongoUserToken.cs

@ -0,0 +1,27 @@
// ==========================================================================
// MongoUserToken.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
using MongoDB.Bson.Serialization.Attributes;
namespace Squidex.Domain.Users.MongoDb
{
public sealed class MongoUserToken
{
[BsonRequired]
[BsonElement]
public string LoginProvider { get; set; }
[BsonIgnoreIfDefault]
[BsonElement]
public string Name { get; set; }
[BsonRequired]
[BsonElement]
public string Value { get; set; }
}
}

1
src/Squidex.Domain.Users.MongoDb/Squidex.Domain.Users.MongoDb.csproj

@ -15,7 +15,6 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="IdentityServer4" Version="1.5.2" /> <PackageReference Include="IdentityServer4" Version="1.5.2" />
<PackageReference Include="Microsoft.AspNetCore.Identity" Version="1.1.2" /> <PackageReference Include="Microsoft.AspNetCore.Identity" Version="1.1.2" />
<PackageReference Include="Microsoft.AspNetCore.Identity.MongoDB" Version="1.0.2" />
<PackageReference Include="Microsoft.Win32.Registry" Version="4.4.0" /> <PackageReference Include="Microsoft.Win32.Registry" Version="4.4.0" />
<PackageReference Include="MongoDB.Driver" Version="2.4.4" /> <PackageReference Include="MongoDB.Driver" Version="2.4.4" />
<PackageReference Include="System.Security.Principal.Windows" Version="4.4.0" /> <PackageReference Include="System.Security.Principal.Windows" Version="4.4.0" />

16
src/Squidex.Domain.Users.MongoDb/WrappedIdentityRole.cs

@ -1,16 +0,0 @@
// ==========================================================================
// WrappedIdentityRole.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
using Microsoft.AspNetCore.Identity.MongoDB;
namespace Squidex.Domain.Users.MongoDb
{
public sealed class WrappedIdentityRole : IdentityRole, IRole
{
}
}

46
src/Squidex.Domain.Users.MongoDb/WrappedIdentityUser.cs

@ -1,46 +0,0 @@
// ==========================================================================
// WrappedIdentityUser.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using Microsoft.AspNetCore.Identity.MongoDB;
using Squidex.Shared.Users;
namespace Squidex.Domain.Users.MongoDb
{
public sealed class WrappedIdentityUser : IdentityUser, IUser
{
public bool IsLocked
{
get { return LockoutEndDateUtc != null && LockoutEndDateUtc.Value > DateTime.UtcNow; }
}
IReadOnlyList<Claim> IUser.Claims
{
get { return Claims.Select(x => new Claim(x.Type, x.Value)).ToList(); }
}
IReadOnlyList<ExternalLogin> IUser.Logins
{
get { return Logins.Select(x => new ExternalLogin(x.LoginProvider, x.ProviderKey, x.ProviderDisplayName)).ToList(); }
}
public void UpdateEmail(string email)
{
Email = UserName = email;
}
public void SetClaim(string type, string value)
{
Claims.RemoveAll(x => string.Equals(x.Type, type, StringComparison.OrdinalIgnoreCase));
Claims.Add(new IdentityUserClaim { Type = type, Value = value });
}
}
}

3
src/Squidex.Domain.Users/UserManagerExtensions.cs

@ -87,7 +87,8 @@ namespace Squidex.Domain.Users
if (!string.IsNullOrWhiteSpace(email)) if (!string.IsNullOrWhiteSpace(email))
{ {
user.UpdateEmail(email); await DoChecked(() => userManager.SetEmailAsync(user, email), "Cannot update email.");
await DoChecked(() => userManager.SetUserNameAsync(user, email), "Cannot update email.");
} }
if (!string.IsNullOrWhiteSpace(displayName)) if (!string.IsNullOrWhiteSpace(displayName))

8
src/Squidex.Infrastructure/CollectionExtensions.cs

@ -128,5 +128,13 @@ namespace Squidex.Infrastructure
return result; return result;
} }
public static void Foreach<T>(this IEnumerable<T> collection, Action<T> action)
{
foreach (var item in collection)
{
action(item);
}
}
} }
} }

3
src/Squidex/Squidex.csproj

@ -8,6 +8,7 @@
<PackageId>Squidex</PackageId> <PackageId>Squidex</PackageId>
<PreserveCompilationContext>true</PreserveCompilationContext> <PreserveCompilationContext>true</PreserveCompilationContext>
<TargetFramework>netcoreapp2.0</TargetFramework> <TargetFramework>netcoreapp2.0</TargetFramework>
<TypeScriptToolsVersion>Latest</TypeScriptToolsVersion>
<TypeScriptCompileBlocked>true</TypeScriptCompileBlocked> <TypeScriptCompileBlocked>true</TypeScriptCompileBlocked>
</PropertyGroup> </PropertyGroup>
@ -68,7 +69,7 @@
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="1.1.2" /> <PackageReference Include="Microsoft.Extensions.Logging.Console" Version="1.1.2" />
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="1.1.2" /> <PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="1.1.2" />
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="1.1.2" /> <PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="1.1.2" />
<PackageReference Include="Microsoft.OData.Core" Version="7.3.1" /> <PackageReference Include="Microsoft.OData.Core" Version="7.2.0" />
<PackageReference Include="MongoDB.Driver" Version="2.4.4" /> <PackageReference Include="MongoDB.Driver" Version="2.4.4" />
<PackageReference Include="NJsonSchema" Version="9.5.0" /> <PackageReference Include="NJsonSchema" Version="9.5.0" />
<PackageReference Include="NodaTime.Serialization.JsonNet" Version="2.0.0" /> <PackageReference Include="NodaTime.Serialization.JsonNet" Version="2.0.0" />

Loading…
Cancel
Save