diff --git a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/IdentityClaimTypeConsts.cs b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/IdentityClaimTypeConsts.cs new file mode 100644 index 0000000000..5581c53638 --- /dev/null +++ b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/IdentityClaimTypeConsts.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Volo.Abp.Identity +{ + public class IdentityClaimTypeConsts + { + public const int MaxNameLength = 128; + + public const int MaxRegexLength = 512; + + public const int MaxRegexDescriptionLength = 128; + + public const int MaxDescriptionLength = 256; + } +} diff --git a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/IdentityClaimValueType.cs b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/IdentityClaimValueType.cs new file mode 100644 index 0000000000..69d40a4607 --- /dev/null +++ b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/IdentityClaimValueType.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Volo.Abp.Identity +{ + public enum IdentityClaimValueType + { + String, + Int, + Boolean, + DateTime + } +} diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IIDentityClaimTypeRepository.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IIDentityClaimTypeRepository.cs new file mode 100644 index 0000000000..bfc62de497 --- /dev/null +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IIDentityClaimTypeRepository.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; +using Volo.Abp.Domain.Repositories; + +namespace Volo.Abp.Identity +{ + public interface IIdentityClaimTypeRepository : IBasicRepository + { + Task DoesNameExist(string name, Guid? claimTypeId = null); + } +} diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdenityClaimTypeManager.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdenityClaimTypeManager.cs new file mode 100644 index 0000000000..a75bb566a7 --- /dev/null +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdenityClaimTypeManager.cs @@ -0,0 +1,51 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; +using Volo.Abp.Domain.Services; +using Volo.Abp.Guids; + +namespace Volo.Abp.Identity +{ + public class IdenityClaimTypeManager : IDomainService + { + private readonly IIdentityClaimTypeRepository _identityClaimTypeRepository; + private readonly IGuidGenerator _guidGenerator; + + public IdenityClaimTypeManager(IIdentityClaimTypeRepository identityClaimTypeRepository, IGuidGenerator guidGenerator) + { + _identityClaimTypeRepository = identityClaimTypeRepository; + _guidGenerator = guidGenerator; + } + + public async Task GetAsync(Guid id) + { + return await _identityClaimTypeRepository.GetAsync(id); + } + + public async Task CreateAsync(IdentityClaimType claimType) + { + if (await _identityClaimTypeRepository.DoesNameExist(claimType.Name)) + { + throw new AbpException($"Name Exist: {claimType.Name}"); + } + + return await _identityClaimTypeRepository.InsertAsync(claimType); + } + + public async Task UpdateAsync(IdentityClaimType claimType) + { + if (await _identityClaimTypeRepository.DoesNameExist(claimType.Name, claimType.Id)) + { + throw new AbpException($"Name Exist: {claimType.Name}"); + } + + return await _identityClaimTypeRepository.UpdateAsync(claimType); + } + + public async Task DeleteAsync(Guid id) + { + await _identityClaimTypeRepository.DeleteAsync(id); + } + } +} diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityClaimType.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityClaimType.cs new file mode 100644 index 0000000000..5755279585 --- /dev/null +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityClaimType.cs @@ -0,0 +1,44 @@ +using System; +using System.Collections.Generic; +using System.Text; +using JetBrains.Annotations; +using Volo.Abp.Domain.Entities; + +namespace Volo.Abp.Identity +{ + public class IdentityClaimType : Entity + { + public virtual string Name { get; protected set; } + + public virtual bool Required { get; protected set; } + + public virtual bool IsStatic { get; protected set; } + + public virtual string Regex { get; protected set; } + + public virtual string RegexDescription { get; protected set; } + + public virtual string Description { get; protected set; } + + public virtual IdentityClaimValueType ValueType { get; protected set; } + + protected IdentityClaimType() + { + } + + public IdentityClaimType(Guid id, [NotNull] string name, bool required, bool isStatic, [CanBeNull]string regex, [CanBeNull]string regexDescription, [CanBeNull] string description, IdentityClaimValueType valueType = IdentityClaimValueType.String) + { + Check.NotNull(name, nameof(name)); + + Name = name; + Required = required; + IsStatic = isStatic; + Regex = regex; + RegexDescription = regexDescription; + Description = description; + ValueType = valueType; + } + + + } +} diff --git a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreIdentityClaimTypeRepository.cs b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreIdentityClaimTypeRepository.cs new file mode 100644 index 0000000000..81cab3ee8c --- /dev/null +++ b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreIdentityClaimTypeRepository.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Internal; +using Volo.Abp.Domain.Repositories.EntityFrameworkCore; +using Volo.Abp.EntityFrameworkCore; + +namespace Volo.Abp.Identity.EntityFrameworkCore +{ + public class EfCoreIdentityClaimTypeRepository : EfCoreRepository, IIdentityClaimTypeRepository + { + public EfCoreIdentityClaimTypeRepository(IDbContextProvider dbContextProvider) : base(dbContextProvider) + { + } + + public async Task DoesNameExist(string name, Guid? claimTypeId = null) + { + return await DbSet.WhereIf(claimTypeId != null, ct => ct.Id == claimTypeId).CountAsync(ct => ct.Name == name) > 0; + } + } +} diff --git a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IIdentityDbContext.cs b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IIdentityDbContext.cs index 5b8503f163..474885e44b 100644 --- a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IIdentityDbContext.cs +++ b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IIdentityDbContext.cs @@ -10,5 +10,7 @@ namespace Volo.Abp.Identity.EntityFrameworkCore DbSet Users { get; set; } DbSet Roles { get; set; } + + DbSet ClaimTypes { get; set; } } } \ No newline at end of file diff --git a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IdentityDbContext.cs b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IdentityDbContext.cs index 15eab5cc08..a9eb5c7648 100644 --- a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IdentityDbContext.cs +++ b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IdentityDbContext.cs @@ -18,6 +18,8 @@ namespace Volo.Abp.Identity.EntityFrameworkCore public DbSet Roles { get; set; } + public DbSet ClaimTypes { get; set; } + public IdentityDbContext(DbContextOptions options) : base(options) { diff --git a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IdentityDbContextModelBuilderExtensions.cs b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IdentityDbContextModelBuilderExtensions.cs index d306b16714..04a0e11047 100644 --- a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IdentityDbContextModelBuilderExtensions.cs +++ b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IdentityDbContextModelBuilderExtensions.cs @@ -112,6 +112,17 @@ namespace Volo.Abp.Identity.EntityFrameworkCore b.HasIndex(uc => uc.RoleId); }); + + builder.Entity(b => + { + b.ToTable(options.TablePrefix + "ClaimTypes", options.Schema); + + b.Property(uc => uc.Name).HasMaxLength(IdentityClaimTypeConsts.MaxNameLength).IsRequired(); // make unique + b.Property(uc => uc.Regex).HasMaxLength(IdentityClaimTypeConsts.MaxRegexLength); + b.Property(uc => uc.RegexDescription).HasMaxLength(IdentityClaimTypeConsts.MaxRegexDescriptionLength); + b.Property(uc => uc.Description).HasMaxLength(IdentityClaimTypeConsts.MaxDescriptionLength); + + }); } } } diff --git a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/AbpIdentityBsonClassMap.cs b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/AbpIdentityBsonClassMap.cs index 8036db7fc8..5d380afde9 100644 --- a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/AbpIdentityBsonClassMap.cs +++ b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/AbpIdentityBsonClassMap.cs @@ -22,6 +22,11 @@ namespace Volo.Abp.Identity.MongoDB { map.AutoMap(); }); + + BsonClassMap.RegisterClassMap(map => + { + map.AutoMap(); + }); }); } } diff --git a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/AbpIdentityMongoDbContext.cs b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/AbpIdentityMongoDbContext.cs index 14e81278bd..f02be5eb9f 100644 --- a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/AbpIdentityMongoDbContext.cs +++ b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/AbpIdentityMongoDbContext.cs @@ -13,6 +13,8 @@ namespace Volo.Abp.Identity.MongoDB public IMongoCollection Roles => Collection(); + public IMongoCollection ClaimTypes => Collection(); + protected override void CreateModel(IMongoModelBuilder modelBuilder) { base.CreateModel(modelBuilder); diff --git a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/AbpIdentityMongoDbContextExtensions.cs b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/AbpIdentityMongoDbContextExtensions.cs index 767ba55fc7..266c100ff6 100644 --- a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/AbpIdentityMongoDbContextExtensions.cs +++ b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/AbpIdentityMongoDbContextExtensions.cs @@ -24,6 +24,11 @@ namespace Volo.Abp.Identity.MongoDB { b.CollectionName = options.CollectionPrefix + "Roles"; }); + + builder.Entity(b => + { + b.CollectionName = options.CollectionPrefix + "ClaimTypes"; + }); } } } \ No newline at end of file diff --git a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/AbpIdentityMongoDbModule.cs b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/AbpIdentityMongoDbModule.cs index d7743a748b..e88fab8a2d 100644 --- a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/AbpIdentityMongoDbModule.cs +++ b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/AbpIdentityMongoDbModule.cs @@ -18,6 +18,7 @@ namespace Volo.Abp.Identity.MongoDB { options.AddRepository(); options.AddRepository(); + options.AddRepository(); }); } } diff --git a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/IAbpIdentityMongoDbContext.cs b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/IAbpIdentityMongoDbContext.cs index cb344e0fc8..ac6420b449 100644 --- a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/IAbpIdentityMongoDbContext.cs +++ b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/IAbpIdentityMongoDbContext.cs @@ -10,5 +10,7 @@ namespace Volo.Abp.Identity.MongoDB IMongoCollection Users { get; } IMongoCollection Roles { get; } + + IMongoCollection ClaimTypes { get; } } } \ No newline at end of file diff --git a/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityClaimTypeRepository.cs b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityClaimTypeRepository.cs new file mode 100644 index 0000000000..3d80cc6520 --- /dev/null +++ b/modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentityClaimTypeRepository.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using MongoDB.Driver.Linq; +using Volo.Abp.Domain.Repositories.MongoDB; +using Volo.Abp.MongoDB; + +namespace Volo.Abp.Identity.MongoDB +{ + public class MongoIdentityClaimTypeRepository : MongoDbRepository, IIdentityClaimTypeRepository + { + public MongoIdentityClaimTypeRepository(IMongoDbContextProvider dbContextProvider) : base(dbContextProvider) + { + } + + public async Task DoesNameExist(string name, Guid? claimTypeId = null) + { + return GetMongoQueryable().WhereIf(claimTypeId != null, ct => ct.Id == claimTypeId).Count(ct => ct.Name == name) > 0; + } + } +} diff --git a/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/AbpIdentityDomainTestBase.cs b/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/AbpIdentityDomainTestBase.cs index 310f6e7107..95dddc2393 100644 --- a/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/AbpIdentityDomainTestBase.cs +++ b/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/AbpIdentityDomainTestBase.cs @@ -4,4 +4,4 @@ { } -} \ No newline at end of file +} diff --git a/modules/identity/test/Volo.Abp.Identity.EntityFrameworkCore.Tests/Volo/Abp/Identity/EntityFrameworkCore/IdentityClaimTypeRepository_Tests.cs b/modules/identity/test/Volo.Abp.Identity.EntityFrameworkCore.Tests/Volo/Abp/Identity/EntityFrameworkCore/IdentityClaimTypeRepository_Tests.cs new file mode 100644 index 0000000000..07f830ba86 --- /dev/null +++ b/modules/identity/test/Volo.Abp.Identity.EntityFrameworkCore.Tests/Volo/Abp/Identity/EntityFrameworkCore/IdentityClaimTypeRepository_Tests.cs @@ -0,0 +1,9 @@ +using Volo.Abp.Identity.EntityFrameworkCore; + +namespace Volo.Abp.Identity.MongoDB +{ + public class IdentityClaimTypeRepository_Tests : IdentityClaimTypeRepository_Tests + { + + } +} diff --git a/modules/identity/test/Volo.Abp.Identity.MongoDB.Tests/Volo/Abp/Identity/MongoDB/IdentityClaimTypeRepository_Tests.cs b/modules/identity/test/Volo.Abp.Identity.MongoDB.Tests/Volo/Abp/Identity/MongoDB/IdentityClaimTypeRepository_Tests.cs new file mode 100644 index 0000000000..b7926aae00 --- /dev/null +++ b/modules/identity/test/Volo.Abp.Identity.MongoDB.Tests/Volo/Abp/Identity/MongoDB/IdentityClaimTypeRepository_Tests.cs @@ -0,0 +1,7 @@ +namespace Volo.Abp.Identity.MongoDB +{ + public class IdentityClaimTypeRepository_Tests : IdentityClaimTypeRepository_Tests + { + + } +} diff --git a/modules/identity/test/Volo.Abp.Identity.TestBase/Volo/Abp/Identity/AbpIdentityTestDataBuilder.cs b/modules/identity/test/Volo.Abp.Identity.TestBase/Volo/Abp/Identity/AbpIdentityTestDataBuilder.cs index 448dfe1c61..ee5fc56fd9 100644 --- a/modules/identity/test/Volo.Abp.Identity.TestBase/Volo/Abp/Identity/AbpIdentityTestDataBuilder.cs +++ b/modules/identity/test/Volo.Abp.Identity.TestBase/Volo/Abp/Identity/AbpIdentityTestDataBuilder.cs @@ -9,6 +9,7 @@ namespace Volo.Abp.Identity { private readonly IGuidGenerator _guidGenerator; private readonly IIdentityUserRepository _userRepository; + private readonly IIdentityClaimTypeRepository _identityClaimTypeRepository; private readonly IIdentityRoleRepository _roleRepository; private readonly ILookupNormalizer _lookupNormalizer; private readonly IdentityTestData _testData; @@ -20,12 +21,14 @@ namespace Volo.Abp.Identity public AbpIdentityTestDataBuilder( IGuidGenerator guidGenerator, IIdentityUserRepository userRepository, + IIdentityClaimTypeRepository identityClaimTypeRepository, IIdentityRoleRepository roleRepository, ILookupNormalizer lookupNormalizer, IdentityTestData testData) { _guidGenerator = guidGenerator; _userRepository = userRepository; + _identityClaimTypeRepository = identityClaimTypeRepository; _roleRepository = roleRepository; _lookupNormalizer = lookupNormalizer; _testData = testData; @@ -35,6 +38,7 @@ namespace Volo.Abp.Identity { AddRoles(); AddUsers(); + AddClaimTypes(); } private void AddRoles() @@ -73,5 +77,13 @@ namespace Volo.Abp.Identity neo.AddClaim(_guidGenerator, new Claim("TestClaimType", "43")); _userRepository.Insert(neo); } + + private void AddClaimTypes() + { + var ageClaim = new IdentityClaimType(_testData.AgeClaimId, "Age", false, false, null, null, null,IdentityClaimValueType.Int); + _identityClaimTypeRepository.Insert(ageClaim); + var educationClaim = new IdentityClaimType(_testData.EducationClaimId, "Education", true, false, null, null, null); + _identityClaimTypeRepository.Insert(educationClaim); + } } } \ No newline at end of file diff --git a/modules/identity/test/Volo.Abp.Identity.TestBase/Volo/Abp/Identity/IdentityClaimTypeRepository_Tests.cs b/modules/identity/test/Volo.Abp.Identity.TestBase/Volo/Abp/Identity/IdentityClaimTypeRepository_Tests.cs new file mode 100644 index 0000000000..56de1d5d5f --- /dev/null +++ b/modules/identity/test/Volo.Abp.Identity.TestBase/Volo/Abp/Identity/IdentityClaimTypeRepository_Tests.cs @@ -0,0 +1,40 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; +using Shouldly; +using Volo.Abp.Guids; +using Volo.Abp.Modularity; +using Xunit; + +namespace Volo.Abp.Identity +{ + public abstract class IdentityClaimTypeRepository_Tests : AbpIdentityTestBase + where TStartupModule : IAbpModule + { + protected IIdentityClaimTypeRepository ClaimTypeRepository { get; } + protected IGuidGenerator GuidGenerator { get; } + + public IdentityClaimTypeRepository_Tests() + { + ClaimTypeRepository = ServiceProvider.GetRequiredService(); + GuidGenerator = ServiceProvider.GetRequiredService(); + } + + [Fact] + public async Task Should_Check_Name_If_It_Is_Uniquee() + { + var claim = (await ClaimTypeRepository.GetListAsync()).FirstOrDefault(); + + var result1 = await ClaimTypeRepository.DoesNameExist(claim.Name); + + result1.ShouldBe(true); + + var result2 = await ClaimTypeRepository.DoesNameExist(Guid.NewGuid().ToString()); + + result2.ShouldBe(false); + } + } +} diff --git a/modules/identity/test/Volo.Abp.Identity.TestBase/Volo/Abp/Identity/IdentityTestData.cs b/modules/identity/test/Volo.Abp.Identity.TestBase/Volo/Abp/Identity/IdentityTestData.cs index b8b99a2453..10fcce89af 100644 --- a/modules/identity/test/Volo.Abp.Identity.TestBase/Volo/Abp/Identity/IdentityTestData.cs +++ b/modules/identity/test/Volo.Abp.Identity.TestBase/Volo/Abp/Identity/IdentityTestData.cs @@ -10,5 +10,7 @@ namespace Volo.Abp.Identity public Guid UserJohnId { get; } = Guid.NewGuid(); public Guid UserDavidId { get; } = Guid.NewGuid(); public Guid UserNeoId { get; } = Guid.NewGuid(); + public Guid AgeClaimId { get; } = Guid.NewGuid(); + public Guid EducationClaimId { get; } = Guid.NewGuid(); } }