From 23b4f8efa26be5883c0daff65fe9af92391da937 Mon Sep 17 00:00:00 2001 From: Berkan Date: Tue, 2 Feb 2021 15:17:34 +0300 Subject: [PATCH] Add organization membership --- .../IOrganizationMembershipAppService.cs | 18 + .../Memberships/OrganizationMemberDto.cs | 15 + .../EventHubApplicationAutoMapperProfile.cs | 3 + .../OrganizationMembershipAppService.cs | 79 + .../Localization/EventHub/en.json | 7 +- .../Memberships/OrganizationMembership.cs | 27 + .../OrganizationMembershipManager.cs | 53 + ...2_Added_OrganizationMembership.Designer.cs | 2496 +++++++++++++++++ ...0202085532_Added_OrganizationMembership.cs | 54 + ...ventHubMigrationsDbContextModelSnapshot.cs | 54 + .../EntityFrameworkCore/EventHubDbContext.cs | 2 + ...ventHubDbContextModelCreatingExtensions.cs | 17 + .../OrganizationMembershipController.cs | 42 + .../Controllers/WidgetsController.cs | 10 + .../Components/JoinArea/Default.cshtml | 34 + .../JoinArea/JoinAreaViewComponent.cs | 52 + .../Components/JoinArea/join-area.js | 51 + .../Components/MembersArea/Default.cshtml | 14 + .../MembersArea/MembersAreaViewComponent.cs | 73 + .../Components/MembersArea/members-area.css | 5 + .../Components/MembersArea/members-area.js | 18 + .../Pages/Organizations/Profile.cshtml | 151 +- .../OrganizationMembershipAppServiceTests.cs | 101 + .../OrganizationMembershipManagerTests.cs | 71 + 24 files changed, 3376 insertions(+), 71 deletions(-) create mode 100644 src/EventHub.Application.Contracts/Organizations/Memberships/IOrganizationMembershipAppService.cs create mode 100644 src/EventHub.Application.Contracts/Organizations/Memberships/OrganizationMemberDto.cs create mode 100644 src/EventHub.Application/Organizations/Memberships/OrganizationMembershipAppService.cs create mode 100644 src/EventHub.Domain/Organizations/Memberships/OrganizationMembership.cs create mode 100644 src/EventHub.Domain/Organizations/Memberships/OrganizationMembershipManager.cs create mode 100644 src/EventHub.EntityFrameworkCore.DbMigrations/Migrations/20210202085532_Added_OrganizationMembership.Designer.cs create mode 100644 src/EventHub.EntityFrameworkCore.DbMigrations/Migrations/20210202085532_Added_OrganizationMembership.cs create mode 100644 src/EventHub.Web/Controllers/OrganizationMembershipController.cs create mode 100644 src/EventHub.Web/Pages/Organizations/Components/JoinArea/Default.cshtml create mode 100644 src/EventHub.Web/Pages/Organizations/Components/JoinArea/JoinAreaViewComponent.cs create mode 100644 src/EventHub.Web/Pages/Organizations/Components/JoinArea/join-area.js create mode 100644 src/EventHub.Web/Pages/Organizations/Components/MembersArea/Default.cshtml create mode 100644 src/EventHub.Web/Pages/Organizations/Components/MembersArea/MembersAreaViewComponent.cs create mode 100644 src/EventHub.Web/Pages/Organizations/Components/MembersArea/members-area.css create mode 100644 src/EventHub.Web/Pages/Organizations/Components/MembersArea/members-area.js create mode 100644 test/EventHub.Application.Tests/Organizations/Memberships/OrganizationMembershipAppServiceTests.cs create mode 100644 test/EventHub.Domain.Tests/Organizations/Memberships/OrganizationMembershipManagerTests.cs diff --git a/src/EventHub.Application.Contracts/Organizations/Memberships/IOrganizationMembershipAppService.cs b/src/EventHub.Application.Contracts/Organizations/Memberships/IOrganizationMembershipAppService.cs new file mode 100644 index 0000000..953fae3 --- /dev/null +++ b/src/EventHub.Application.Contracts/Organizations/Memberships/IOrganizationMembershipAppService.cs @@ -0,0 +1,18 @@ +using System; +using System.Threading.Tasks; +using Volo.Abp.Application.Dtos; +using Volo.Abp.Application.Services; + +namespace EventHub.Organizations.Memberships +{ + public interface IOrganizationMembershipAppService : IApplicationService + { + Task JoinAsync(Guid organizationId); + + Task LeaveAsync(Guid organizationId); + + Task IsJoinedAsync(Guid organizationId); + + Task> GetMembersAsync(Guid organizationId); + } +} \ No newline at end of file diff --git a/src/EventHub.Application.Contracts/Organizations/Memberships/OrganizationMemberDto.cs b/src/EventHub.Application.Contracts/Organizations/Memberships/OrganizationMemberDto.cs new file mode 100644 index 0000000..056dfb7 --- /dev/null +++ b/src/EventHub.Application.Contracts/Organizations/Memberships/OrganizationMemberDto.cs @@ -0,0 +1,15 @@ +using System; + +namespace EventHub.Organizations.Memberships +{ + public class OrganizationMemberDto + { + public Guid Id { get; set; } + + public string UserName { get; set; } + + public string Name { get; set; } + + public string Surname { get; set; } + } +} \ No newline at end of file diff --git a/src/EventHub.Application/EventHubApplicationAutoMapperProfile.cs b/src/EventHub.Application/EventHubApplicationAutoMapperProfile.cs index c8690d3..adbd955 100644 --- a/src/EventHub.Application/EventHubApplicationAutoMapperProfile.cs +++ b/src/EventHub.Application/EventHubApplicationAutoMapperProfile.cs @@ -2,6 +2,7 @@ using EventHub.Events; using EventHub.Events.Registrations; using EventHub.Organizations; +using EventHub.Organizations.Memberships; using EventHub.Users; using Volo.Abp.AutoMapper; @@ -13,6 +14,8 @@ namespace EventHub { CreateMap(); CreateMap(); + + CreateMap(); CreateMap(); CreateMap() diff --git a/src/EventHub.Application/Organizations/Memberships/OrganizationMembershipAppService.cs b/src/EventHub.Application/Organizations/Memberships/OrganizationMembershipAppService.cs new file mode 100644 index 0000000..a9d5f69 --- /dev/null +++ b/src/EventHub.Application/Organizations/Memberships/OrganizationMembershipAppService.cs @@ -0,0 +1,79 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using EventHub.Users; +using Microsoft.AspNetCore.Authorization; +using Volo.Abp.Application.Dtos; +using Volo.Abp.Domain.Repositories; +using Volo.Abp.Users; + +namespace EventHub.Organizations.Memberships +{ + public class OrganizationMembershipAppService : EventHubAppService, IOrganizationMembershipAppService + { + private readonly OrganizationMembershipManager _organizationMembershipManager; + private readonly IRepository _userRepository; + private readonly IRepository _organizationRepository; + private readonly IRepository _organizationMembershipsRepository; + + public OrganizationMembershipAppService( + OrganizationMembershipManager organizationMembershipManager, + IRepository userRepository, + IRepository organizationRepository, + IRepository organizationMembershipsRepository) + { + _organizationMembershipManager = organizationMembershipManager; + _userRepository = userRepository; + _organizationRepository = organizationRepository; + _organizationMembershipsRepository = organizationMembershipsRepository; + } + + [Authorize] + public async Task JoinAsync(Guid organizationId) + { + await _organizationMembershipManager.JoinAsync( + await _organizationRepository.GetAsync(organizationId), + await _userRepository.GetAsync(CurrentUser.GetId()) + ); + } + + [Authorize] + public async Task LeaveAsync(Guid organizationId) + { + await _organizationMembershipManager.LeaveAsync( + await _organizationRepository.GetAsync(organizationId), + await _userRepository.GetAsync(CurrentUser.GetId()) + ); + } + + [Authorize] + public async Task IsJoinedAsync(Guid organizationId) + { + return await _organizationMembershipManager.IsJoinedAsync( + await _organizationRepository.GetAsync(organizationId), + await _userRepository.GetAsync(CurrentUser.GetId()) + ); + } + + public async Task> GetMembersAsync(Guid organizationId) + { + var organizationMembershipsQueryable = await _organizationMembershipsRepository.GetQueryableAsync(); + var userQueryable = await _userRepository.GetQueryableAsync(); + + var query = from organizationMembership in organizationMembershipsQueryable + join user in userQueryable on organizationMembership.UserId equals user.Id + where organizationMembership.OrganizationId == organizationId + orderby organizationMembership.CreationTime descending + select user; + + var totalCount = await AsyncExecuter.CountAsync(query); + var users = await AsyncExecuter.ToListAsync(query.Take(10)); + + return new PagedResultDto( + totalCount, + ObjectMapper.Map, List>(users) + ); + } + } +} \ No newline at end of file diff --git a/src/EventHub.Domain.Shared/Localization/EventHub/en.json b/src/EventHub.Domain.Shared/Localization/EventHub/en.json index 28b2661..18fb75d 100644 --- a/src/EventHub.Domain.Shared/Localization/EventHub/en.json +++ b/src/EventHub.Domain.Shared/Localization/EventHub/en.json @@ -37,6 +37,11 @@ "Upcoming": "Upcoming", "Past": "Past", "NewEventYouHaveNoOrganizationYetMessage": "You have to create an organization first!", - "CreateAnOrganization": "Create an organization" + "CreateAnOrganization": "Create an organization", + "OrganizationJoinSuccessMessageTitle": "Thank you for your membership!", + "OrganizationJoinSuccessMessage": "See you at the events.", + "OrganizationMembershipLeaveMessage": "You left your organization membership.", + "LeaveOrganization": "Leave this organization", + "JoinOrganization": "Join the organization" } } diff --git a/src/EventHub.Domain/Organizations/Memberships/OrganizationMembership.cs b/src/EventHub.Domain/Organizations/Memberships/OrganizationMembership.cs new file mode 100644 index 0000000..fcdac12 --- /dev/null +++ b/src/EventHub.Domain/Organizations/Memberships/OrganizationMembership.cs @@ -0,0 +1,27 @@ +using System; +using Volo.Abp.Domain.Entities.Auditing; + +namespace EventHub.Organizations.Memberships +{ + public class OrganizationMembership : CreationAuditedAggregateRoot + { + public Guid OrganizationId { get; private set; } + + public Guid UserId { get; private set; } + + private OrganizationMembership() + { + + } + + internal OrganizationMembership( + Guid id, + Guid organizationId, + Guid userId) + : base(id) + { + OrganizationId = organizationId; + UserId = userId; + } + } +} \ No newline at end of file diff --git a/src/EventHub.Domain/Organizations/Memberships/OrganizationMembershipManager.cs b/src/EventHub.Domain/Organizations/Memberships/OrganizationMembershipManager.cs new file mode 100644 index 0000000..3e32daa --- /dev/null +++ b/src/EventHub.Domain/Organizations/Memberships/OrganizationMembershipManager.cs @@ -0,0 +1,53 @@ +using System; +using System.Threading.Tasks; +using EventHub.Users; +using Volo.Abp.Domain.Repositories; +using Volo.Abp.Domain.Services; + +namespace EventHub.Organizations.Memberships +{ + public class OrganizationMembershipManager : DomainService + { + private readonly IRepository _organizationMembershipsRepository; + + public OrganizationMembershipManager(IRepository organizationMembershipsRepository) + { + _organizationMembershipsRepository = organizationMembershipsRepository; + } + + public async Task JoinAsync( + Organization organization, + AppUser user) + { + if (await IsJoinedAsync(organization, user)) + { + return; + } + + await _organizationMembershipsRepository.InsertAsync( + new OrganizationMembership( + GuidGenerator.Create(), + organization.Id, + user.Id + ) + ); + } + + public async Task LeaveAsync( + Organization organization, + AppUser user) + { + await _organizationMembershipsRepository.DeleteAsync( + x => x.OrganizationId == organization.Id && x.UserId == user.Id + ); + } + + public async Task IsJoinedAsync( + Organization organization, + AppUser user) + { + return await _organizationMembershipsRepository + .AnyAsync(x => x.OrganizationId == organization.Id && x.UserId == user.Id); + } + } +} \ No newline at end of file diff --git a/src/EventHub.EntityFrameworkCore.DbMigrations/Migrations/20210202085532_Added_OrganizationMembership.Designer.cs b/src/EventHub.EntityFrameworkCore.DbMigrations/Migrations/20210202085532_Added_OrganizationMembership.Designer.cs new file mode 100644 index 0000000..f5d0caa --- /dev/null +++ b/src/EventHub.EntityFrameworkCore.DbMigrations/Migrations/20210202085532_Added_OrganizationMembership.Designer.cs @@ -0,0 +1,2496 @@ +// +using System; +using EventHub.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Volo.Abp.EntityFrameworkCore; + +namespace EventHub.Migrations +{ + [DbContext(typeof(EventHubMigrationsDbContext))] + [Migration("20210202085532_Added_OrganizationMembership")] + partial class Added_OrganizationMembership + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .UseIdentityColumns() + .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.SqlServer) + .HasAnnotation("Relational:MaxIdentifierLength", 128) + .HasAnnotation("ProductVersion", "5.0.2"); + + modelBuilder.Entity("EventHub.Events.Event", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Capacity") + .HasColumnType("int"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uniqueidentifier") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime2") + .HasColumnName("DeletionTime"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(2000) + .HasColumnType("nvarchar(2000)"); + + b.Property("EndTime") + .HasColumnType("datetime2"); + + b.Property("ExtraProperties") + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("IsOnline") + .HasColumnType("bit"); + + b.Property("LastModificationTime") + .HasColumnType("datetime2") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uniqueidentifier") + .HasColumnName("LastModifierId"); + + b.Property("OrganizationId") + .HasColumnType("uniqueidentifier"); + + b.Property("StartTime") + .HasColumnType("datetime2"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("Url") + .IsRequired() + .HasMaxLength(69) + .HasColumnType("nvarchar(69)"); + + b.Property("UrlCode") + .IsRequired() + .HasMaxLength(8) + .HasColumnType("nvarchar(8)"); + + b.HasKey("Id"); + + b.HasIndex("StartTime"); + + b.HasIndex("UrlCode"); + + b.HasIndex("OrganizationId", "StartTime"); + + b.ToTable("AppEvents"); + }); + + modelBuilder.Entity("EventHub.Events.Registrations.EventRegistration", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("EventId") + .HasColumnType("uniqueidentifier"); + + b.Property("ExtraProperties") + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.HasIndex("EventId", "UserId"); + + b.ToTable("AppEventRegistrations"); + }); + + modelBuilder.Entity("EventHub.Organizations.Memberships.OrganizationMembership", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("OrganizationId") + .HasColumnType("uniqueidentifier"); + + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.HasIndex("OrganizationId", "UserId"); + + b.ToTable("AppOrganizationMemberships"); + }); + + modelBuilder.Entity("EventHub.Organizations.Organization", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uniqueidentifier") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime2") + .HasColumnName("DeletionTime"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("ExtraProperties") + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("FacebookUsername") + .HasColumnType("nvarchar(max)"); + + b.Property("GitHubUsername") + .HasColumnType("nvarchar(max)"); + + b.Property("InstagramUsername") + .HasColumnType("nvarchar(max)"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("datetime2") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uniqueidentifier") + .HasColumnName("LastModifierId"); + + b.Property("MediumUsername") + .HasColumnType("nvarchar(max)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(32) + .HasColumnType("nvarchar(32)"); + + b.Property("OwnerUserId") + .HasColumnType("uniqueidentifier"); + + b.Property("TwitterUsername") + .HasColumnType("nvarchar(max)"); + + b.Property("Website") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("DisplayName"); + + b.HasIndex("Name"); + + b.HasIndex("OwnerUserId"); + + b.ToTable("AppOrganizations"); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ApplicationName") + .HasMaxLength(96) + .HasColumnType("nvarchar(96)") + .HasColumnName("ApplicationName"); + + b.Property("BrowserInfo") + .HasMaxLength(512) + .HasColumnType("nvarchar(512)") + .HasColumnName("BrowserInfo"); + + b.Property("ClientId") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)") + .HasColumnName("ClientId"); + + b.Property("ClientIpAddress") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)") + .HasColumnName("ClientIpAddress"); + + b.Property("ClientName") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)") + .HasColumnName("ClientName"); + + b.Property("Comments") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)") + .HasColumnName("Comments"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CorrelationId") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)") + .HasColumnName("CorrelationId"); + + b.Property("Exceptions") + .HasMaxLength(4000) + .HasColumnType("nvarchar(4000)") + .HasColumnName("Exceptions"); + + b.Property("ExecutionDuration") + .HasColumnType("int") + .HasColumnName("ExecutionDuration"); + + b.Property("ExecutionTime") + .HasColumnType("datetime2"); + + b.Property("ExtraProperties") + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("HttpMethod") + .HasMaxLength(16) + .HasColumnType("nvarchar(16)") + .HasColumnName("HttpMethod"); + + b.Property("HttpStatusCode") + .HasColumnType("int") + .HasColumnName("HttpStatusCode"); + + b.Property("ImpersonatorTenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("ImpersonatorTenantId"); + + b.Property("ImpersonatorUserId") + .HasColumnType("uniqueidentifier") + .HasColumnName("ImpersonatorUserId"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.Property("TenantName") + .HasColumnType("nvarchar(max)"); + + b.Property("Url") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)") + .HasColumnName("Url"); + + b.Property("UserId") + .HasColumnType("uniqueidentifier") + .HasColumnName("UserId"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)") + .HasColumnName("UserName"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "ExecutionTime"); + + b.HasIndex("TenantId", "UserId", "ExecutionTime"); + + b.ToTable("AbpAuditLogs"); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLogAction", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("AuditLogId") + .HasColumnType("uniqueidentifier") + .HasColumnName("AuditLogId"); + + b.Property("ExecutionDuration") + .HasColumnType("int") + .HasColumnName("ExecutionDuration"); + + b.Property("ExecutionTime") + .HasColumnType("datetime2") + .HasColumnName("ExecutionTime"); + + b.Property("ExtraProperties") + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("MethodName") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)") + .HasColumnName("MethodName"); + + b.Property("Parameters") + .HasMaxLength(2000) + .HasColumnType("nvarchar(2000)") + .HasColumnName("Parameters"); + + b.Property("ServiceName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)") + .HasColumnName("ServiceName"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("AuditLogId"); + + b.HasIndex("TenantId", "ServiceName", "MethodName", "ExecutionTime"); + + b.ToTable("AbpAuditLogActions"); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.EntityChange", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("AuditLogId") + .HasColumnType("uniqueidentifier") + .HasColumnName("AuditLogId"); + + b.Property("ChangeTime") + .HasColumnType("datetime2") + .HasColumnName("ChangeTime"); + + b.Property("ChangeType") + .HasColumnType("tinyint") + .HasColumnName("ChangeType"); + + b.Property("EntityId") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)") + .HasColumnName("EntityId"); + + b.Property("EntityTenantId") + .HasColumnType("uniqueidentifier"); + + b.Property("EntityTypeFullName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)") + .HasColumnName("EntityTypeFullName"); + + b.Property("ExtraProperties") + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("AuditLogId"); + + b.HasIndex("TenantId", "EntityTypeFullName", "EntityId"); + + b.ToTable("AbpEntityChanges"); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.EntityPropertyChange", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("EntityChangeId") + .HasColumnType("uniqueidentifier"); + + b.Property("NewValue") + .HasMaxLength(512) + .HasColumnType("nvarchar(512)") + .HasColumnName("NewValue"); + + b.Property("OriginalValue") + .HasMaxLength(512) + .HasColumnType("nvarchar(512)") + .HasColumnName("OriginalValue"); + + b.Property("PropertyName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)") + .HasColumnName("PropertyName"); + + b.Property("PropertyTypeFullName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)") + .HasColumnName("PropertyTypeFullName"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("EntityChangeId"); + + b.ToTable("AbpEntityPropertyChanges"); + }); + + modelBuilder.Entity("Volo.Abp.BackgroundJobs.BackgroundJobRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("ExtraProperties") + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("IsAbandoned") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false); + + b.Property("JobArgs") + .IsRequired() + .HasMaxLength(1048576) + .HasColumnType("nvarchar(max)"); + + b.Property("JobName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("LastTryTime") + .HasColumnType("datetime2"); + + b.Property("NextTryTime") + .HasColumnType("datetime2"); + + b.Property("Priority") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint") + .HasDefaultValue((byte)15); + + b.Property("TryCount") + .ValueGeneratedOnAdd() + .HasColumnType("smallint") + .HasDefaultValue((short)0); + + b.HasKey("Id"); + + b.HasIndex("IsAbandoned", "NextTryTime"); + + b.ToTable("AbpBackgroundJobs"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityClaimType", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("Description") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("ExtraProperties") + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("IsStatic") + .HasColumnType("bit"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("Regex") + .HasMaxLength(512) + .HasColumnType("nvarchar(512)"); + + b.Property("RegexDescription") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("Required") + .HasColumnType("bit"); + + b.Property("ValueType") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("AbpClaimTypes"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityLinkUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("SourceTenantId") + .HasColumnType("uniqueidentifier"); + + b.Property("SourceUserId") + .HasColumnType("uniqueidentifier"); + + b.Property("TargetTenantId") + .HasColumnType("uniqueidentifier"); + + b.Property("TargetUserId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("SourceUserId", "SourceTenantId", "TargetUserId", "TargetTenantId") + .IsUnique() + .HasFilter("[SourceTenantId] IS NOT NULL AND [TargetTenantId] IS NOT NULL"); + + b.ToTable("AbpLinkUsers"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("ExtraProperties") + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("IsDefault") + .HasColumnType("bit") + .HasColumnName("IsDefault"); + + b.Property("IsPublic") + .HasColumnType("bit") + .HasColumnName("IsPublic"); + + b.Property("IsStatic") + .HasColumnType("bit") + .HasColumnName("IsStatic"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("NormalizedName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName"); + + b.ToTable("AbpRoles"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("ClaimType") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("ClaimValue") + .HasMaxLength(1024) + .HasColumnType("nvarchar(1024)"); + + b.Property("RoleId") + .HasColumnType("uniqueidentifier"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AbpRoleClaims"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentitySecurityLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Action") + .HasMaxLength(96) + .HasColumnType("nvarchar(96)"); + + b.Property("ApplicationName") + .HasMaxLength(96) + .HasColumnType("nvarchar(96)"); + + b.Property("BrowserInfo") + .HasMaxLength(512) + .HasColumnType("nvarchar(512)"); + + b.Property("ClientId") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("ClientIpAddress") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CorrelationId") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("CreationTime") + .HasColumnType("datetime2"); + + b.Property("ExtraProperties") + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("Identity") + .HasMaxLength(96) + .HasColumnType("nvarchar(96)"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.Property("TenantName") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "Action"); + + b.HasIndex("TenantId", "ApplicationName"); + + b.HasIndex("TenantId", "Identity"); + + b.HasIndex("TenantId", "UserId"); + + b.ToTable("AbpSecurityLogs"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("AccessFailedCount") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasDefaultValue(0) + .HasColumnName("AccessFailedCount"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uniqueidentifier") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime2") + .HasColumnName("DeletionTime"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)") + .HasColumnName("Email"); + + b.Property("EmailConfirmed") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("EmailConfirmed"); + + b.Property("ExtraProperties") + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("IsExternal") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("IsExternal"); + + b.Property("LastModificationTime") + .HasColumnType("datetime2") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uniqueidentifier") + .HasColumnName("LastModifierId"); + + b.Property("LockoutEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("LockoutEnabled"); + + b.Property("LockoutEnd") + .HasColumnType("datetimeoffset"); + + b.Property("Name") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)") + .HasColumnName("Name"); + + b.Property("NormalizedEmail") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)") + .HasColumnName("NormalizedEmail"); + + b.Property("NormalizedUserName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)") + .HasColumnName("NormalizedUserName"); + + b.Property("PasswordHash") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)") + .HasColumnName("PasswordHash"); + + b.Property("PhoneNumber") + .HasMaxLength(16) + .HasColumnType("nvarchar(16)") + .HasColumnName("PhoneNumber"); + + b.Property("PhoneNumberConfirmed") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("PhoneNumberConfirmed"); + + b.Property("SecurityStamp") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)") + .HasColumnName("SecurityStamp"); + + b.Property("Surname") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)") + .HasColumnName("Surname"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.Property("TwoFactorEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("TwoFactorEnabled"); + + b.Property("UserName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)") + .HasColumnName("UserName"); + + b.HasKey("Id"); + + b.HasIndex("Email"); + + b.HasIndex("NormalizedEmail"); + + b.HasIndex("NormalizedUserName"); + + b.HasIndex("UserName"); + + b.ToTable("AbpUsers"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("ClaimType") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("ClaimValue") + .HasMaxLength(1024) + .HasColumnType("nvarchar(1024)"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AbpUserClaims"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserLogin", b => + { + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.Property("LoginProvider") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("ProviderDisplayName") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("ProviderKey") + .IsRequired() + .HasMaxLength(196) + .HasColumnType("nvarchar(196)"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("UserId", "LoginProvider"); + + b.HasIndex("LoginProvider", "ProviderKey"); + + b.ToTable("AbpUserLogins"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserOrganizationUnit", b => + { + b.Property("OrganizationUnitId") + .HasColumnType("uniqueidentifier"); + + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("OrganizationUnitId", "UserId"); + + b.HasIndex("UserId", "OrganizationUnitId"); + + b.ToTable("AbpUserOrganizationUnits"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.Property("RoleId") + .HasColumnType("uniqueidentifier"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId", "UserId"); + + b.ToTable("AbpUserRoles"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.Property("LoginProvider") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("Name") + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.Property("Value") + .HasColumnType("nvarchar(max)"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AbpUserTokens"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Code") + .IsRequired() + .HasMaxLength(95) + .HasColumnType("nvarchar(95)") + .HasColumnName("Code"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uniqueidentifier") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime2") + .HasColumnName("DeletionTime"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)") + .HasColumnName("DisplayName"); + + b.Property("ExtraProperties") + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("datetime2") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uniqueidentifier") + .HasColumnName("LastModifierId"); + + b.Property("ParentId") + .HasColumnType("uniqueidentifier"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("Code"); + + b.HasIndex("ParentId"); + + b.ToTable("AbpOrganizationUnits"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnitRole", b => + { + b.Property("OrganizationUnitId") + .HasColumnType("uniqueidentifier"); + + b.Property("RoleId") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("OrganizationUnitId", "RoleId"); + + b.HasIndex("RoleId", "OrganizationUnitId"); + + b.ToTable("AbpOrganizationUnitRoles"); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiResource", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("AllowedAccessTokenSigningAlgorithms") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uniqueidentifier") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime2") + .HasColumnName("DeletionTime"); + + b.Property("Description") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("DisplayName") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("Enabled") + .HasColumnType("bit"); + + b.Property("ExtraProperties") + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("datetime2") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uniqueidentifier") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("ShowInDiscoveryDocument") + .HasColumnType("bit"); + + b.HasKey("Id"); + + b.ToTable("IdentityServerApiResources"); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiResourceClaim", b => + { + b.Property("ApiResourceId") + .HasColumnType("uniqueidentifier"); + + b.Property("Type") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.HasKey("ApiResourceId", "Type"); + + b.ToTable("IdentityServerApiResourceClaims"); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiResourceProperty", b => + { + b.Property("ApiResourceId") + .HasColumnType("uniqueidentifier"); + + b.Property("Key") + .HasMaxLength(250) + .HasColumnType("nvarchar(250)"); + + b.Property("Value") + .HasMaxLength(2000) + .HasColumnType("nvarchar(2000)"); + + b.HasKey("ApiResourceId", "Key", "Value"); + + b.ToTable("IdentityServerApiResourceProperties"); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiResourceScope", b => + { + b.Property("ApiResourceId") + .HasColumnType("uniqueidentifier"); + + b.Property("Scope") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.HasKey("ApiResourceId", "Scope"); + + b.ToTable("IdentityServerApiResourceScopes"); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiResourceSecret", b => + { + b.Property("ApiResourceId") + .HasColumnType("uniqueidentifier"); + + b.Property("Type") + .HasMaxLength(250) + .HasColumnType("nvarchar(250)"); + + b.Property("Value") + .HasMaxLength(4000) + .HasColumnType("nvarchar(4000)"); + + b.Property("Description") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("Expiration") + .HasColumnType("datetime2"); + + b.HasKey("ApiResourceId", "Type", "Value"); + + b.ToTable("IdentityServerApiResourceSecrets"); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.ApiScopes.ApiScope", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uniqueidentifier") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime2") + .HasColumnName("DeletionTime"); + + b.Property("Description") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("DisplayName") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("Emphasize") + .HasColumnType("bit"); + + b.Property("Enabled") + .HasColumnType("bit"); + + b.Property("ExtraProperties") + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("datetime2") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uniqueidentifier") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("Required") + .HasColumnType("bit"); + + b.Property("ShowInDiscoveryDocument") + .HasColumnType("bit"); + + b.HasKey("Id"); + + b.ToTable("IdentityServerApiScopes"); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.ApiScopes.ApiScopeClaim", b => + { + b.Property("ApiScopeId") + .HasColumnType("uniqueidentifier"); + + b.Property("Type") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.HasKey("ApiScopeId", "Type"); + + b.ToTable("IdentityServerApiScopeClaims"); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.ApiScopes.ApiScopeProperty", b => + { + b.Property("ApiScopeId") + .HasColumnType("uniqueidentifier"); + + b.Property("Key") + .HasMaxLength(250) + .HasColumnType("nvarchar(250)"); + + b.Property("Value") + .HasMaxLength(2000) + .HasColumnType("nvarchar(2000)"); + + b.HasKey("ApiScopeId", "Key", "Value"); + + b.ToTable("IdentityServerApiScopeProperties"); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.Client", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("AbsoluteRefreshTokenLifetime") + .HasColumnType("int"); + + b.Property("AccessTokenLifetime") + .HasColumnType("int"); + + b.Property("AccessTokenType") + .HasColumnType("int"); + + b.Property("AllowAccessTokensViaBrowser") + .HasColumnType("bit"); + + b.Property("AllowOfflineAccess") + .HasColumnType("bit"); + + b.Property("AllowPlainTextPkce") + .HasColumnType("bit"); + + b.Property("AllowRememberConsent") + .HasColumnType("bit"); + + b.Property("AllowedIdentityTokenSigningAlgorithms") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("AlwaysIncludeUserClaimsInIdToken") + .HasColumnType("bit"); + + b.Property("AlwaysSendClientClaims") + .HasColumnType("bit"); + + b.Property("AuthorizationCodeLifetime") + .HasColumnType("int"); + + b.Property("BackChannelLogoutSessionRequired") + .HasColumnType("bit"); + + b.Property("BackChannelLogoutUri") + .HasMaxLength(2000) + .HasColumnType("nvarchar(2000)"); + + b.Property("ClientClaimsPrefix") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("ClientId") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("ClientName") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("ClientUri") + .HasMaxLength(2000) + .HasColumnType("nvarchar(2000)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("ConsentLifetime") + .HasColumnType("int"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uniqueidentifier") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime2") + .HasColumnName("DeletionTime"); + + b.Property("Description") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("DeviceCodeLifetime") + .HasColumnType("int"); + + b.Property("EnableLocalLogin") + .HasColumnType("bit"); + + b.Property("Enabled") + .HasColumnType("bit"); + + b.Property("ExtraProperties") + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("FrontChannelLogoutSessionRequired") + .HasColumnType("bit"); + + b.Property("FrontChannelLogoutUri") + .HasMaxLength(2000) + .HasColumnType("nvarchar(2000)"); + + b.Property("IdentityTokenLifetime") + .HasColumnType("int"); + + b.Property("IncludeJwtId") + .HasColumnType("bit"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("datetime2") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uniqueidentifier") + .HasColumnName("LastModifierId"); + + b.Property("LogoUri") + .HasMaxLength(2000) + .HasColumnType("nvarchar(2000)"); + + b.Property("PairWiseSubjectSalt") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("ProtocolType") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("RefreshTokenExpiration") + .HasColumnType("int"); + + b.Property("RefreshTokenUsage") + .HasColumnType("int"); + + b.Property("RequireClientSecret") + .HasColumnType("bit"); + + b.Property("RequireConsent") + .HasColumnType("bit"); + + b.Property("RequirePkce") + .HasColumnType("bit"); + + b.Property("RequireRequestObject") + .HasColumnType("bit"); + + b.Property("SlidingRefreshTokenLifetime") + .HasColumnType("int"); + + b.Property("UpdateAccessTokenClaimsOnRefresh") + .HasColumnType("bit"); + + b.Property("UserCodeType") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("UserSsoLifetime") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("ClientId"); + + b.ToTable("IdentityServerClients"); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientClaim", b => + { + b.Property("ClientId") + .HasColumnType("uniqueidentifier"); + + b.Property("Type") + .HasMaxLength(250) + .HasColumnType("nvarchar(250)"); + + b.Property("Value") + .HasMaxLength(250) + .HasColumnType("nvarchar(250)"); + + b.HasKey("ClientId", "Type", "Value"); + + b.ToTable("IdentityServerClientClaims"); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientCorsOrigin", b => + { + b.Property("ClientId") + .HasColumnType("uniqueidentifier"); + + b.Property("Origin") + .HasMaxLength(150) + .HasColumnType("nvarchar(150)"); + + b.HasKey("ClientId", "Origin"); + + b.ToTable("IdentityServerClientCorsOrigins"); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientGrantType", b => + { + b.Property("ClientId") + .HasColumnType("uniqueidentifier"); + + b.Property("GrantType") + .HasMaxLength(250) + .HasColumnType("nvarchar(250)"); + + b.HasKey("ClientId", "GrantType"); + + b.ToTable("IdentityServerClientGrantTypes"); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientIdPRestriction", b => + { + b.Property("ClientId") + .HasColumnType("uniqueidentifier"); + + b.Property("Provider") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.HasKey("ClientId", "Provider"); + + b.ToTable("IdentityServerClientIdPRestrictions"); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientPostLogoutRedirectUri", b => + { + b.Property("ClientId") + .HasColumnType("uniqueidentifier"); + + b.Property("PostLogoutRedirectUri") + .HasMaxLength(2000) + .HasColumnType("nvarchar(2000)"); + + b.HasKey("ClientId", "PostLogoutRedirectUri"); + + b.ToTable("IdentityServerClientPostLogoutRedirectUris"); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientProperty", b => + { + b.Property("ClientId") + .HasColumnType("uniqueidentifier"); + + b.Property("Key") + .HasMaxLength(250) + .HasColumnType("nvarchar(250)"); + + b.Property("Value") + .HasMaxLength(2000) + .HasColumnType("nvarchar(2000)"); + + b.HasKey("ClientId", "Key", "Value"); + + b.ToTable("IdentityServerClientProperties"); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientRedirectUri", b => + { + b.Property("ClientId") + .HasColumnType("uniqueidentifier"); + + b.Property("RedirectUri") + .HasMaxLength(2000) + .HasColumnType("nvarchar(2000)"); + + b.HasKey("ClientId", "RedirectUri"); + + b.ToTable("IdentityServerClientRedirectUris"); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientScope", b => + { + b.Property("ClientId") + .HasColumnType("uniqueidentifier"); + + b.Property("Scope") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.HasKey("ClientId", "Scope"); + + b.ToTable("IdentityServerClientScopes"); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientSecret", b => + { + b.Property("ClientId") + .HasColumnType("uniqueidentifier"); + + b.Property("Type") + .HasMaxLength(250) + .HasColumnType("nvarchar(250)"); + + b.Property("Value") + .HasMaxLength(4000) + .HasColumnType("nvarchar(4000)"); + + b.Property("Description") + .HasMaxLength(2000) + .HasColumnType("nvarchar(2000)"); + + b.Property("Expiration") + .HasColumnType("datetime2"); + + b.HasKey("ClientId", "Type", "Value"); + + b.ToTable("IdentityServerClientSecrets"); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Devices.DeviceFlowCodes", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ClientId") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("Data") + .IsRequired() + .HasMaxLength(50000) + .HasColumnType("nvarchar(max)"); + + b.Property("Description") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("DeviceCode") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("Expiration") + .IsRequired() + .HasColumnType("datetime2"); + + b.Property("ExtraProperties") + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("SessionId") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("SubjectId") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("UserCode") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.HasKey("Id"); + + b.HasIndex("DeviceCode") + .IsUnique(); + + b.HasIndex("Expiration"); + + b.HasIndex("UserCode"); + + b.ToTable("IdentityServerDeviceFlowCodes"); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Grants.PersistedGrant", b => + { + b.Property("Key") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("ClientId") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("ConsumedTime") + .HasColumnType("datetime2"); + + b.Property("CreationTime") + .HasColumnType("datetime2"); + + b.Property("Data") + .IsRequired() + .HasMaxLength(50000) + .HasColumnType("nvarchar(max)"); + + b.Property("Description") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("Expiration") + .HasColumnType("datetime2"); + + b.Property("ExtraProperties") + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("SessionId") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("SubjectId") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("Type") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.HasKey("Key"); + + b.HasIndex("Expiration"); + + b.HasIndex("SubjectId", "ClientId", "Type"); + + b.HasIndex("SubjectId", "SessionId", "Type"); + + b.ToTable("IdentityServerPersistedGrants"); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.IdentityResources.IdentityResource", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("uniqueidentifier") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime2") + .HasColumnName("DeletionTime"); + + b.Property("Description") + .HasMaxLength(1000) + .HasColumnType("nvarchar(1000)"); + + b.Property("DisplayName") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("Emphasize") + .HasColumnType("bit"); + + b.Property("Enabled") + .HasColumnType("bit"); + + b.Property("ExtraProperties") + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("bit") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("datetime2") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("uniqueidentifier") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("Required") + .HasColumnType("bit"); + + b.Property("ShowInDiscoveryDocument") + .HasColumnType("bit"); + + b.HasKey("Id"); + + b.ToTable("IdentityServerIdentityResources"); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.IdentityResources.IdentityResourceClaim", b => + { + b.Property("IdentityResourceId") + .HasColumnType("uniqueidentifier"); + + b.Property("Type") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.HasKey("IdentityResourceId", "Type"); + + b.ToTable("IdentityServerIdentityResourceClaims"); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.IdentityResources.IdentityResourceProperty", b => + { + b.Property("IdentityResourceId") + .HasColumnType("uniqueidentifier"); + + b.Property("Key") + .HasMaxLength(250) + .HasColumnType("nvarchar(250)"); + + b.Property("Value") + .HasMaxLength(2000) + .HasColumnType("nvarchar(2000)"); + + b.HasKey("IdentityResourceId", "Key", "Value"); + + b.ToTable("IdentityServerIdentityResourceProperties"); + }); + + modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionGrant", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("ProviderKey") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("ProviderName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("TenantId") + .HasColumnType("uniqueidentifier") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("Name", "ProviderName", "ProviderKey"); + + b.ToTable("AbpPermissionGrants"); + }); + + modelBuilder.Entity("Volo.Abp.SettingManagement.Setting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("nvarchar(128)"); + + b.Property("ProviderKey") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("ProviderName") + .HasMaxLength(64) + .HasColumnType("nvarchar(64)"); + + b.Property("Value") + .IsRequired() + .HasMaxLength(2048) + .HasColumnType("nvarchar(2048)"); + + b.HasKey("Id"); + + b.HasIndex("Name", "ProviderName", "ProviderKey"); + + b.ToTable("AbpSettings"); + }); + + modelBuilder.Entity("EventHub.Events.Event", b => + { + b.HasOne("EventHub.Organizations.Organization", null) + .WithMany() + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + }); + + modelBuilder.Entity("EventHub.Events.Registrations.EventRegistration", b => + { + b.HasOne("EventHub.Events.Event", null) + .WithMany() + .HasForeignKey("EventId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + }); + + modelBuilder.Entity("EventHub.Organizations.Memberships.OrganizationMembership", b => + { + b.HasOne("EventHub.Organizations.Organization", null) + .WithMany() + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + }); + + modelBuilder.Entity("EventHub.Organizations.Organization", b => + { + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany() + .HasForeignKey("OwnerUserId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLogAction", b => + { + b.HasOne("Volo.Abp.AuditLogging.AuditLog", null) + .WithMany("Actions") + .HasForeignKey("AuditLogId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.EntityChange", b => + { + b.HasOne("Volo.Abp.AuditLogging.AuditLog", null) + .WithMany("EntityChanges") + .HasForeignKey("AuditLogId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.EntityPropertyChange", b => + { + b.HasOne("Volo.Abp.AuditLogging.EntityChange", null) + .WithMany("PropertyChanges") + .HasForeignKey("EntityChangeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRoleClaim", b => + { + b.HasOne("Volo.Abp.Identity.IdentityRole", null) + .WithMany("Claims") + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserClaim", b => + { + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("Claims") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserLogin", b => + { + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("Logins") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserOrganizationUnit", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany() + .HasForeignKey("OrganizationUnitId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("OrganizationUnits") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserRole", b => + { + b.HasOne("Volo.Abp.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("Roles") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUserToken", b => + { + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany("Tokens") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany() + .HasForeignKey("ParentId"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnitRole", b => + { + b.HasOne("Volo.Abp.Identity.OrganizationUnit", null) + .WithMany("Roles") + .HasForeignKey("OrganizationUnitId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Volo.Abp.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiResourceClaim", b => + { + b.HasOne("Volo.Abp.IdentityServer.ApiResources.ApiResource", null) + .WithMany("UserClaims") + .HasForeignKey("ApiResourceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiResourceProperty", b => + { + b.HasOne("Volo.Abp.IdentityServer.ApiResources.ApiResource", null) + .WithMany("Properties") + .HasForeignKey("ApiResourceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiResourceScope", b => + { + b.HasOne("Volo.Abp.IdentityServer.ApiResources.ApiResource", null) + .WithMany("Scopes") + .HasForeignKey("ApiResourceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiResourceSecret", b => + { + b.HasOne("Volo.Abp.IdentityServer.ApiResources.ApiResource", null) + .WithMany("Secrets") + .HasForeignKey("ApiResourceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.ApiScopes.ApiScopeClaim", b => + { + b.HasOne("Volo.Abp.IdentityServer.ApiScopes.ApiScope", null) + .WithMany("UserClaims") + .HasForeignKey("ApiScopeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.ApiScopes.ApiScopeProperty", b => + { + b.HasOne("Volo.Abp.IdentityServer.ApiScopes.ApiScope", null) + .WithMany("Properties") + .HasForeignKey("ApiScopeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientClaim", b => + { + b.HasOne("Volo.Abp.IdentityServer.Clients.Client", null) + .WithMany("Claims") + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientCorsOrigin", b => + { + b.HasOne("Volo.Abp.IdentityServer.Clients.Client", null) + .WithMany("AllowedCorsOrigins") + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientGrantType", b => + { + b.HasOne("Volo.Abp.IdentityServer.Clients.Client", null) + .WithMany("AllowedGrantTypes") + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientIdPRestriction", b => + { + b.HasOne("Volo.Abp.IdentityServer.Clients.Client", null) + .WithMany("IdentityProviderRestrictions") + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientPostLogoutRedirectUri", b => + { + b.HasOne("Volo.Abp.IdentityServer.Clients.Client", null) + .WithMany("PostLogoutRedirectUris") + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientProperty", b => + { + b.HasOne("Volo.Abp.IdentityServer.Clients.Client", null) + .WithMany("Properties") + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientRedirectUri", b => + { + b.HasOne("Volo.Abp.IdentityServer.Clients.Client", null) + .WithMany("RedirectUris") + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientScope", b => + { + b.HasOne("Volo.Abp.IdentityServer.Clients.Client", null) + .WithMany("AllowedScopes") + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.ClientSecret", b => + { + b.HasOne("Volo.Abp.IdentityServer.Clients.Client", null) + .WithMany("ClientSecrets") + .HasForeignKey("ClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.IdentityResources.IdentityResourceClaim", b => + { + b.HasOne("Volo.Abp.IdentityServer.IdentityResources.IdentityResource", null) + .WithMany("UserClaims") + .HasForeignKey("IdentityResourceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.IdentityResources.IdentityResourceProperty", b => + { + b.HasOne("Volo.Abp.IdentityServer.IdentityResources.IdentityResource", null) + .WithMany("Properties") + .HasForeignKey("IdentityResourceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLog", b => + { + b.Navigation("Actions"); + + b.Navigation("EntityChanges"); + }); + + modelBuilder.Entity("Volo.Abp.AuditLogging.EntityChange", b => + { + b.Navigation("PropertyChanges"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityRole", b => + { + b.Navigation("Claims"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.IdentityUser", b => + { + b.Navigation("Claims"); + + b.Navigation("Logins"); + + b.Navigation("OrganizationUnits"); + + b.Navigation("Roles"); + + b.Navigation("Tokens"); + }); + + modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b => + { + b.Navigation("Roles"); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiResource", b => + { + b.Navigation("Properties"); + + b.Navigation("Scopes"); + + b.Navigation("Secrets"); + + b.Navigation("UserClaims"); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.ApiScopes.ApiScope", b => + { + b.Navigation("Properties"); + + b.Navigation("UserClaims"); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.Client", b => + { + b.Navigation("AllowedCorsOrigins"); + + b.Navigation("AllowedGrantTypes"); + + b.Navigation("AllowedScopes"); + + b.Navigation("Claims"); + + b.Navigation("ClientSecrets"); + + b.Navigation("IdentityProviderRestrictions"); + + b.Navigation("PostLogoutRedirectUris"); + + b.Navigation("Properties"); + + b.Navigation("RedirectUris"); + }); + + modelBuilder.Entity("Volo.Abp.IdentityServer.IdentityResources.IdentityResource", b => + { + b.Navigation("Properties"); + + b.Navigation("UserClaims"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/EventHub.EntityFrameworkCore.DbMigrations/Migrations/20210202085532_Added_OrganizationMembership.cs b/src/EventHub.EntityFrameworkCore.DbMigrations/Migrations/20210202085532_Added_OrganizationMembership.cs new file mode 100644 index 0000000..04d2765 --- /dev/null +++ b/src/EventHub.EntityFrameworkCore.DbMigrations/Migrations/20210202085532_Added_OrganizationMembership.cs @@ -0,0 +1,54 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +namespace EventHub.Migrations +{ + public partial class Added_OrganizationMembership : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "AppOrganizationMemberships", + columns: table => new + { + Id = table.Column(type: "uniqueidentifier", nullable: false), + OrganizationId = table.Column(type: "uniqueidentifier", nullable: false), + UserId = table.Column(type: "uniqueidentifier", nullable: false), + ExtraProperties = table.Column(type: "nvarchar(max)", nullable: true), + ConcurrencyStamp = table.Column(type: "nvarchar(40)", maxLength: 40, nullable: true), + CreationTime = table.Column(type: "datetime2", nullable: false), + CreatorId = table.Column(type: "uniqueidentifier", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_AppOrganizationMemberships", x => x.Id); + table.ForeignKey( + name: "FK_AppOrganizationMemberships_AbpUsers_UserId", + column: x => x.UserId, + principalTable: "AbpUsers", + principalColumn: "Id"); + table.ForeignKey( + name: "FK_AppOrganizationMemberships_AppOrganizations_OrganizationId", + column: x => x.OrganizationId, + principalTable: "AppOrganizations", + principalColumn: "Id"); + }); + + migrationBuilder.CreateIndex( + name: "IX_AppOrganizationMemberships_OrganizationId_UserId", + table: "AppOrganizationMemberships", + columns: new[] { "OrganizationId", "UserId" }); + + migrationBuilder.CreateIndex( + name: "IX_AppOrganizationMemberships_UserId", + table: "AppOrganizationMemberships", + column: "UserId"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "AppOrganizationMemberships"); + } + } +} diff --git a/src/EventHub.EntityFrameworkCore.DbMigrations/Migrations/EventHubMigrationsDbContextModelSnapshot.cs b/src/EventHub.EntityFrameworkCore.DbMigrations/Migrations/EventHubMigrationsDbContextModelSnapshot.cs index 3b4bc25..641dcca 100644 --- a/src/EventHub.EntityFrameworkCore.DbMigrations/Migrations/EventHubMigrationsDbContextModelSnapshot.cs +++ b/src/EventHub.EntityFrameworkCore.DbMigrations/Migrations/EventHubMigrationsDbContextModelSnapshot.cs @@ -152,6 +152,45 @@ namespace EventHub.Migrations b.ToTable("AppEventRegistrations"); }); + modelBuilder.Entity("EventHub.Organizations.Memberships.OrganizationMembership", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("datetime2") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("uniqueidentifier") + .HasColumnName("CreatorId"); + + b.Property("ExtraProperties") + .HasColumnType("nvarchar(max)") + .HasColumnName("ExtraProperties"); + + b.Property("OrganizationId") + .HasColumnType("uniqueidentifier"); + + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.HasIndex("OrganizationId", "UserId"); + + b.ToTable("AppOrganizationMemberships"); + }); + modelBuilder.Entity("EventHub.Organizations.Organization", b => { b.Property("Id") @@ -2077,6 +2116,21 @@ namespace EventHub.Migrations .IsRequired(); }); + modelBuilder.Entity("EventHub.Organizations.Memberships.OrganizationMembership", b => + { + b.HasOne("EventHub.Organizations.Organization", null) + .WithMany() + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + + b.HasOne("Volo.Abp.Identity.IdentityUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.NoAction) + .IsRequired(); + }); + modelBuilder.Entity("EventHub.Organizations.Organization", b => { b.HasOne("Volo.Abp.Identity.IdentityUser", null) diff --git a/src/EventHub.EntityFrameworkCore/EntityFrameworkCore/EventHubDbContext.cs b/src/EventHub.EntityFrameworkCore/EntityFrameworkCore/EventHubDbContext.cs index 3e47805..d3e0023 100644 --- a/src/EventHub.EntityFrameworkCore/EntityFrameworkCore/EventHubDbContext.cs +++ b/src/EventHub.EntityFrameworkCore/EntityFrameworkCore/EventHubDbContext.cs @@ -1,6 +1,7 @@ using EventHub.Events; using EventHub.Events.Registrations; using EventHub.Organizations; +using EventHub.Organizations.Memberships; using Microsoft.EntityFrameworkCore; using EventHub.Users; using Volo.Abp.Data; @@ -25,6 +26,7 @@ namespace EventHub.EntityFrameworkCore { public DbSet Users { get; set; } public DbSet Organizations { get; set; } + public DbSet OrganizationMemberships { get; set; } public DbSet Events { get; set; } public DbSet EventRegistrations { get; set; } diff --git a/src/EventHub.EntityFrameworkCore/EntityFrameworkCore/EventHubDbContextModelCreatingExtensions.cs b/src/EventHub.EntityFrameworkCore/EntityFrameworkCore/EventHubDbContextModelCreatingExtensions.cs index 0714915..156ff68 100644 --- a/src/EventHub.EntityFrameworkCore/EntityFrameworkCore/EventHubDbContextModelCreatingExtensions.cs +++ b/src/EventHub.EntityFrameworkCore/EntityFrameworkCore/EventHubDbContextModelCreatingExtensions.cs @@ -1,6 +1,7 @@ using EventHub.Events; using EventHub.Events.Registrations; using EventHub.Organizations; +using EventHub.Organizations.Memberships; using Microsoft.EntityFrameworkCore; using Volo.Abp; using Volo.Abp.EntityFrameworkCore.Modeling; @@ -36,6 +37,22 @@ namespace EventHub.EntityFrameworkCore b.HasIndex(x => x.Name); b.HasIndex(x => x.DisplayName); }); + + builder.Entity(b => + { + b.ToTable(EventHubConsts.DbTablePrefix + "OrganizationMemberships", EventHubConsts.DbSchema); + + b.ConfigureByConvention(); + + b.HasOne().WithMany().HasForeignKey(x => x.OrganizationId).IsRequired().OnDelete(DeleteBehavior.NoAction); + + if (isMigrationDbContext) + { + b.HasOne().WithMany().HasForeignKey(x => x.UserId).IsRequired().OnDelete(DeleteBehavior.NoAction); + } + + b.HasIndex(x => new {x.OrganizationId, x.UserId}); + }); builder.Entity(b => { diff --git a/src/EventHub.Web/Controllers/OrganizationMembershipController.cs b/src/EventHub.Web/Controllers/OrganizationMembershipController.cs new file mode 100644 index 0000000..fd9e42c --- /dev/null +++ b/src/EventHub.Web/Controllers/OrganizationMembershipController.cs @@ -0,0 +1,42 @@ +using System; +using System.Threading.Tasks; +using EventHub.Organizations.Memberships; +using EventHub.Web.Pages.Organizations.Components.JoinArea; +using Microsoft.AspNetCore.Mvc; +using Volo.Abp.AspNetCore.Mvc; + +namespace EventHub.Web.Controllers +{ + public class OrganizationMembershipController : AbpController + { + private readonly IOrganizationMembershipAppService _organizationMembershipAppService; + + public OrganizationMembershipController(IOrganizationMembershipAppService organizationMembershipAppService) + { + _organizationMembershipAppService = organizationMembershipAppService; + } + + [HttpPost] + public async Task Join(Guid organizationId) + { + await _organizationMembershipAppService.JoinAsync(organizationId); + return NoContent(); + } + + [HttpPost] + public async Task Leave(Guid organizationId) + { + await _organizationMembershipAppService.LeaveAsync(organizationId); + return NoContent(); + } + + [HttpGet] + public IActionResult Widget(Guid organizationId) + { + return ViewComponent( + typeof(JoinAreaViewComponent), + new {organizationId} + ); + } + } +} \ No newline at end of file diff --git a/src/EventHub.Web/Controllers/WidgetsController.cs b/src/EventHub.Web/Controllers/WidgetsController.cs index 8cbd060..ab22f12 100644 --- a/src/EventHub.Web/Controllers/WidgetsController.cs +++ b/src/EventHub.Web/Controllers/WidgetsController.cs @@ -1,5 +1,6 @@ using System; using EventHub.Web.Pages.Events.Components.AttendeesArea; +using EventHub.Web.Pages.Organizations.Components.MembersArea; using Microsoft.AspNetCore.Mvc; using Volo.Abp.AspNetCore.Mvc; @@ -15,5 +16,14 @@ namespace EventHub.Web.Controllers new {eventId} ); } + + [HttpGet] + public IActionResult OrganizationMembersArea(Guid organizationId) + { + return ViewComponent( + typeof(MembersAreaViewComponent), + new {organizationId} + ); + } } } diff --git a/src/EventHub.Web/Pages/Organizations/Components/JoinArea/Default.cshtml b/src/EventHub.Web/Pages/Organizations/Components/JoinArea/Default.cshtml new file mode 100644 index 0000000..e86c846 --- /dev/null +++ b/src/EventHub.Web/Pages/Organizations/Components/JoinArea/Default.cshtml @@ -0,0 +1,34 @@ +@using EventHub.Localization +@using Microsoft.AspNetCore.Mvc.Localization +@inject IHtmlLocalizer L +@model EventHub.Web.Pages.Organizations.Components.JoinArea.JoinAreaViewComponent.MembershipAreaViewComponentModel + + + @if (Model.IsLoggedIn) + { + if (Model.IsJoined) + { + + } + else + { + + } + } + else + { + @L["LoginToRegister"] + } + + \ No newline at end of file diff --git a/src/EventHub.Web/Pages/Organizations/Components/JoinArea/JoinAreaViewComponent.cs b/src/EventHub.Web/Pages/Organizations/Components/JoinArea/JoinAreaViewComponent.cs new file mode 100644 index 0000000..12a1096 --- /dev/null +++ b/src/EventHub.Web/Pages/Organizations/Components/JoinArea/JoinAreaViewComponent.cs @@ -0,0 +1,52 @@ +using System; +using System.Threading.Tasks; +using EventHub.Organizations.Memberships; +using Microsoft.AspNetCore.Mvc; +using Volo.Abp.AspNetCore.Mvc; +using Volo.Abp.AspNetCore.Mvc.UI.Widgets; +using Volo.Abp.Users; + +namespace EventHub.Web.Pages.Organizations.Components.JoinArea +{ + [Widget( + AutoInitialize = true, + RefreshUrl = "/OrganizationMembership/Widget", + ScriptFiles = new[] {"/Pages/Organizations/Components/JoinArea/join-area.js"} + )] + public class JoinAreaViewComponent : AbpViewComponent + { + private readonly IOrganizationMembershipAppService _organizationMembershipAppService; + private readonly ICurrentUser _currentUser; + + public JoinAreaViewComponent( + IOrganizationMembershipAppService organizationMembershipAppService, + ICurrentUser currentUser) + { + _organizationMembershipAppService = organizationMembershipAppService; + _currentUser = currentUser; + } + + public async Task InvokeAsync(Guid organizationId) + { + var model = new MembershipAreaViewComponentModel + { + OrganizationId = organizationId, + IsLoggedIn = _currentUser.IsAuthenticated + }; + + if (model.IsLoggedIn) + { + model.IsJoined = await _organizationMembershipAppService.IsJoinedAsync(organizationId); + } + + return View("~/Pages/Organizations/Components/JoinArea/Default.cshtml", model); + } + + public class MembershipAreaViewComponentModel + { + public Guid OrganizationId { get; set; } + public bool IsLoggedIn { get; set; } + public bool IsJoined { get; set; } + } + } +} \ No newline at end of file diff --git a/src/EventHub.Web/Pages/Organizations/Components/JoinArea/join-area.js b/src/EventHub.Web/Pages/Organizations/Components/JoinArea/join-area.js new file mode 100644 index 0000000..a8eacdf --- /dev/null +++ b/src/EventHub.Web/Pages/Organizations/Components/JoinArea/join-area.js @@ -0,0 +1,51 @@ +(function () { + var l = abp.localization.getResource('EventHub'); + abp.widgets.JoinArea = function ($wrapper) { + + var widgetManager = $wrapper.data('abp-widget-manager'); + var organizationId = $wrapper.find('[data-organization-id]').attr('data-organization-id'); + + function getFilters() { + return { + organizationId: organizationId + }; + } + + function init() { + var joinButton = $wrapper.find('#OrganizationJoinButton'); + joinButton.click(function (e) { + e.preventDefault(); + joinButton.buttonBusy(true); + abp.ajax({ + url: joinButton.attr('data-url') + }).then(function (){ + widgetManager.refresh(); + abp.event.trigger('EventHub.Organization.JoinStatusChanged'); + abp.message.success(l('OrganizationJoinSuccessMessage'), l('OrganizationJoinSuccessMessageTitle')); + }).always(function (){ + joinButton.buttonBusy(false); + }); + }); + + var $leaveButton = $wrapper.find('#OrganizationLeaveButton'); + $leaveButton.click(function (e) { + e.preventDefault(); + $leaveButton.buttonBusy(true); + abp.ajax({ + url: $leaveButton.attr('data-url') + }).then(function (){ + widgetManager.refresh(); + abp.event.trigger('EventHub.Organization.JoinStatusChanged'); + abp.notify.info(l('OrganizationMembershipLeaveMessage')); + }).always(function (){ + $leaveButton.buttonBusy(false); + }); + }); + } + + return { + getFilters: getFilters, + init: init + }; + }; +})(); diff --git a/src/EventHub.Web/Pages/Organizations/Components/MembersArea/Default.cshtml b/src/EventHub.Web/Pages/Organizations/Components/MembersArea/Default.cshtml new file mode 100644 index 0000000..f8d6554 --- /dev/null +++ b/src/EventHub.Web/Pages/Organizations/Components/MembersArea/Default.cshtml @@ -0,0 +1,14 @@ +@model EventHub.Web.Pages.Organizations.Components.MembersArea.MembersAreaViewComponent.MembersAreaViewComponentModel + + + Members (@Model.TotalCount) + +
    + @foreach (var member in Model.Members) + { +
  • @Model.GetMemberName(member)
  • + } +
