Browse Source

Made Identity compiling, but not working yet.

pull/81/head
Halil İbrahim Kalkan 9 years ago
parent
commit
d674af3eaa
  1. 7
      Volo.Abp.sln
  2. 2
      src/AbpDesk/AbpDesk.EntityFrameworkCore/AbpDesk/EntityFrameworkCore/AbpDeskEntityFrameworkCoreModule.cs
  3. 6
      src/Volo.Abp.EntityFrameworkCore/Microsoft/Extensions/DependencyInjection/AbpEfCoreServiceCollectionExtensions.cs
  4. 29
      src/Volo.Abp.EntityFrameworkCore/Volo/Abp/Domain/Repositories/EntityFrameworkCore/EfCoreRepository.cs
  5. 6
      src/Volo.Abp.EntityFrameworkCore/Volo/Abp/Domain/Repositories/EntityFrameworkCore/IEfCoreRepository.cs
  6. 31
      src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs
  7. 6
      src/Volo.Abp.EntityFrameworkCore/Volo/Abp/Uow/EntityFrameworkCore/DbContextDatabaseApi.cs
  8. 23
      src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EfCoreIdentityRoleRepository.cs
  9. 84
      src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EfCoreIdentityUserRepository.cs
  10. 2
      src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/AbpIdentityEntityFrameworkCoreModule.cs
  11. 2
      src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IdentityDbContext.cs
  12. 11
      src/Volo.Abp.Identity/Volo/Abp/Identity/IIdentityRoleRepository.cs
  13. 24
      src/Volo.Abp.Identity/Volo/Abp/Identity/IIdentityUserRepository.cs
  14. 113
      src/Volo.Abp.Identity/Volo/Abp/Identity/IdentityUser.cs
  15. 8
      src/Volo.Abp.Identity/Volo/Abp/Identity/IdentityUserClaim.cs
  16. 19
      src/Volo.Abp.Identity/Volo/Abp/Identity/IdentityUserLogin.cs
  17. 2
      src/Volo.Abp.Identity/Volo/Abp/Identity/IdentityUserManager.cs
  18. 1106
      src/Volo.Abp.Identity/Volo/Abp/Identity/UserStore.cs
  19. 8
      src/Volo.Abp/Volo/Abp/Domain/Entities/IHasConcurrencyStamp.cs
  20. 6
      src/Volo.Abp/Volo/Abp/Domain/Repositories/IQueryableRepository.cs
  21. 11
      src/Volo.Abp/Volo/Abp/Domain/Repositories/IRepository.cs
  22. 6
      src/Volo.Abp/Volo/Abp/Domain/Repositories/QueryableRepositoryBase.cs
  23. 6
      src/Volo.Abp/Volo/Abp/Domain/Repositories/RepositoryBase.cs
  24. 33
      src/Volo.Abp/Volo/Abp/Linq/DefaultAsyncQueryableExecuter.cs
  25. 21
      src/Volo.Abp/Volo/Abp/Linq/IAsyncQueryableExecuter.cs
  26. 5
      src/Volo.Abp/Volo/Abp/Modularity/AbpModuleDescriptor.cs
  27. 36
      src/Volo.Abp/Volo/Abp/Uow/AbpDbConcurrencyException.cs
  28. 6
      src/Volo.Abp/Volo/Abp/Uow/ChildUnitOfWork.cs
  29. 7
      src/Volo.Abp/Volo/Abp/Uow/IDatabaseApi.cs
  30. 3
      src/Volo.Abp/Volo/Abp/Uow/IUnitOfWork.cs
  31. 6
      src/Volo.Abp/Volo/Abp/Uow/IUnitOfWorkManager.cs
  32. 9
      src/Volo.Abp/Volo/Abp/Uow/UnitOfWork.cs
  33. 14
      src/Volo.ExtensionMethods/Volo/ExtensionMethods/Collections/Generic/CollectionExtensions.cs
  34. 3
      test/AbpDesk/AbpDesk.Application.Tests/project.json
  35. 19
      test/Volo.Abp.Identity.Tests/Properties/AssemblyInfo.cs
  36. 23
      test/Volo.Abp.Identity.Tests/Volo.Abp.Identity.Tests.xproj
  37. 31
      test/Volo.Abp.Identity.Tests/Volo/Abp/Identity/AbpIdentityTestModule.cs
  38. 15
      test/Volo.Abp.Identity.Tests/Volo/Abp/Identity/Initialize_Tests.cs
  39. 23
      test/Volo.Abp.Identity.Tests/project.json

7
Volo.Abp.sln

