diff --git a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/en.json b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/en.json
index e7a038fd57..87c599ea4f 100644
--- a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/en.json
+++ b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/en.json
@@ -63,6 +63,7 @@
"Identity.PasswordConfirmationFailed": "Password does not match the confirm password.",
"Identity.StaticRoleRenamingErrorMessage": "Static roles can not be renamed.",
"Identity.StaticRoleDeletionErrorMessage": "Static roles can not be deleted.",
+ "Identity.OrganizationUnit.DuplicateDisplayNameWarning": "There is already an organization unit with name {0}. Two units with same name can not be created in same level.",
"Volo.Abp.Identity:010001": "You can not delete your own account!",
"Permission:IdentityManagement": "Identity management",
"Permission:RoleManagement": "Role management",
diff --git a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/pt-BR.json b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/pt-BR.json
index 4df719fffe..1dda38b2a5 100644
--- a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/pt-BR.json
+++ b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/pt-BR.json
@@ -63,6 +63,7 @@
"Identity.PasswordConfirmationFailed": "A senha não confere com a confirmação de senha.",
"Identity.StaticRoleRenamingErrorMessage": "Perfis estáticos não podem ser renomeados.",
"Identity.StaticRoleDeletionErrorMessage": "Perfis estáticos não podem ser excluídos.",
+ "Identity.OrganizationUnit.DuplicateDisplayNameWarning": "Já existe uma unidade organizacional com o nome {0}. Duas unidades com o mesmo nome não pode ser criada no mesmo nível.",
"Volo.Abp.Identity:010001": "Você não pode deletar sua própria conta!",
"Permission:IdentityManagement": "Acessos",
"Permission:RoleManagement": "Perfis",
diff --git a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/tr.json b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/tr.json
index 8b8b936c0a..cfc58d4dad 100644
--- a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/tr.json
+++ b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/tr.json
@@ -63,6 +63,7 @@
"Identity.UserNameNotFound": "{0} kullanıcısı bulunamadı.",
"Identity.UserNotInRole": "Kullanıcı '{0}' rolünde değil.",
"Identity.PasswordConfirmationFailed": "Yeni şifre ile onay şifresi uyuşmuyor.",
+ "Identity.OrganizationUnit.DuplicateDisplayNameWarning": "{0} isminde bir birim zaten var. Aynı seviyede aynı isimli iki birim olamaz.",
"Volo.Abp.Identity:010001": "Kendi hesabınızı silemezsiniz!",
"Permission:IdentityManagement": "Kimlik yönetimi",
"Permission:RoleManagement": "Rol yönetimi",
diff --git a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/zh-Hans.json b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/zh-Hans.json
index f57029eb9e..b80c820f98 100644
--- a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/zh-Hans.json
+++ b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Localization/zh-Hans.json
@@ -63,6 +63,7 @@
"Identity.PasswordConfirmationFailed": "密码或确认密码不一致.",
"Identity.StaticRoleRenamingErrorMessage": "无法重命名静态角色.",
"Identity.StaticRoleDeletionErrorMessage": "无法删除静态角色.",
+ "Identity.OrganizationUnit.DuplicateDisplayNameWarning": "已存在名为 {0} 的组织单位. 无法在同一级别创建相同名称的组织单位.",
"Volo.Abp.Identity:010001": "您无法删除自己的帐户!",
"Permission:IdentityManagement": "身份标识管理",
"Permission:RoleManagement": "角色管理",
diff --git a/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Organizations/OrganizationUnitConsts.cs b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Organizations/OrganizationUnitConsts.cs
new file mode 100644
index 0000000000..a704e6bb05
--- /dev/null
+++ b/modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/Organizations/OrganizationUnitConsts.cs
@@ -0,0 +1,25 @@
+namespace Volo.Abp.Identity.Organizations
+{
+ public class OrganizationUnitConsts
+ {
+ ///
+ /// Maximum length of the property.
+ ///
+ public const int MaxDisplayNameLength = 128;
+
+ ///
+ /// Maximum depth of an OU hierarchy.
+ ///
+ public const int MaxDepth = 16;
+
+ ///
+ /// Length of a code unit between dots.
+ ///
+ public const int CodeUnitLength = 5;
+
+ ///
+ /// Maximum length of the property.
+ ///
+ public const int MaxCodeLength = MaxDepth * (CodeUnitLength + 1) - 1;
+ }
+}
diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/IOrganizationUnitRepository.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/IOrganizationUnitRepository.cs
new file mode 100644
index 0000000000..0136d9ef4c
--- /dev/null
+++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/IOrganizationUnitRepository.cs
@@ -0,0 +1,14 @@
+using System;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using Volo.Abp.Domain.Repositories;
+
+namespace Volo.Abp.Identity.Organizations
+{
+ public interface IOrganizationUnitRepository : IBasicRepository
+ {
+ Task> GetChildrenAsync(Guid? parentId);
+
+ Task> GetAllChildrenWithParentCodeAsync(string code, Guid? parentId);
+ }
+}
diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/OrganizationUnit.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/OrganizationUnit.cs
new file mode 100644
index 0000000000..0955aa248a
--- /dev/null
+++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/OrganizationUnit.cs
@@ -0,0 +1,178 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Volo.Abp.Domain.Entities.Auditing;
+using Volo.Abp.MultiTenancy;
+
+namespace Volo.Abp.Identity.Organizations
+{
+ ///
+ /// Represents an organization unit (OU).
+ ///
+ public class OrganizationUnit : FullAuditedAggregateRoot, IMultiTenant
+ {
+ public virtual Guid? TenantId { get; protected set; }
+
+ ///
+ /// Parent Id.
+ /// Null, if this OU is root.
+ ///
+ public virtual Guid? ParentId { get; set; }
+
+ ///
+ /// Hierarchical Code of this organization unit.
+ /// Example: "00001.00042.00005".
+ /// This is a unique code for a Tenant.
+ /// It's changeable if OU hierarch is changed.
+ ///
+ public virtual string Code { get; set; }
+
+ ///
+ /// Display name of this role.
+ ///
+ public virtual string DisplayName { get; set; }
+
+ ///
+ /// Children of this OU.
+ ///
+ public virtual ICollection Children { get; set; }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public OrganizationUnit()
+ {
+
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// Tenant's Id or null for host.
+ /// Display name.
+ /// Parent's Id or null if OU is a root.
+ public OrganizationUnit(Guid? tenantId, string displayName, Guid? parentId = null)
+ {
+ TenantId = tenantId;
+ DisplayName = displayName;
+ ParentId = parentId;
+ }
+
+ ///
+ /// Creates code for given numbers.
+ /// Example: if numbers are 4,2 then returns "00004.00002";
+ ///
+ /// Numbers
+ public static string CreateCode(params int[] numbers)
+ {
+ if (numbers.IsNullOrEmpty())
+ {
+ return null;
+ }
+
+ return numbers.Select(number => number.ToString(new string('0', OrganizationUnitConsts.CodeUnitLength))).JoinAsString(".");
+ }
+
+ ///
+ /// Appends a child code to a parent code.
+ /// Example: if parentCode = "00001", childCode = "00042" then returns "00001.00042".
+ ///
+ /// Parent code. Can be null or empty if parent is a root.
+ /// Child code.
+ public static string AppendCode(string parentCode, string childCode)
+ {
+ if (childCode.IsNullOrEmpty())
+ {
+ throw new ArgumentNullException(nameof(childCode), "childCode can not be null or empty.");
+ }
+
+ if (parentCode.IsNullOrEmpty())
+ {
+ return childCode;
+ }
+
+ return parentCode + "." + childCode;
+ }
+
+ ///
+ /// Gets relative code to the parent.
+ /// Example: if code = "00019.00055.00001" and parentCode = "00019" then returns "00055.00001".
+ ///
+ /// The code.
+ /// The parent code.
+ public static string GetRelativeCode(string code, string parentCode)
+ {
+ if (code.IsNullOrEmpty())
+ {
+ throw new ArgumentNullException(nameof(code), "code can not be null or empty.");
+ }
+
+ if (parentCode.IsNullOrEmpty())
+ {
+ return code;
+ }
+
+ if (code.Length == parentCode.Length)
+ {
+ return null;
+ }
+
+ return code.Substring(parentCode.Length + 1);
+ }
+
+ ///
+ /// Calculates next code for given code.
+ /// Example: if code = "00019.00055.00001" returns "00019.00055.00002".
+ ///
+ /// The code.
+ public static string CalculateNextCode(string code)
+ {
+ if (code.IsNullOrEmpty())
+ {
+ throw new ArgumentNullException(nameof(code), "code can not be null or empty.");
+ }
+
+ var parentCode = GetParentCode(code);
+ var lastUnitCode = GetLastUnitCode(code);
+
+ return AppendCode(parentCode, CreateCode(Convert.ToInt32(lastUnitCode) + 1));
+ }
+
+ ///
+ /// Gets the last unit code.
+ /// Example: if code = "00019.00055.00001" returns "00001".
+ ///
+ /// The code.
+ public static string GetLastUnitCode(string code)
+ {
+ if (code.IsNullOrEmpty())
+ {
+ throw new ArgumentNullException(nameof(code), "code can not be null or empty.");
+ }
+
+ var splittedCode = code.Split('.');
+ return splittedCode[splittedCode.Length - 1];
+ }
+
+ ///
+ /// Gets parent code.
+ /// Example: if code = "00019.00055.00001" returns "00019.00055".
+ ///
+ /// The code.
+ public static string GetParentCode(string code)
+ {
+ if (code.IsNullOrEmpty())
+ {
+ throw new ArgumentNullException(nameof(code), "code can not be null or empty.");
+ }
+
+ var splittedCode = code.Split('.');
+ if (splittedCode.Length == 1)
+ {
+ return null;
+ }
+
+ return splittedCode.Take(splittedCode.Length - 1).JoinAsString(".");
+ }
+ }
+}
diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/OrganizationUnitManager.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/OrganizationUnitManager.cs
new file mode 100644
index 0000000000..88aad4d66a
--- /dev/null
+++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/OrganizationUnitManager.cs
@@ -0,0 +1,138 @@
+using Microsoft.Extensions.Localization;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Volo.Abp.Domain.Services;
+using Volo.Abp.Identity.Localization;
+using Volo.Abp.Uow;
+
+namespace Volo.Abp.Identity.Organizations
+{
+ ///
+ /// Performs domain logic for Organization Units.
+ ///
+ public class OrganizationUnitManager : DomainService
+ {
+ protected IOrganizationUnitRepository _organizationUnitRepository { get; private set; }
+
+ private readonly IStringLocalizer _localizer;
+
+ public OrganizationUnitManager(
+ IOrganizationUnitRepository organizationUnitRepository,
+ IStringLocalizer localizer)
+ {
+ _organizationUnitRepository = organizationUnitRepository;
+ _localizer = localizer;
+ }
+
+ [UnitOfWork]
+ public virtual async Task CreateAsync(OrganizationUnit organizationUnit)
+ {
+ organizationUnit.Code = await GetNextChildCodeAsync(organizationUnit.ParentId);
+ await ValidateOrganizationUnitAsync(organizationUnit);
+ await _organizationUnitRepository.InsertAsync(organizationUnit);
+ }
+
+ public virtual async Task UpdateAsync(OrganizationUnit organizationUnit)
+ {
+ await ValidateOrganizationUnitAsync(organizationUnit);
+ await _organizationUnitRepository.UpdateAsync(organizationUnit);
+ }
+
+ public virtual async Task GetNextChildCodeAsync(Guid? parentId)
+ {
+ var lastChild = await GetLastChildOrNullAsync(parentId);
+ if (lastChild == null)
+ {
+ var parentCode = parentId != null ? await GetCodeOrDefaultAsync(parentId.Value) : null;
+ return OrganizationUnit.AppendCode(parentCode, OrganizationUnit.CreateCode(1));
+ }
+
+ return OrganizationUnit.CalculateNextCode(lastChild.Code);
+ }
+
+ public virtual async Task GetLastChildOrNullAsync(Guid? parentId)
+ {
+ var children = await _organizationUnitRepository.GetChildrenAsync(parentId);
+ return children.OrderBy(c => c.Code).LastOrDefault();
+ }
+
+ [UnitOfWork]
+ public virtual async Task DeleteAsync(Guid id)
+ {
+ var children = await FindChildrenAsync(id, true);
+
+ foreach (var child in children)
+ {
+ await _organizationUnitRepository.DeleteAsync(child);
+ }
+
+ await _organizationUnitRepository.DeleteAsync(id);
+ }
+
+ [UnitOfWork]
+ public virtual async Task MoveAsync(Guid id, Guid? parentId)
+ {
+ var organizationUnit = await _organizationUnitRepository.GetAsync(id);
+ if (organizationUnit.ParentId == parentId)
+ {
+ return;
+ }
+
+ //Should find children before Code change
+ var children = await FindChildrenAsync(id, true);
+
+ //Store old code of OU
+ var oldCode = organizationUnit.Code;
+
+ //Move OU
+ organizationUnit.Code = await GetNextChildCodeAsync(parentId);
+ organizationUnit.ParentId = parentId;
+
+ await ValidateOrganizationUnitAsync(organizationUnit);
+
+ //Update Children Codes
+ foreach (var child in children)
+ {
+ child.Code = OrganizationUnit.AppendCode(organizationUnit.Code, OrganizationUnit.GetRelativeCode(child.Code, oldCode));
+ }
+ }
+
+ public virtual async Task GetCodeOrDefaultAsync(Guid id)
+ {
+ var ou = await _organizationUnitRepository.GetAsync(id);
+ return ou?.Code;
+ }
+
+ protected virtual async Task ValidateOrganizationUnitAsync(OrganizationUnit organizationUnit)
+ {
+ var siblings = (await FindChildrenAsync(organizationUnit.ParentId))
+ .Where(ou => ou.Id != organizationUnit.Id)
+ .ToList();
+
+ if (siblings.Any(ou => ou.DisplayName == organizationUnit.DisplayName))
+ {
+ throw new UserFriendlyException(_localizer["OrganizationUnitDuplicateDisplayNameWarning", organizationUnit.DisplayName]);
+ }
+ }
+
+ public async Task> FindChildrenAsync(Guid? parentId, bool recursive = false)
+ {
+ if (!recursive)
+ {
+ return await _organizationUnitRepository.GetChildrenAsync(parentId);
+ }
+
+ if (!parentId.HasValue)
+ {
+ return await _organizationUnitRepository.GetListAsync();
+ }
+
+ var code = await GetCodeOrDefaultAsync(parentId.Value);
+
+ return await _organizationUnitRepository.GetAllChildrenWithParentCodeAsync(code, parentId);
+ }
+ }
+}
diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/OrganizationUnitRole.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/OrganizationUnitRole.cs
new file mode 100644
index 0000000000..cd9d9d3ac4
--- /dev/null
+++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/OrganizationUnitRole.cs
@@ -0,0 +1,54 @@
+using System;
+using Volo.Abp.Domain.Entities.Auditing;
+using Volo.Abp.MultiTenancy;
+
+namespace Volo.Abp.Identity.Organizations
+{
+ ///
+ /// Represents membership of a User to an OU.
+ ///
+ public class OrganizationUnitRole : CreationAuditedEntity, IMultiTenant, ISoftDelete
+ {
+ ///
+ /// TenantId of this entity.
+ ///
+ public virtual Guid? TenantId { get; protected set; }
+
+ ///
+ /// Id of the Role.
+ ///
+ public virtual Guid RoleId { get; set; }
+
+ ///
+ /// Id of the .
+ ///
+ public virtual Guid OrganizationUnitId { get; set; }
+
+ ///
+ /// Specifies if the organization is soft deleted or not.
+ ///
+ public virtual bool IsDeleted { get; set; }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public OrganizationUnitRole()
+ {
+
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// TenantId
+ /// Id of the User.
+ /// Id of the .
+ public OrganizationUnitRole(Guid? tenantId, Guid roleId, Guid organizationUnitId)
+ {
+ TenantId = tenantId;
+ RoleId = roleId;
+ OrganizationUnitId = organizationUnitId;
+ }
+
+ }
+}
diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/OrganizationUnitUser.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/OrganizationUnitUser.cs
new file mode 100644
index 0000000000..3ab7a1c711
--- /dev/null
+++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/Organizations/OrganizationUnitUser.cs
@@ -0,0 +1,54 @@
+using System;
+using Volo.Abp.Domain.Entities.Auditing;
+using Volo.Abp.MultiTenancy;
+
+namespace Volo.Abp.Identity.Organizations
+{
+ ///
+ /// Represents membership of a User to an OU.
+ ///
+ public class OrganizationUnitUser : CreationAuditedEntity, IMultiTenant, ISoftDelete
+ {
+
+ ///
+ /// TenantId of this entity.
+ ///
+ public virtual Guid? TenantId { get; set; }
+
+ ///
+ /// Id of the User.
+ ///
+ public virtual Guid UserId { get; set; }
+
+ ///
+ /// Id of the .
+ ///
+ public virtual Guid OrganizationUnitId { get; set; }
+
+ ///
+ /// Specifies if the organization is soft deleted or not.
+ ///
+ public virtual bool IsDeleted { get; set; }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public OrganizationUnitUser()
+ {
+
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// TenantId
+ /// Id of the User.
+ /// Id of the .
+ public OrganizationUnitUser(Guid? tenantId, Guid userId, Guid organizationUnitId)
+ {
+ TenantId = tenantId;
+ UserId = userId;
+ OrganizationUnitId = organizationUnitId;
+ }
+ }
+}
diff --git a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo.Abp.Identity.EntityFrameworkCore.csproj b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo.Abp.Identity.EntityFrameworkCore.csproj
index 945905d75f..994a3a3985 100644
--- a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo.Abp.Identity.EntityFrameworkCore.csproj
+++ b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo.Abp.Identity.EntityFrameworkCore.csproj
@@ -14,8 +14,8 @@
-
+
diff --git a/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreOrganizationUnitRepository.cs b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreOrganizationUnitRepository.cs
new file mode 100644
index 0000000000..f24adad3f7
--- /dev/null
+++ b/modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreOrganizationUnitRepository.cs
@@ -0,0 +1,32 @@
+using Microsoft.EntityFrameworkCore;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Volo.Abp.Domain.Repositories.EntityFrameworkCore;
+using Volo.Abp.EntityFrameworkCore;
+using Volo.Abp.Identity.Organizations;
+
+namespace Volo.Abp.Identity.EntityFrameworkCore
+{
+ public class EfCoreOrganizationUnitRepository : EfCoreRepository, IOrganizationUnitRepository
+ {
+ public EfCoreOrganizationUnitRepository(IDbContextProvider dbContextProvider)
+ : base(dbContextProvider)
+ {
+ }
+
+ public async Task> GetChildrenAsync(Guid? parentId)
+ {
+ return await DbSet.Where(x => x.ParentId == parentId)
+ .ToListAsync();
+ }
+
+ public async Task> GetAllChildrenWithParentCodeAsync(string code, Guid? parentId)
+ {
+ return await DbSet.Where(ou => ou.Code.StartsWith(code) && ou.Id != parentId.Value)
+ .ToListAsync();
+ }
+ }
+}
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 d3c560dca2..b5d7007767 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
@@ -1,6 +1,7 @@
using Microsoft.EntityFrameworkCore;
using Volo.Abp.Data;
using Volo.Abp.EntityFrameworkCore;
+using Volo.Abp.Identity.Organizations;
namespace Volo.Abp.Identity.EntityFrameworkCore
{
@@ -12,5 +13,11 @@ namespace Volo.Abp.Identity.EntityFrameworkCore
DbSet Roles { get; set; }
DbSet ClaimTypes { get; set; }
+
+ DbSet OrganizationUnits { get; set; }
+
+ DbSet OrganizationUnitRoles { get; set; }
+
+ DbSet OrganizationUnitUsers { 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 05050159bc..576a5d2347 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
@@ -1,6 +1,7 @@
using Microsoft.EntityFrameworkCore;
using Volo.Abp.Data;
using Volo.Abp.EntityFrameworkCore;
+using Volo.Abp.Identity.Organizations;
namespace Volo.Abp.Identity.EntityFrameworkCore
{
@@ -16,6 +17,12 @@ namespace Volo.Abp.Identity.EntityFrameworkCore
public DbSet ClaimTypes { get; set; }
+ public DbSet OrganizationUnits { get; set; }
+
+ public DbSet OrganizationUnitRoles { get; set; }
+
+ public DbSet OrganizationUnitUsers { get; set; }
+
public IdentityDbContext(DbContextOptions options)
: base(options)
{