+
+
+
\ No newline at end of file diff --git a/src/EventHub.Web/Pages/Organizations/Components/MembersArea/MembersAreaViewComponent.cs b/src/EventHub.Web/Pages/Organizations/Components/MembersArea/MembersAreaViewComponent.cs new file mode 100644 index 0000000..739e2b1 --- /dev/null +++ b/src/EventHub.Web/Pages/Organizations/Components/MembersArea/MembersAreaViewComponent.cs @@ -0,0 +1,73 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; +using EventHub.Organizations.Memberships; +using Microsoft.AspNetCore.Mvc; +using Volo.Abp.AspNetCore.Mvc; +using Volo.Abp.AspNetCore.Mvc.UI.Widgets; + +namespace EventHub.Web.Pages.Organizations.Components.MembersArea +{ + [Widget( + AutoInitialize = true, + RefreshUrl = "/Widgets/OrganizationMembersArea", + ScriptFiles = new[] {"/Pages/Organizations/Components/MembersArea/members-area.js"}, + StyleFiles = new[] {"/Pages/Organizations/Components/MembersArea/members-area.css"} + )] + public class MembersAreaViewComponent : AbpViewComponent + { + private readonly IOrganizationMembershipAppService _organizationMembershipAppService; + + public MembersAreaViewComponent(IOrganizationMembershipAppService organizationMembershipAppService) + { + _organizationMembershipAppService = organizationMembershipAppService; + } + + public async Task InvokeAsync(Guid organizationId) + { + var result = await _organizationMembershipAppService.GetMembersAsync(organizationId); + + return View( + "~/Pages/Organizations/Components/MembersArea/Default.cshtml", + new MembersAreaViewComponentModel + { + OrganizationId = organizationId, + Members = result.Items, + TotalCount = result.TotalCount + } + ); + } + + public class MembersAreaViewComponentModel + { + public IReadOnlyList Members { get; set; } + + public long TotalCount { get; set; } + + public Guid OrganizationId { get; set; } + + public string GetMemberName(OrganizationMemberDto member) + { + var nameBuilder = new StringBuilder(); + + if (!member.Name.IsNullOrEmpty()) + { + nameBuilder.Append(member.Name); + } + + if (!member.Surname.IsNullOrEmpty()) + { + nameBuilder.Append(member.Surname); + } + + if (nameBuilder.Length == 0) + { + nameBuilder.Append(member.UserName); + } + + return nameBuilder.ToString(); + } + } + } +} \ No newline at end of file diff --git a/src/EventHub.Web/Pages/Organizations/Components/MembersArea/members-area.css b/src/EventHub.Web/Pages/Organizations/Components/MembersArea/members-area.css new file mode 100644 index 0000000..135beab --- /dev/null +++ b/src/EventHub.Web/Pages/Organizations/Components/MembersArea/members-area.css @@ -0,0 +1,5 @@ +#OrganizationMemberList +{ + list-style: none; + padding: 0; +} diff --git a/src/EventHub.Web/Pages/Organizations/Components/MembersArea/members-area.js b/src/EventHub.Web/Pages/Organizations/Components/MembersArea/members-area.js new file mode 100644 index 0000000..c8014c8 --- /dev/null +++ b/src/EventHub.Web/Pages/Organizations/Components/MembersArea/members-area.js @@ -0,0 +1,18 @@ +(function () { + abp.widgets.MembersArea = function ($wrapper) { + var organizationId = $wrapper.find('[data-organization-id]').attr('data-organization-id'); + return { + getFilters: function () { + return { + organizationId: organizationId + }; + } + }; + }; + + abp.event.on("EventHub.Organization.JoinStatusChanged", function(){ + $('[data-widget-name="MembersArea"]') + .data('abp-widget-manager') + .refresh(); + }); +})(); diff --git a/src/EventHub.Web/Pages/Organizations/Profile.cshtml b/src/EventHub.Web/Pages/Organizations/Profile.cshtml index e1f535a..817437e 100644 --- a/src/EventHub.Web/Pages/Organizations/Profile.cshtml +++ b/src/EventHub.Web/Pages/Organizations/Profile.cshtml @@ -2,78 +2,89 @@ @inject IHtmlLocalizer L @using EventHub.Localization @using EventHub.Web.Pages.Events +@using EventHub.Web.Pages.Organizations.Components.JoinArea +@using EventHub.Web.Pages.Organizations.Components.MembersArea @using Microsoft.AspNetCore.Mvc.Localization @model EventHub.Web.Pages.Organizations.ProfilePageModel + - - - @Model.Organization.DisplayName - - -