@ -82,6 +82,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Abp.Identity", "Abp.Identit
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Volo.Abp.Identity.EntityFrameworkCore", "src\Volo.Abp.Identity.EntityFrameworkCore\Volo.Abp.Identity.EntityFrameworkCore.xproj", "{439DFC0F-1BA2-464F-900E-EA7E18C08975}"
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Volo.Abp.Identity.Tests", "test\Volo.Abp.Identity.Tests\Volo.Abp.Identity.Tests.xproj", "{4AB91077-82DC-4335-9274-BCE017BD9C8B}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -196,6 +198,10 @@ Global
{439DFC0F-1BA2-464F-900E-EA7E18C08975}.Debug|Any CPU.Build.0 = Debug|Any CPU
{439DFC0F-1BA2-464F-900E-EA7E18C08975}.Release|Any CPU.ActiveCfg = Release|Any CPU
{439DFC0F-1BA2-464F-900E-EA7E18C08975}.Release|Any CPU.Build.0 = Release|Any CPU
{4AB91077-82DC-4335-9274-BCE017BD9C8B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4AB91077-82DC-4335-9274-BCE017BD9C8B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4AB91077-82DC-4335-9274-BCE017BD9C8B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4AB91077-82DC-4335-9274-BCE017BD9C8B}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -236,5 +242,6 @@ Global
{17DBB40A-243E-41F7-A672-FA316ECB1E33} = {1895A5C9-50D4-4568-9A3A-14657E615A5E}
{146F561E-C7B8-4166-9383-47E1BC1A2E62} = {447C8A77-E5F0-4538-8687-7383196D04EA}
{439DFC0F-1BA2-464F-900E-EA7E18C08975} = {1895A5C9-50D4-4568-9A3A-14657E615A5E}
{4AB91077-82DC-4335-9274-BCE017BD9C8B} = {146F561E-C7B8-4166-9383-47E1BC1A2E62}
EndGlobalSection
EndGlobal

2
src/AbpDesk/AbpDesk.EntityFrameworkCore/AbpDesk/EntityFrameworkCore/AbpDeskEntityFrameworkCoreModule.cs

@ -10,7 +10,7 @@ namespace AbpDesk.EntityFrameworkCore
public override void ConfigureServices(IServiceCollection services)
{
services.AddAbpDbContext<AbpDeskDbContext>();
services.AddDefaultEfCoreRepositories<AbpDeskDbContext>(); //TODO: Move this into AddAbpDbContext as an option
services.AddDefaultEfCoreRepositories<AbpDeskDbContext>();
services.AddAssemblyOf<AbpDeskEntityFrameworkCoreModule>();
}

6
src/Volo.Abp.EntityFrameworkCore/Microsoft/Extensions/DependencyInjection/AbpEfCoreServiceCollectionExtensions.cs