@Model.Organization.DisplayName

-
- - @Model.Organization.Description - -
-
+ + + + + @Model.Organization.DisplayName + + +

@Model.Organization.DisplayName

+
+ + @Model.Organization.Description + +
+
+
+
+ + @if (Model.UpcomingEvents.Any()) + { +

Events

+ + + + + @foreach (var eventItem in Model.UpcomingEvents) + { + + + @eventItem.Title + + @eventItem.Title + + @EventDateHelper.GetDateRangeText(eventItem.StartTime, eventItem.EndTime) + + + @eventItem.Description.TruncateWithPostfix(100) + + @L["SeeEvent"] + + + + } + + + + + @foreach (var eventItem in Model.PastEvents) + { + + + @eventItem.Title + + @eventItem.Title + + @EventDateHelper.GetDateRangeText(eventItem.StartTime, eventItem.EndTime) + + + @eventItem.Description.TruncateWithPostfix(100) + + @L["SeeEvent"] + + + + } + + + + } + else + { + + @L["NoEventOrganizedByThisOrganizationYet"] + + } +
+ + @await Component.InvokeAsync(typeof(JoinAreaViewComponent), new {organizationId = Model.Organization.Id}) + @await Component.InvokeAsync(typeof(MembersAreaViewComponent), new {organizationId = Model.Organization.Id})
- -@if (Model.UpcomingEvents.Any()) -{ -

Events

- - - - - @foreach (var eventItem in Model.UpcomingEvents) - { - - - @eventItem.Title - - @eventItem.Title - - @EventDateHelper.GetDateRangeText(eventItem.StartTime, eventItem.EndTime) - - - @eventItem.Description.TruncateWithPostfix(100) - - @L["SeeEvent"] - - - - } - - - - - @foreach (var eventItem in Model.PastEvents) - { - - - @eventItem.Title - - @eventItem.Title - - @EventDateHelper.GetDateRangeText(eventItem.StartTime, eventItem.EndTime) - - - @eventItem.Description.TruncateWithPostfix(100) - - @L["SeeEvent"] - - - - } - - - -} -else -{ - - @L["NoEventOrganizedByThisOrganizationYet"] - -} diff --git a/test/EventHub.Application.Tests/Organizations/Memberships/OrganizationMembershipAppServiceTests.cs b/test/EventHub.Application.Tests/Organizations/Memberships/OrganizationMembershipAppServiceTests.cs new file mode 100644 index 0000000..75d6f29 --- /dev/null +++ b/test/EventHub.Application.Tests/Organizations/Memberships/OrganizationMembershipAppServiceTests.cs @@ -0,0 +1,101 @@ +using System; +using System.Threading.Tasks; +using Shouldly; +using Volo.Abp.Domain.Repositories; +using Volo.Abp.Users; +using Xunit; + +namespace EventHub.Organizations.Memberships +{ + public class OrganizationMembershipAppServiceTests : EventHubApplicationTestBase + { + private readonly IOrganizationMembershipAppService _organizationMembershipAppService; + private readonly IRepository _organizationMembershipRepository; + private readonly EventHubTestData _testData; + private readonly ICurrentUser _currentUser; + + public OrganizationMembershipAppServiceTests() + { + _organizationMembershipAppService = GetRequiredService(); + _organizationMembershipRepository = GetRequiredService>(); + _testData = GetRequiredService(); + _currentUser = GetRequiredService(); + } + + [Fact] + public async Task Should_Join_To_An_Organization() + { + await _organizationMembershipAppService.JoinAsync( + _testData.OrganizationVolosoftId + ); + + (await GetMembershipOrNull( + _testData.OrganizationVolosoftId, + _currentUser.GetId() + )).ShouldNotBeNull(); + } + + [Fact] + public async Task Should_Leave_From_An_Organization() + { + await WithUnitOfWorkAsync(async () => + { + await _organizationMembershipRepository.InsertAsync( + new OrganizationMembership( + Guid.NewGuid(), + _testData.OrganizationDotnetEuropeId, + _currentUser.GetId() + ) + ); + }); + + await _organizationMembershipAppService.LeaveAsync( + _testData.OrganizationDotnetEuropeId + ); + + (await GetMembershipOrNull( + _testData.OrganizationDotnetEuropeId, + _currentUser.GetId()) + ).ShouldBeNull(); + } + + [Fact] + public async Task Should_Get_List_Of_Members() + { + await WithUnitOfWorkAsync(async () => + { + await _organizationMembershipRepository.InsertAsync( + new OrganizationMembership( + Guid.NewGuid(), + _testData.OrganizationVolosoftId, + _testData.UserAdminId + ) + ); + + await _organizationMembershipRepository.InsertAsync( + new OrganizationMembership( + Guid.NewGuid(), + _testData.OrganizationVolosoftId, + _testData.UserJohnId + ) + ); + }); + + var result = await _organizationMembershipAppService.GetMembersAsync(_testData.OrganizationVolosoftId); + + result.TotalCount.ShouldBeGreaterThanOrEqualTo(2); + result.Items.ShouldContain(x => x.Id == _testData.UserAdminId); + result.Items.ShouldContain(x => x.Id == _testData.UserJohnId); + } + + private async Task GetMembershipOrNull(Guid organizationId, Guid userId) + { + return await WithUnitOfWorkAsync(async () => + { + return await _organizationMembershipRepository.FirstOrDefaultAsync( + x => x.OrganizationId == organizationId && x.UserId == userId + ); + }); + } + } +} \ No newline at end of file diff --git a/test/EventHub.Domain.Tests/Organizations/Memberships/OrganizationMembershipManagerTests.cs b/test/EventHub.Domain.Tests/Organizations/Memberships/OrganizationMembershipManagerTests.cs new file mode 100644 index 0000000..7929927 --- /dev/null +++ b/test/EventHub.Domain.Tests/Organizations/Memberships/OrganizationMembershipManagerTests.cs @@ -0,0 +1,71 @@ +using System; +using System.Threading.Tasks; +using Shouldly; +using Volo.Abp.Domain.Repositories; +using Xunit; + +namespace EventHub.Organizations.Memberships +{ + public class OrganizationMembershipManagerTests : EventHubDomainTestBase + { + private readonly OrganizationMembershipManager _organizationMembershipManager; + private readonly IRepository _organizationMembershipRepository; + private readonly EventHubTestData _testData; + + public OrganizationMembershipManagerTests() + { + _organizationMembershipManager = GetRequiredService(); + _organizationMembershipRepository = GetRequiredService>(); + _testData = GetRequiredService(); + } + + [Fact] + public async Task Should_Join_To_An_Organization() + { + await WithUnitOfWorkAsync(async () => + { + var user = await GetUserAsync(_testData.UserAdminId); + var organization = await GetOrganizationAsync(_testData.OrganizationVolosoftName); + await _organizationMembershipManager.JoinAsync(organization, user); + }); + + (await GetMembershipOrNull(_testData.OrganizationVolosoftId, _testData.UserAdminId)) + .ShouldNotBeNull(); + } + + [Fact] + public async Task Should_Leave_From_An_Organization() + { + await WithUnitOfWorkAsync(async () => + { + await _organizationMembershipRepository.InsertAsync( + new OrganizationMembership( + Guid.NewGuid(), + _testData.OrganizationVolosoftId, + _testData.UserAdminId + ) + ); + }); + + await WithUnitOfWorkAsync(async () => + { + var user = await GetUserAsync(_testData.UserAdminId); + var organization = await GetOrganizationAsync(_testData.OrganizationVolosoftName); + await _organizationMembershipManager.LeaveAsync(organization, user); + }); + + (await GetMembershipOrNull(_testData.OrganizationVolosoftId, _testData.UserAdminId)) + .ShouldBeNull(); + } + + private async Task GetMembershipOrNull(Guid organizationId, Guid userId) + { + return await WithUnitOfWorkAsync(async () => + { + return await _organizationMembershipRepository.FirstOrDefaultAsync( + x => x.OrganizationId == organizationId && x.UserId == userId + ); + }); + } + } +} \ No newline at end of file