@ -6,6 +6,10 @@ using Volo.Abp.EntityFrameworkCore;
namespace Microsoft.Extensions.DependencyInjection
{
//TODO: By default, only create repositories for Aggregate Roots.
//TODO: Move AddDefaultEfCoreRepositories into AddAbpDbContext as optional which will have it's own options
//TODO: Add options to use a provided type as default repository.
public static class AbpEfCoreServiceCollectionExtensions
{
public static IServiceCollection AddAbpDbContext<TDbContext>(
@ -25,8 +29,6 @@ namespace Microsoft.Extensions.DependencyInjection
public static IServiceCollection AddDefaultEfCoreRepositories<TDbContext>(this IServiceCollection services)
where TDbContext : AbpDbContext<TDbContext>
{
//TODO: Add options to use a provided type as default repository.
var dbContextType = typeof(TDbContext);
foreach (var entityType in DbContextHelper.GetEntityTypes(dbContextType))

29
src/Volo.Abp.EntityFrameworkCore/Volo/Abp/Domain/Repositories/EntityFrameworkCore/EfCoreRepository.cs

@ -1,4 +1,5 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
@ -7,6 +8,16 @@ using Volo.Abp.EntityFrameworkCore;
namespace Volo.Abp.Domain.Repositories.EntityFrameworkCore
{
public class EfCoreRepository<TDbContext, TEntity> : EfCoreRepository<TDbContext, TEntity, string>, IEfCoreRepository<TEntity>
where TDbContext : AbpDbContext<TDbContext>
where TEntity : class, IEntity<string>
{
public EfCoreRepository(IDbContextProvider<TDbContext> dbContextProvider)
: base(dbContextProvider)
{
}
}
public class EfCoreRepository<TDbContext, TEntity, TPrimaryKey> : QueryableRepositoryBase<TEntity, TPrimaryKey>, IEfCoreRepository<TEntity, TPrimaryKey>
where TDbContext : AbpDbContext<TDbContext>
where TEntity : class, IEntity<TPrimaryKey>
@ -72,13 +83,25 @@ namespace Volo.Abp.Domain.Repositories.EntityFrameworkCore
public override async Task<TPrimaryKey> InsertAndGetIdAsync(TEntity entity)
{
var insertedEntity = await InsertAsync(entity);
await DbContext.SaveChangesAsync();
await DbContext.SaveChangesAsync(true);
return insertedEntity.Id;
}
public override TEntity Update(TEntity entity)
{
return DbSet.Update(entity).Entity;
//TODO: This code is got from UserStore.UpdateAsync and revised Update method based on that, but we should be sure that it's valid
//Context.Attach(user);
//user.ConcurrencyStamp = Guid.NewGuid().ToString();
//Context.Update(user);
DbContext.Attach(entity); //TODO: What is different for DbSet.Attach(entity)?
if (entity is IHasConcurrencyStamp)
{
(entity as IHasConcurrencyStamp).ConcurrencyStamp = Guid.NewGuid().ToString(); //TODO: Use IGuidGenerator!
}
return DbContext.Update(entity).Entity; //TODO: or DbSet.Update(entity) ?
}
public override void Delete(TEntity entity)

6
src/Volo.Abp.EntityFrameworkCore/Volo/Abp/Domain/Repositories/EntityFrameworkCore/IEfCoreRepository.cs

@ -3,6 +3,12 @@ using Volo.Abp.Domain.Entities;
namespace Volo.Abp.Domain.Repositories.EntityFrameworkCore
{
public interface IEfCoreRepository<TEntity> : IEfCoreRepository<TEntity, string>, IQueryableRepository<TEntity>
where TEntity : class, IEntity<string>
{
}
public interface IEfCoreRepository<TEntity, TPrimaryKey> : IQueryableRepository<TEntity, TPrimaryKey>
where TEntity : class, IEntity<TPrimaryKey>
{

31
src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/AbpDbContext.cs

@ -1,4 +1,7 @@
using Microsoft.EntityFrameworkCore;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Volo.Abp.Uow;
namespace Volo.Abp.EntityFrameworkCore
{
@ -10,5 +13,31 @@ namespace Volo.Abp.EntityFrameworkCore
{
}
public override int SaveChanges(bool acceptAllChangesOnSuccess)
{
try
{
return base.SaveChanges(acceptAllChangesOnSuccess);
}
catch (DbUpdateConcurrencyException ex)
{
//TODO: Better exception message using DbUpdateConcurrencyException
throw new AbpDbConcurrencyException(ex.Message, ex);
}
}
public override async Task<int> SaveChangesAsync(bool acceptAllChangesOnSuccess, CancellationToken cancellationToken = default(CancellationToken))
{
try
{
return await base.SaveChangesAsync(acceptAllChangesOnSuccess, cancellationToken);
}
catch (DbUpdateConcurrencyException ex)
{
//TODO: Better exception message using DbUpdateConcurrencyException
throw new AbpDbConcurrencyException(ex.Message, ex);
}
}
}
}

6
src/Volo.Abp.EntityFrameworkCore/Volo/Abp/Uow/EntityFrameworkCore/DbContextDatabaseApi.cs

@ -1,3 +1,4 @@
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.EntityFrameworkCore;
@ -18,6 +19,11 @@ namespace Volo.Abp.Uow.EntityFrameworkCore
return DbContext.SaveChangesAsync();
}
public Task SaveChangesAsync(CancellationToken cancellationToken)
{
return DbContext.SaveChangesAsync(cancellationToken);
}
public Task CommitAsync()
{
return DbContext.SaveChangesAsync();

23
src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EfCoreIdentityRoleRepository.cs

@ -0,0 +1,23 @@
using System.Threading;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Volo.Abp.Domain.Repositories.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore;
using Volo.Abp.Identity.EntityFrameworkCore;
namespace Volo.Abp.Identity
{
//TODO: Register for all repositories!
public class EfCoreIdentityRoleRepository : EfCoreRepository<IdentityDbContext, IdentityRole>, IIdentityRoleRepository
{
public EfCoreIdentityRoleRepository(IDbContextProvider<IdentityDbContext> dbContextProvider)
: base(dbContextProvider)
{
}
public Task<IdentityRole> FindByNormalizedNameAsync(string normalizedRoleName, CancellationToken cancellationToken)
{
return DbSet.FirstOrDefaultAsync(r => r.NormalizedName == normalizedRoleName, cancellationToken);
}
}
}

84
src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EfCoreIdentityUserRepository.cs

@ -0,0 +1,84 @@
using System.Collections.Generic;
using System.Threading;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Volo.Abp.Domain.Repositories.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore;
using Volo.Abp.Identity.EntityFrameworkCore;
namespace Volo.Abp.Identity
{
//TODO: Register for;
//- IIdentityUserRepository
//- IRepository<IdentityUser>
//- IRepository<IdentityUser, string>
//- IQueryableRepository<IdentityUser>
//- IQueryableRepository<IdentityUser, string>
public class EfCoreIdentityUserRepository : EfCoreRepository<IdentityDbContext, IdentityUser>, IIdentityUserRepository
{
public EfCoreIdentityUserRepository(IDbContextProvider<IdentityDbContext> dbContextProvider)
: base(dbContextProvider)
{
}
public Task<IdentityUser> FindByNormalizedUserNameAsync(string normalizedUserName, CancellationToken cancellationToken)
{
return DbSet.FirstOrDefaultAsync(u => u.NormalizedUserName == normalizedUserName, cancellationToken);
}
public Task<List<string>> GetRoleNamesAsync(string userId)
{
var query = from userRole in DbContext.UserRoles
join role in DbContext.Roles on userRole.RoleId equals role.Id
where userRole.UserId.Equals(userId)
select role.Name;
return query.ToListAsync();
}
public async Task<IdentityUser> FindByLoginAsync(string loginProvider, string providerKey, CancellationToken cancellationToken)
{
var userLogin = await DbContext.UserLogins.FindAsync(new object[] { loginProvider, providerKey }, cancellationToken);
if (userLogin == null)
{
return null;
}
return await DbSet.FindAsync(new object[] { userLogin.UserId }, cancellationToken);
}
public Task<IdentityUser> FindByNormalizedEmailAsync(string normalizedEmail, CancellationToken cancellationToken)
{
return DbSet.FirstOrDefaultAsync(u => u.NormalizedEmail == normalizedEmail, cancellationToken);
}
public async Task<IList<IdentityUser>> GetListByClaimAsync(Claim claim, CancellationToken cancellationToken)
{
var query = from userclaims in DbContext.UserClaims
join user in DbContext.Users on userclaims.UserId equals user.Id
where userclaims.ClaimValue == claim.Value && userclaims.ClaimType == claim.Type
select user;
return await query.ToListAsync(cancellationToken);
}
public async Task<IList<IdentityUser>> GetListByNormalizedRoleNameAsync(string normalizedRoleName, CancellationToken cancellationToken)
{
var role = await DbContext.Roles.Where(x => x.NormalizedName == normalizedRoleName).FirstOrDefaultAsync(cancellationToken);
if (role == null)
{
return new List<IdentityUser>();
}
var query = from userrole in DbContext.UserRoles
join user in DbContext.Users on userrole.UserId equals user.Id
where userrole.RoleId.Equals(role.Id)
select user;
return await query.ToListAsync(cancellationToken);
}
}
}

2
src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/AbpIdentityEntityFrameworkCoreModule.cs

@ -10,7 +10,7 @@ namespace Volo.Abp.Identity.EntityFrameworkCore
public override void ConfigureServices(IServiceCollection services)
{
services.AddAbpDbContext<IdentityDbContext>();
services.AddDefaultEfCoreRepositories<IdentityDbContext>(); //TODO: Move this into AddAbpDbContext as optional which will have it's own options
services.AddDefaultEfCoreRepositories<IdentityDbContext>();
services.AddAssemblyOf<AbpIdentityEntityFrameworkCoreModule>();
}
}

2
src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IdentityDbContext.cs

@ -17,7 +17,7 @@ namespace Volo.Abp.Identity.EntityFrameworkCore
{
}
/// <summary>
/// Gets or sets the <see cref="DbSet{TEntity}"/> of Users.
/// </summary>

11
src/Volo.Abp.Identity/Volo/Abp/Identity/IIdentityRoleRepository.cs

@ -0,0 +1,11 @@
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.Domain.Repositories;
namespace Volo.Abp.Identity
{
public interface IIdentityRoleRepository : IRepository<IdentityRole>
{
Task<IdentityRole> FindByNormalizedNameAsync(string normalizedRoleName, CancellationToken cancellationToken);
}
}

24
src/Volo.Abp.Identity/Volo/Abp/Identity/IIdentityUserRepository.cs

@ -0,0 +1,24 @@
using System.Collections.Generic;
using System.Security.Claims;
using System.Threading;
using System.Threading.Tasks;
using JetBrains.Annotations;
using Volo.Abp.Domain.Repositories;
namespace Volo.Abp.Identity
{
public interface IIdentityUserRepository : IRepository<IdentityUser>
{
Task<IdentityUser> FindByNormalizedUserNameAsync([NotNull] string normalizedUserName, CancellationToken cancellationToken);
Task<List<string>> GetRoleNamesAsync([NotNull] string userId);
Task<IdentityUser> FindByLoginAsync([NotNull] string loginProvider, [NotNull] string providerKey, CancellationToken cancellationToken);
Task<IdentityUser> FindByNormalizedEmailAsync([NotNull] string normalizedEmail, CancellationToken cancellationToken);
Task<IList<IdentityUser>> GetListByClaimAsync(Claim claim, CancellationToken cancellationToken);
Task<IList<IdentityUser>> GetListByNormalizedRoleNameAsync(string normalizedRoleName, CancellationToken cancellationToken);
}
}

113
src/Volo.Abp.Identity/Volo/Abp/Identity/IdentityUser.cs

@ -1,15 +1,21 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Security.Claims;
using System.Threading;
using JetBrains.Annotations;
using Microsoft.AspNetCore.Identity;
using Volo.Abp.Domain.Entities;
using Volo.ExtensionMethods.Collections.Generic;
namespace Volo.Abp.Identity
{
//TODO: Should set Id to a GUID (where? on repository?)
//TODO: Properties should not be public!
//TODO: Add Name/Surname/FullName?
public class IdentityUser : AggregateRoot
public class IdentityUser : AggregateRoot, IHasConcurrencyStamp
{
/// <summary>
/// Gets or sets the user name for this user.
@ -88,6 +94,8 @@ namespace Volo.Abp.Identity
/// </summary>
public virtual int AccessFailedCount { get; set; }
//TODO: Can we make collections readonly collection, which will provide encapsulation but can work for all ORMs?
/// <summary>
/// Navigation property for the roles this user belongs to.
/// </summary>
@ -120,6 +128,109 @@ namespace Volo.Abp.Identity
UserName = userName;
}
public void AddRole([NotNull] string roleId)
{
Check.NotNull(roleId, nameof(roleId));
if (Roles.Any(r => r.RoleId == roleId))
{
return;
}
Roles.Add(new IdentityUserRole(Id, roleId));
}
public void RemoveRole([NotNull] string roleId)
{
Check.NotNull(roleId, nameof(roleId));
if (Roles.All(r => r.RoleId != roleId))
{
return;
}
Roles.Add(new IdentityUserRole(Id, roleId));
}
public bool IsInRole([NotNull] string roleId)
{
Check.NotNull(roleId, nameof(roleId));
return Roles.Any(r => r.RoleId == roleId);
}
public void AddClaims([NotNull] IEnumerable<Claim> claims)
{
Check.NotNull(claims, nameof(claims));
foreach (var claim in claims)
{
Claims.Add(new IdentityUserClaim(Id, claim));
}
}
public void ReplaceClaim([NotNull] Claim claim, [NotNull] Claim newClaim)
{
Check.NotNull(claim, nameof(claim));
Check.NotNull(newClaim, nameof(newClaim));
var userClaims = Claims.Where(uc => uc.ClaimValue == claim.Value && uc.ClaimType == claim.Type);
foreach (var userClaim in userClaims)
{
userClaim.SetClaim(newClaim);
}
}
public void RemoveClaims([NotNull] IEnumerable<Claim> claims)
{
Check.NotNull(claims, nameof(claims));
foreach (var claim in claims)
{
Claims.RemoveAll(uc => uc.ClaimValue == claim.Value && uc.ClaimType == claim.Type);
}
}
public void AddLogin([NotNull] UserLoginInfo login)
{
Check.NotNull(login, nameof(login));
Logins.Add(new IdentityUserLogin(Id, login));
}
public void RemoveLogin([NotNull] string loginProvider, [NotNull] string providerKey)
{
Check.NotNull(loginProvider, nameof(loginProvider));
Check.NotNull(providerKey, nameof(providerKey));
Logins.RemoveAll(userLogin => userLogin.LoginProvider == loginProvider && userLogin.ProviderKey == providerKey);
}
[CanBeNull]
public IdentityUserToken FindToken(string loginProvider, string name)
{
return Tokens.FirstOrDefault(t => t.LoginProvider == loginProvider && t.Name == name);
}
public void SetToken(string loginProvider, string name, string value)
{
var token = FindToken(loginProvider, name);
if (token == null)
{
Tokens.Add(new IdentityUserToken(Id, loginProvider, name, value));
}
else
{
token.Value = value;
}
}
public void RemoveToken(string loginProvider, string name)
{
Tokens.RemoveAll(t => t.LoginProvider == loginProvider && t.Name == name);
}
/// <summary>
/// Returns the username for this user.
/// </summary>

8
src/Volo.Abp.Identity/Volo/Abp/Identity/IdentityUserClaim.cs

@ -57,5 +57,13 @@ namespace Volo.Abp.Identity
{
return new Claim(ClaimType, ClaimValue);
}
public void SetClaim([NotNull] Claim claim)
{
Check.NotNull(claim, nameof(claim));
ClaimType = claim.Type;
ClaimValue = claim.Value;
}
}
}

19
src/Volo.Abp.Identity/Volo/Abp/Identity/IdentityUserLogin.cs

@ -1,8 +1,11 @@
using JetBrains.Annotations;
using Microsoft.AspNetCore.Identity;
using Volo.Abp.Domain.Entities;
namespace Volo.Abp.Identity
{
//TODO: Make constructors internal to ensure that it's called by only from IdentityUser?
/// <summary>
/// Represents a login and its associated provider for a user.
/// </summary>
@ -44,5 +47,21 @@ namespace Volo.Abp.Identity
ProviderKey = providerKey;
ProviderDisplayName = providerDisplayName;
}
public IdentityUserLogin(string userId, UserLoginInfo login)
{
Check.NotNull(userId, nameof(userId));
Check.NotNull(login, nameof(login));
UserId = userId;
LoginProvider = login.LoginProvider;
ProviderKey = login.ProviderKey;
ProviderDisplayName = login.ProviderDisplayName;
}
public UserLoginInfo ToUserLoginInfo()
{
return new UserLoginInfo(LoginProvider, ProviderKey, ProviderDisplayName);
}
}
}

2
src/Volo.Abp.Identity/Volo/Abp/Identity/IdentityUserManager.cs

@ -11,7 +11,7 @@ namespace Volo.Abp.Identity
public class IdentityUserManager : UserManager<IdentityUser>, IDomainService
{
public IdentityUserManager(
IUserStore<IdentityUser> store,
UserStore store,
IOptions<IdentityOptions> optionsAccessor,
IPasswordHasher<IdentityUser> passwordHasher,
IEnumerable<IUserValidator<IdentityUser>> userValidators,

1106
src/Volo.Abp.Identity/Volo/Abp/Identity/UserStore.cs

File diff suppressed because it is too large

8
src/Volo.Abp/Volo/Abp/Domain/Entities/IHasConcurrencyStamp.cs

@ -0,0 +1,8 @@
namespace Volo.Abp.Domain.Entities
{
//TODO: Think a better naming?
public interface IHasConcurrencyStamp
{
string ConcurrencyStamp { get; set; }
}
}

6
src/Volo.Abp/Volo/Abp/Domain/Repositories/IQueryableRepository.cs

@ -7,6 +7,12 @@ using Volo.Abp.Domain.Entities;
namespace Volo.Abp.Domain.Repositories
{
public interface IQueryableRepository<TEntity> : IQueryableRepository<TEntity, string>
where TEntity : class, IEntity<string>
{
}
public interface IQueryableRepository<TEntity, TPrimaryKey> : IRepository<TEntity, TPrimaryKey>, IQueryable<TEntity>
where TEntity : class, IEntity<TPrimaryKey>
{

11
src/Volo.Abp/Volo/Abp/Domain/Repositories/IRepository.cs

@ -11,6 +11,15 @@ namespace Volo.Abp.Domain.Repositories
}
public interface IRepository<TEntity> : IRepository<TEntity, string>
where TEntity : class, IEntity<string>
{
}
//TODO: Add overloads with cancellationToken to appropriate methods?
//TODO: Add overloads for Find/Get/Delete to get multiple PK?
public interface IRepository<TEntity, TPrimaryKey> : IRepository
where TEntity : class, IEntity<TPrimaryKey>
{
@ -30,6 +39,7 @@ namespace Volo.Abp.Domain.Repositories
/// <summary>
/// Gets an entity with given primary key.
/// Throws <see cref="EntityNotFoundException"/> if can not find an entity with given id.
/// </summary>
/// <param name="id">Primary key of the entity to get</param>
/// <returns>Entity</returns>
@ -38,6 +48,7 @@ namespace Volo.Abp.Domain.Repositories
/// <summary>
/// Gets an entity with given primary key.
/// Throws <see cref="EntityNotFoundException"/> if can not find an entity with given id.
/// </summary>
/// <param name="id">Primary key of the entity to get</param>
/// <returns>Entity</returns>

6
src/Volo.Abp/Volo/Abp/Domain/Repositories/QueryableRepositoryBase.cs

@ -8,6 +8,12 @@ using Volo.Abp.Domain.Entities;
namespace Volo.Abp.Domain.Repositories
{
public abstract class QueryableRepositoryBase<TEntity> : QueryableRepositoryBase<TEntity, string>, IQueryableRepository<TEntity>
where TEntity : class, IEntity<string>
{
}
public abstract class QueryableRepositoryBase<TEntity, TPrimaryKey> : RepositoryBase<TEntity, TPrimaryKey>, IQueryableRepository<TEntity, TPrimaryKey>
where TEntity : class, IEntity<TPrimaryKey>
{

6
src/Volo.Abp/Volo/Abp/Domain/Repositories/RepositoryBase.cs

@ -6,6 +6,12 @@ using Volo.Abp.Domain.Entities;
namespace Volo.Abp.Domain.Repositories
{
public abstract class RepositoryBase<TEntity> : RepositoryBase<TEntity, string>, IRepository<TEntity>
where TEntity : class, IEntity<string>
{
}
public abstract class RepositoryBase<TEntity, TPrimaryKey> : IRepository<TEntity, TPrimaryKey>
where TEntity : class, IEntity<TPrimaryKey>
{

33
src/Volo.Abp/Volo/Abp/Linq/DefaultAsyncQueryableExecuter.cs

@ -0,0 +1,33 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Volo.DependencyInjection;
namespace Volo.Abp.Linq
{
//TODO: DefaultAsyncQueryableExecuter should be able to work with multiple Executer, each will try to execute it!
//TODO: Implement with EF Core as first executer implementation!
public class DefaultAsyncQueryableExecuter : IAsyncQueryableExecuter, ITransientDependency
{
public Task<int> CountAsync<T>(IQueryable<T> queryable)
{
return Task.FromResult(queryable.Count());
}
public Task<List<T>> ToListAsync<T>(IQueryable<T> queryable)
{
return Task.FromResult(queryable.ToList());
}
public Task<T> FirstOrDefaultAsync<T>(IQueryable<T> queryable)
{
return Task.FromResult(queryable.FirstOrDefault());
}
public Task<T> FirstOrDefaultAsync<T>(IQueryable<T> queryable, CancellationToken cancellationToken)
{
return Task.FromResult(queryable.FirstOrDefault());
}
}
}

21
src/Volo.Abp/Volo/Abp/Linq/IAsyncQueryableExecuter.cs

@ -0,0 +1,21 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace Volo.Abp.Linq
{
/// <summary>
/// This interface is intended to be used by ABP.
/// </summary>
public interface IAsyncQueryableExecuter
{
Task<int> CountAsync<T>(IQueryable<T> queryable);
Task<List<T>> ToListAsync<T>(IQueryable<T> queryable);
Task<T> FirstOrDefaultAsync<T>(IQueryable<T> queryable);
Task<T> FirstOrDefaultAsync<T>(IQueryable<T> queryable, CancellationToken cancellationToken);
}
}

5
src/Volo.Abp/Volo/Abp/Modularity/AbpModuleDescriptor.cs

@ -28,5 +28,10 @@ namespace Volo.Abp.Modularity
Dependencies = new List<AbpModuleDescriptor>();
}
public override string ToString()
{
return $"[AbpModuleDescriptor {Type.FullName}]";
}
}
}

36
src/Volo.Abp/Volo/Abp/Uow/AbpDbConcurrencyException.cs

@ -0,0 +1,36 @@
using System;
namespace Volo.Abp.Uow
{
public class AbpDbConcurrencyException : AbpException
{
/// <summary>
/// Creates a new <see cref="AbpDbConcurrencyException"/> object.
/// </summary>
public AbpDbConcurrencyException()
{
}
/// <summary>
/// Creates a new <see cref="AbpDbConcurrencyException"/> object.
/// </summary>
/// <param name="message">Exception message</param>
public AbpDbConcurrencyException(string message)
: base(message)
{
}
/// <summary>
/// Creates a new <see cref="AbpDbConcurrencyException"/> object.
/// </summary>
/// <param name="message">Exception message</param>
/// <param name="innerException">Inner exception</param>
public AbpDbConcurrencyException(string message, Exception innerException)
: base(message, innerException)
{
}
}
}

6
src/Volo.Abp/Volo/Abp/Uow/ChildUnitOfWork.cs

@ -1,4 +1,5 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using JetBrains.Annotations;
@ -22,6 +23,11 @@ namespace Volo.Abp.Uow
return _parent.SaveChangesAsync();
}
public Task SaveChangesAsync(CancellationToken cancellationToken)
{
return _parent.SaveChangesAsync(cancellationToken);
}
public Task CompleteAsync()
{
return Task.CompletedTask;

7
src/Volo.Abp/Volo/Abp/Uow/IDatabaseApi.cs

@ -1,4 +1,5 @@
using System.Threading.Tasks;
using System.Threading;
using System.Threading.Tasks;
namespace Volo.Abp.Uow
{
@ -6,6 +7,8 @@ namespace Volo.Abp.Uow
{
Task SaveChangesAsync();
Task CommitAsync();
Task SaveChangesAsync(CancellationToken cancellationToken);
Task CommitAsync(); //TODO: Add CancellationToken to CommitAsync?
}
}

3
src/Volo.Abp/Volo/Abp/Uow/IUnitOfWork.cs

@ -1,4 +1,5 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using JetBrains.Annotations;
using Volo.Abp.DependencyInjection;
@ -18,6 +19,8 @@ namespace Volo.Abp.Uow
Task SaveChangesAsync();
Task SaveChangesAsync(CancellationToken cancellationToken);
Task CompleteAsync();
}
}

6
src/Volo.Abp/Volo/Abp/Uow/IUnitOfWorkManager.cs

@ -1,9 +1,13 @@
namespace Volo.Abp.Uow
using JetBrains.Annotations;
namespace Volo.Abp.Uow
{
public interface IUnitOfWorkManager
{
[CanBeNull]
IUnitOfWork Current { get; }
[NotNull]
IUnitOfWork Begin();
}
}

9
src/Volo.Abp/Volo/Abp/Uow/UnitOfWork.cs

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Volo.ExtensionMethods.Collections.Generic;
@ -31,6 +32,14 @@ namespace Volo.Abp.Uow
}
}
public async Task SaveChangesAsync(CancellationToken cancellationToken)
{
foreach (var databaseApi in _databaseApis.Values)
{
await databaseApi.SaveChangesAsync(cancellationToken);
}
}
public async Task CompleteAsync()
{
foreach (var databaseApi in _databaseApis.Values)

14
src/Volo.ExtensionMethods/Volo/ExtensionMethods/Collections/Generic/CollectionExtensions.cs

@ -1,4 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using JetBrains.Annotations;
namespace Volo.ExtensionMethods.Collections.Generic
@ -35,5 +37,17 @@ namespace Volo.ExtensionMethods.Collections.Generic
source.Add(item);
return true;
}
public static IList<T> RemoveAll<T>([NotNull] this ICollection<T> source, Func<T, bool> predicate)
{
var items = source.Where(predicate).ToList();
foreach (var item in items)
{
source.Remove(item);
}
return items;
}
}
}

3
test/AbpDesk/AbpDesk.Application.Tests/project.json

@ -7,8 +7,7 @@
"AbpDesk.Application": "1.0.0-*",
"AbpDesk.EntityFrameworkCore": "1.0.0-*",
"AbpTestBase": "1.0.0-*",
"Microsoft.EntityFrameworkCore.InMemory": "1.1.0",
"Volo.Abp.TestBase": "1.0.0-*"
"Microsoft.EntityFrameworkCore.InMemory": "1.1.0"
},
"frameworks": {

19
test/Volo.Abp.Identity.Tests/Properties/AssemblyInfo.cs

@ -0,0 +1,19 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Volo.Abp.Identity.Tests")]
[assembly: AssemblyTrademark("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("4ab91077-82dc-4335-9274-bce017bd9c8b")]

23
test/Volo.Abp.Identity.Tests/Volo.Abp.Identity.Tests.xproj

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.Props" Condition="'$(VSToolsPath)' != ''" />
<PropertyGroup Label="Globals">
<ProjectGuid>4ab91077-82dc-4335-9274-bce017bd9c8b</ProjectGuid>
<RootNamespace>
</RootNamespace>
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">.\obj</BaseIntermediateOutputPath>
<OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup>
<SchemaVersion>2.0</SchemaVersion>
</PropertyGroup>
<ItemGroup>
<Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
</ItemGroup>
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.targets" Condition="'$(VSToolsPath)' != ''" />
</Project>

31
test/Volo.Abp.Identity.Tests/Volo/Abp/Identity/AbpIdentityTestModule.cs

@ -0,0 +1,31 @@
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Data;
using Volo.Abp.EntityFrameworkCore;
using Volo.Abp.Modularity;
namespace Volo.Abp.Identity
{
[DependsOn(typeof(AbpIdentityModule))]
public class AbpIdentityTestModule : AbpModule
{
public override void ConfigureServices(IServiceCollection services)
{
services.AddEntityFrameworkInMemoryDatabase();
services.Configure<DbConnectionOptions>(options =>
{
options.ConnectionStrings.Default = Guid.NewGuid().ToString();
});
services.Configure<AbpDbContextOptions>(options =>
{
options.Configure(context =>
{
context.DbContextOptions.UseInMemoryDatabase(context.ConnectionString);
});
});
}
}
}

15
test/Volo.Abp.Identity.Tests/Volo/Abp/Identity/Initialize_Tests.cs

@ -0,0 +1,15 @@
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.TestBase;
using Xunit;
namespace Volo.Abp.Identity
{
public class Initialize_Tests : AbpIntegratedTest<AbpIdentityTestModule>
{
[Fact]
public void Should_Initialize_Identity_Module()
{
var userManager = ServiceProvider.GetRequiredService<IdentityUserManager>();
}
}
}

23
test/Volo.Abp.Identity.Tests/project.json

@ -0,0 +1,23 @@
{
"version": "1.0.0-*",
"testRunner": "xunit",
"dependencies": {
"AbpTestBase": "1.0.0-*",
"Microsoft.EntityFrameworkCore.InMemory": "1.1.0",
"Volo.Abp.Identity": "1.0.0-*",
"Volo.Abp.Identity.EntityFrameworkCore": "1.0.0-*"
},
"frameworks": {
"netcoreapp1.1": {
"dependencies": {
"Microsoft.NETCore.App": {
"type": "platform",
"version": "1.1.0"
}
}
}
}
}
Loading…
Cancel
Save