Browse Source

Merge branch 'dev' into EntityCacheBase

pull/19394/head
maliming 3 years ago
parent
commit
ae4d2cd9d3
No known key found for this signature in database GPG Key ID: A646B9CB645ECEA4
  1. 1
      Directory.Packages.props
  2. 16
      abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json
  3. 16
      abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/tr.json
  4. 7
      framework/Volo.Abp.sln
  5. 3
      framework/src/Volo.Abp.AspNetCore.Abstractions/FodyWeavers.xml
  6. 30
      framework/src/Volo.Abp.AspNetCore.Abstractions/FodyWeavers.xsd
  7. 23
      framework/src/Volo.Abp.AspNetCore.Abstractions/Volo.Abp.AspNetCore.Abstractions.csproj
  8. 15
      framework/src/Volo.Abp.AspNetCore.Abstractions/Volo/Abp/AspNetCore/AbpAspNetCoreAbstractionsModule.cs
  9. 0
      framework/src/Volo.Abp.AspNetCore.Abstractions/Volo/Abp/AspNetCore/Filters/IAbpFilter.cs
  10. 0
      framework/src/Volo.Abp.AspNetCore.Abstractions/Volo/Abp/AspNetCore/VirtualFileSystem/IWebContentFileProvider.cs
  11. 22
      framework/src/Volo.Abp.AspNetCore.Abstractions/Volo/Abp/AspNetCore/VirtualFileSystem/NullWebContentFileProvider.cs
  12. 2
      framework/src/Volo.Abp.AspNetCore.Abstractions/Volo/Abp/AspNetCore/WebClientInfo/IWebClientInfoProvider.cs
  13. 10
      framework/src/Volo.Abp.AspNetCore.Abstractions/Volo/Abp/AspNetCore/WebClientInfo/NullWebClientInfoProvider.cs
  14. 27
      framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Bundling/AbpScripts.razor
  15. 29
      framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Bundling/AbpStyles.razor
  16. 2
      framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/Volo/Abp/AspNetCore/Mvc/Client/MvcCachedApplicationConfigurationClientHelper.cs
  17. 11
      framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/Volo/Abp/AspNetCore/Mvc/Client/RemoteDynamicClaimsPrincipalContributorCache.cs
  18. 2
      framework/src/Volo.Abp.AspNetCore/Volo.Abp.AspNetCore.csproj
  19. 3
      framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/AbpAspNetCoreModule.cs
  20. 20
      framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Security/Claims/AbpDynamicClaimsMiddleware.cs
  21. 1
      framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/VirtualFileSystem/WebContentFileProvider.cs
  22. 30
      framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/WebClientInfo/HttpContextWebClientInfoProvider.cs
  23. 2
      framework/src/Volo.Abp.Http/Volo/Abp/Http/Modeling/ApplicationApiDescriptionModel.cs
  24. 28
      framework/src/Volo.Abp.Security/System/Security/Principal/AbpClaimsIdentityExtensions.cs
  25. 5
      framework/src/Volo.Abp.Security/Volo/Abp/Security/Claims/AbpClaimTypes.cs
  26. 12
      framework/src/Volo.Abp.Security/Volo/Abp/Users/CurrentUserExtensions.cs
  27. 5
      framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/ar.json
  28. 5
      framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/cs.json
  29. 5
      framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/de.json
  30. 7
      framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/el.json
  31. 5
      framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/en-GB.json
  32. 3
      framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/en.json
  33. 5
      framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/es.json
  34. 3
      framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/fa.json
  35. 5
      framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/fi.json
  36. 5
      framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/fr.json
  37. 5
      framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/hi.json
  38. 5
      framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/hr.json
  39. 5
      framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/hu.json
  40. 5
      framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/is.json
  41. 5
      framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/it.json
  42. 5
      framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/nl.json
  43. 5
      framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/pl-PL.json
  44. 5
      framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/pt-BR.json
  45. 5
      framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/ro-RO.json
  46. 5
      framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/ru.json
  47. 5
      framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/sk.json
  48. 5
      framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/sl.json
  49. 3
      framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/tr.json
  50. 5
      framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/vi.json
  51. 5
      framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/zh-Hans.json
  52. 5
      framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/zh-Hant.json
  53. 6
      modules/docs/src/Volo.Docs.Admin.Application/Volo/Docs/Admin/Documents/DocumentAdminAppService.cs
  54. 2
      modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/DocumentWithoutDetails.cs
  55. 3
      modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/IDocumentRepository.cs
  56. 7
      modules/docs/src/Volo.Docs.EntityFrameworkCore/Volo/Docs/Documents/EFCoreDocumentRepository.cs
  57. 14
      modules/docs/src/Volo.Docs.MongoDB/Volo/Docs/Documents/MongoDocumentRepository.cs
  58. 11
      modules/docs/test/Volo.Docs.TestBase/Volo/Docs/DocumentRepository_Tests.cs
  59. 14
      modules/identity/src/Volo.Abp.Identity.AspNetCore/Volo/Abp/Identity/AspNetCore/AbpIdentityAspNetCoreModule.cs
  60. 17
      modules/identity/src/Volo.Abp.Identity.AspNetCore/Volo/Abp/Identity/AspNetCore/AbpRefreshingPrincipalOptions.cs
  61. 17
      modules/identity/src/Volo.Abp.Identity.AspNetCore/Volo/Abp/Identity/AspNetCore/AbpSecurityStampValidatorCallback.cs
  62. 4
      modules/identity/src/Volo.Abp.Identity.AspNetCore/Volo/Abp/Identity/AspNetCore/SecurityStampValidatorOptionsExtensions.cs
  63. 14
      modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/IdentitySessionConsts.cs
  64. 10
      modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/IdentitySessionDevices.cs
  65. 2
      modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IIdentitySecurityLogRepository.cs
  66. 35
      modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IIdentitySessionRepository.cs
  67. 90
      modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentitySession.cs
  68. 3
      modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/AbpIdentityEntityFrameworkCoreModule.cs
  69. 6
      modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreIdentitySecurityLogRepository.cs
  70. 85
      modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreIdentitySessionRepository.cs
  71. 2
      modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IIdentityDbContext.cs
  72. 2
      modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IdentityDbContext.cs
  73. 19
      modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IdentityDbContextModelBuilderExtensions.cs
  74. 2
      modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/AbpIdentityMongoDbContext.cs
  75. 5
      modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/AbpIdentityMongoDbContextExtensions.cs
  76. 1
      modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/AbpIdentityMongoDbModule.cs
  77. 2
      modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/IAbpIdentityMongoDbContext.cs
  78. 2
      modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentitySecurityLogRepository.cs
  79. 90
      modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentitySessionRepository.cs
  80. 6
      modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/Claims/AbpDefaultOpenIddictClaimsPrincipalHandler.cs
  81. 6
      npm/ng-packs/packages/account-core/ng-package.json
  82. 6
      npm/ng-packs/packages/account-core/package.json
  83. 31
      npm/ng-packs/packages/account/src/lib/components/personal-settings/personal-settings.component.ts
  84. 2
      npm/ng-packs/packages/components/extensible/src/lib/components/extensible-table/extensible-table.component.html
  85. 74
      npm/ng-packs/packages/components/extensible/src/lib/components/extensible-table/extensible-table.component.ts
  86. 17
      npm/ng-packs/packages/feature-management/src/lib/components/feature-management/feature-management.component.ts
  87. 21
      npm/ng-packs/packages/identity/src/lib/components/roles/roles.component.ts
  88. 36
      npm/ng-packs/packages/identity/src/lib/components/users/users.component.ts
  89. 48
      npm/ng-packs/packages/permission-management/src/lib/components/permission-management.component.ts
  90. 23
      npm/ng-packs/packages/tenant-management/src/lib/components/tenants/tenants.component.ts
  91. 99
      npm/ng-packs/packages/theme-shared/src/lib/directives/ngx-datatable-list.directive.ts
  92. 2
      npm/ng-packs/packages/theme-shared/src/lib/services/create-error-component.service.ts
  93. 1
      nupkg/common.ps1
  94. 54
      templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/20240312033651_Initial.Designer.cs
  95. 38
      templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/20240312033651_Initial.cs
  96. 52
      templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/MyProjectNameDbContextModelSnapshot.cs
  97. 54
      templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20240312033906_Initial.Designer.cs
  98. 67
      templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20240312033906_Initial.cs
  99. 52
      templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/MyProjectNameDbContextModelSnapshot.cs
  100. 54
      templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/20240321011533_Initial.Designer.cs

1
Directory.Packages.props

@ -27,6 +27,7 @@
<PackageVersion Include="Dapper" Version="2.1.21" /> <PackageVersion Include="Dapper" Version="2.1.21" />
<PackageVersion Include="Dapr.AspNetCore" Version="1.12.0" /> <PackageVersion Include="Dapr.AspNetCore" Version="1.12.0" />
<PackageVersion Include="Dapr.Client" Version="1.12.0" /> <PackageVersion Include="Dapr.Client" Version="1.12.0" />
<PackageVersion Include="DeviceDetector.NET" Version="6.1.4" />
<PackageVersion Include="Devart.Data.Oracle.EFCore" Version="10.3.10.8" /> <PackageVersion Include="Devart.Data.Oracle.EFCore" Version="10.3.10.8" />
<PackageVersion Include="DistributedLock.Core" Version="1.0.5" /> <PackageVersion Include="DistributedLock.Core" Version="1.0.5" />
<PackageVersion Include="DistributedLock.Redis" Version="1.0.2" /> <PackageVersion Include="DistributedLock.Redis" Version="1.0.2" />

16
abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/en.json

@ -602,9 +602,21 @@
"ProductCount": "Product Count", "ProductCount": "Product Count",
"Actions": "Actions", "Actions": "Actions",
"CreateInvoice": "Create Invoice", "CreateInvoice": "Create Invoice",
"IsVisible": "Visible",
"Menu:Testimonials": "Testimonials",
"TestimonialDeletionConfirmationMessage": "Are you sure you want to delete this testimonial ?",
"FullName": "Full name",
"TestimonialText": "Testimonial text",
"ExperienceYear": "Experience year",
"Position": "Title",
"YearsOfExperience": "Experience year",
"AllowedLicenses": "Allowed Licenses", "AllowedLicenses": "Allowed Licenses",
"AllowedModules": "Allowed Modules", "AllowedModules": "Allowed Modules",
"ModuleName": "Module name", "ModuleName": "Module name",
"NonYet": "Non yet" "NonYet": "Non yet",
"Permission:Testimonials": "Testimonials",
"SelectCompanySizePlaceholder": "Company Size",
"SelectExperienceYearPlaceholder": "Experience year",
"SelectCountryPlaceholder": "Country"
} }
} }

16
abp_io/AbpIoLocalization/AbpIoLocalization/Admin/Localization/Resources/tr.json

@ -443,6 +443,18 @@
"QuotationTemplate.Tax/VAT:": "Vergiler (%{0}) :", "QuotationTemplate.Tax/VAT:": "Vergiler (%{0}) :",
"QuotationTemplate.TotalDiscount:": "Toplam İndirim :", "QuotationTemplate.TotalDiscount:": "Toplam İndirim :",
"QuotationTemplate.TOTALDUE:": "NET TOPLAM :", "QuotationTemplate.TOTALDUE:": "NET TOPLAM :",
"QuotationTemplate.BankAccount": "Banka hesabı bilgilerimiz {0} adresinde bulunabilir." "QuotationTemplate.BankAccount": "Banka hesap bilgilerimize {0} adresinden erişebilirsiniz.",
"Menu:Testimonials": "Referanslar",
"IsVisible": "Görünürlük",
"TestimonialDeletionConfirmationMessage": "Bu referansı silmek istediğinize emin misiniz ?",
"FullName": "Ad soyad",
"TestimonialText": "Tecrübe yazısı",
"ExperienceYear": "Sektörel deneyim",
"Position": "Başlık",
"Actions": "İşlemler",
"Permission:Testimonials": "Referanslar",
"SelectCompanySizePlaceholder": "Şirket Büyüklüğü",
"SelectExperienceYearPlaceholder": "Sektörel deneyim",
"SelectCountryPlaceholder": "Ülke"
} }
} }

7
framework/Volo.Abp.sln

@ -465,6 +465,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Imaging.SkiaSharp.
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.RemoteServices.Tests", "test\Volo.Abp.RemoteServices.Tests\Volo.Abp.RemoteServices.Tests.csproj", "{DACD4485-61BE-4DE5-ACAE-4FFABC122500}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.RemoteServices.Tests", "test\Volo.Abp.RemoteServices.Tests\Volo.Abp.RemoteServices.Tests.csproj", "{DACD4485-61BE-4DE5-ACAE-4FFABC122500}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.AspNetCore.Abstractions", "src\Volo.Abp.AspNetCore.Abstractions\Volo.Abp.AspNetCore.Abstractions.csproj", "{E1051CD0-9262-4869-832D-B951723F4DDE}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
@ -1387,6 +1389,10 @@ Global
{DACD4485-61BE-4DE5-ACAE-4FFABC122500}.Debug|Any CPU.Build.0 = Debug|Any CPU {DACD4485-61BE-4DE5-ACAE-4FFABC122500}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DACD4485-61BE-4DE5-ACAE-4FFABC122500}.Release|Any CPU.ActiveCfg = Release|Any CPU {DACD4485-61BE-4DE5-ACAE-4FFABC122500}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DACD4485-61BE-4DE5-ACAE-4FFABC122500}.Release|Any CPU.Build.0 = Release|Any CPU {DACD4485-61BE-4DE5-ACAE-4FFABC122500}.Release|Any CPU.Build.0 = Release|Any CPU
{E1051CD0-9262-4869-832D-B951723F4DDE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E1051CD0-9262-4869-832D-B951723F4DDE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E1051CD0-9262-4869-832D-B951723F4DDE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E1051CD0-9262-4869-832D-B951723F4DDE}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
@ -1621,6 +1627,7 @@ Global
{198683D0-7DC6-40F2-B81B-8E446E70A9DE} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6} {198683D0-7DC6-40F2-B81B-8E446E70A9DE} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
{DFAF8763-D1D6-4EB4-B459-20E31007FE2F} = {447C8A77-E5F0-4538-8687-7383196D04EA} {DFAF8763-D1D6-4EB4-B459-20E31007FE2F} = {447C8A77-E5F0-4538-8687-7383196D04EA}
{DACD4485-61BE-4DE5-ACAE-4FFABC122500} = {447C8A77-E5F0-4538-8687-7383196D04EA} {DACD4485-61BE-4DE5-ACAE-4FFABC122500} = {447C8A77-E5F0-4538-8687-7383196D04EA}
{E1051CD0-9262-4869-832D-B951723F4DDE} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
EndGlobalSection EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {BB97ECF4-9A84-433F-A80B-2A3285BDD1D5} SolutionGuid = {BB97ECF4-9A84-433F-A80B-2A3285BDD1D5}

3
framework/src/Volo.Abp.AspNetCore.Abstractions/FodyWeavers.xml

@ -0,0 +1,3 @@
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<ConfigureAwait ContinueOnCapturedContext="false" />
</Weavers>

30
framework/src/Volo.Abp.AspNetCore.Abstractions/FodyWeavers.xsd

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. -->
<xs:element name="Weavers">
<xs:complexType>
<xs:all>
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" />
</xs:complexType>
</xs:element>
</xs:all>
<xs:attribute name="VerifyAssembly" type="xs:boolean">
<xs:annotation>
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="VerifyIgnoreCodes" type="xs:string">
<xs:annotation>
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="GenerateXsd" type="xs:boolean">
<xs:annotation>
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
</xs:element>
</xs:schema>

23
framework/src/Volo.Abp.AspNetCore.Abstractions/Volo.Abp.AspNetCore.Abstractions.csproj

@ -0,0 +1,23 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\configureawait.props" />
<Import Project="..\..\..\common.props" />
<PropertyGroup>
<TargetFrameworks>netstandard2.0;netstandard2.1;net8.0</TargetFrameworks>
<Nullable>enable</Nullable>
<WarningsAsErrors>Nullable</WarningsAsErrors>
<AssemblyName>Volo.Abp.AspNetCore.Abstractions</AssemblyName>
<PackageId>Volo.Abp.AspNetCore.Abstractions</PackageId>
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Volo.Abp.Core\Volo.Abp.Core.csproj" />
</ItemGroup>
</Project>

15
framework/src/Volo.Abp.AspNetCore.Abstractions/Volo/Abp/AspNetCore/AbpAspNetCoreAbstractionsModule.cs

@ -0,0 +1,15 @@
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.AspNetCore.VirtualFileSystem;
using Volo.Abp.AspNetCore.WebClientInfo;
using Volo.Abp.Modularity;
namespace Volo.Abp.AspNetCore;
public class AbpAspNetCoreAbstractionsModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
context.Services.AddSingleton<IWebContentFileProvider, NullWebContentFileProvider>();
context.Services.AddSingleton<IWebClientInfoProvider, NullWebClientInfoProvider>();;
}
}

0
framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Filters/IAbpFilter.cs → framework/src/Volo.Abp.AspNetCore.Abstractions/Volo/Abp/AspNetCore/Filters/IAbpFilter.cs

0
framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/VirtualFileSystem/IWebContentFileProvider.cs → framework/src/Volo.Abp.AspNetCore.Abstractions/Volo/Abp/AspNetCore/VirtualFileSystem/IWebContentFileProvider.cs

22
framework/src/Volo.Abp.AspNetCore.Abstractions/Volo/Abp/AspNetCore/VirtualFileSystem/NullWebContentFileProvider.cs

@ -0,0 +1,22 @@
using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Primitives;
namespace Volo.Abp.AspNetCore.VirtualFileSystem;
public class NullWebContentFileProvider : IWebContentFileProvider
{
public virtual IFileInfo GetFileInfo(string subpath)
{
return new NotFoundFileInfo(subpath);
}
public virtual IDirectoryContents GetDirectoryContents(string subpath)
{
return new NotFoundDirectoryContents();
}
public virtual IChangeToken Watch(string filter)
{
return NullChangeToken.Singleton;
}
}

2
framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/WebClientInfo/IWebClientInfoProvider.cs → framework/src/Volo.Abp.AspNetCore.Abstractions/Volo/Abp/AspNetCore/WebClientInfo/IWebClientInfoProvider.cs

@ -5,4 +5,6 @@ public interface IWebClientInfoProvider
string? BrowserInfo { get; } string? BrowserInfo { get; }
string? ClientIpAddress { get; } string? ClientIpAddress { get; }
string? DeviceInfo { get; }
} }

10
framework/src/Volo.Abp.AspNetCore.Abstractions/Volo/Abp/AspNetCore/WebClientInfo/NullWebClientInfoProvider.cs

@ -0,0 +1,10 @@
namespace Volo.Abp.AspNetCore.WebClientInfo;
public class NullWebClientInfoProvider : IWebClientInfoProvider
{
public virtual string? BrowserInfo { get; }
public virtual string? ClientIpAddress { get; }
public virtual string? DeviceInfo { get; }
}

27
framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Bundling/AbpScripts.razor

@ -1,5 +1,7 @@
@using Volo.Abp @using Volo.Abp
@implements IDisposable
@inject IComponentBundleManager BundleManager @inject IComponentBundleManager BundleManager
@inject PersistentComponentState PersistentComponentState
@if (ScriptFiles != null) @if (ScriptFiles != null)
{ {
@ -18,16 +20,37 @@
private List<string>? ScriptFiles { get; set; } private List<string>? ScriptFiles { get; set; }
private PersistingComponentStateSubscription persistingSubscription;
protected override async Task OnInitializedAsync() protected override async Task OnInitializedAsync()
{ {
if (BundleName == null) if (BundleName == null)
{ {
throw new AbpException("The BundleName parameter of the AbpScripts component can not be null!"); throw new AbpException("The BundleName parameter of the AbpScripts component can not be null!");
} }
ScriptFiles = (await BundleManager.GetScriptBundleFilesAsync(BundleName!)).ToList();
persistingSubscription = PersistentComponentState.RegisterOnPersisting(PersistScriptFiles);
if (PersistentComponentState.TryTakeFromJson<List<string>>(nameof(ScriptFiles), out var restoredStyleFiles))
{
ScriptFiles = restoredStyleFiles;
}
else
{
ScriptFiles = (await BundleManager.GetScriptBundleFilesAsync(BundleName!)).ToList();
}
if (OperatingSystem.IsBrowser() && WebAssemblyScriptFiles != null) if (OperatingSystem.IsBrowser() && WebAssemblyScriptFiles != null)
{ {
ScriptFiles.AddRange(WebAssemblyScriptFiles); ScriptFiles?.AddRange(WebAssemblyScriptFiles);
} }
} }
private Task PersistScriptFiles()
{
PersistentComponentState.PersistAsJson(nameof(ScriptFiles), ScriptFiles);
return Task.CompletedTask;
}
public void Dispose() => persistingSubscription.Dispose();
} }

29
framework/src/Volo.Abp.AspNetCore.Components.Web.Theming/Bundling/AbpStyles.razor

@ -1,11 +1,13 @@
@using Volo.Abp @using Volo.Abp
@implements IDisposable
@inject IComponentBundleManager BundleManager @inject IComponentBundleManager BundleManager
@inject PersistentComponentState PersistentComponentState
@if (StyleFiles != null) @if (StyleFiles != null)
{ {
foreach (var file in StyleFiles) foreach (var file in StyleFiles)
{ {
<link rel="stylesheet" href="@file"/> <link rel="stylesheet" href="@file" />
} }
} }
@ -18,16 +20,37 @@
private List<string>? StyleFiles { get; set; } private List<string>? StyleFiles { get; set; }
private PersistingComponentStateSubscription persistingSubscription;
protected override async Task OnInitializedAsync() protected override async Task OnInitializedAsync()
{ {
if (BundleName == null) if (BundleName == null)
{ {
throw new AbpException("The BundleName parameter of the AbpStyles component can not be null!"); throw new AbpException("The BundleName parameter of the AbpStyles component can not be null!");
} }
StyleFiles = (await BundleManager.GetStyleBundleFilesAsync(BundleName!)).ToList();
persistingSubscription = PersistentComponentState.RegisterOnPersisting(PersistStyleFiles);
if (PersistentComponentState.TryTakeFromJson<List<string>>(nameof(StyleFiles), out var restoredStyleFiles))
{
StyleFiles = restoredStyleFiles;
}
else
{
StyleFiles = (await BundleManager.GetStyleBundleFilesAsync(BundleName!)).ToList();
}
if (OperatingSystem.IsBrowser() && WebAssemblyStyleFiles != null) if (OperatingSystem.IsBrowser() && WebAssemblyStyleFiles != null)
{ {
StyleFiles.AddRange(WebAssemblyStyleFiles); StyleFiles?.AddRange(WebAssemblyStyleFiles);
} }
} }
private Task PersistStyleFiles()
{
PersistentComponentState.PersistAsJson(nameof(StyleFiles), StyleFiles);
return Task.CompletedTask;
}
public void Dispose() => persistingSubscription.Dispose();
} }

2
framework/src/Volo.Abp.AspNetCore.Mvc.Client/Volo/Abp/AspNetCore/Mvc/Client/MvcCachedApplicationConfigurationClientHelper.cs → framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/Volo/Abp/AspNetCore/Mvc/Client/MvcCachedApplicationConfigurationClientHelper.cs

@ -3,7 +3,7 @@ using Volo.Abp.Users;
namespace Volo.Abp.AspNetCore.Mvc.Client; namespace Volo.Abp.AspNetCore.Mvc.Client;
internal static class MvcCachedApplicationConfigurationClientHelper public static class MvcCachedApplicationConfigurationClientHelper
{ {
public static string CreateCacheKey(ICurrentUser currentUser) public static string CreateCacheKey(ICurrentUser currentUser)
{ {

11
framework/src/Volo.Abp.AspNetCore.Mvc.Client.Common/Volo/Abp/AspNetCore/Mvc/Client/RemoteDynamicClaimsPrincipalContributorCache.cs

@ -4,10 +4,12 @@ using System.Net.Http;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations;
using Volo.Abp.Caching; using Volo.Abp.Caching;
using Volo.Abp.Http.Client; using Volo.Abp.Http.Client;
using Volo.Abp.Http.Client.Authentication; using Volo.Abp.Http.Client.Authentication;
using Volo.Abp.Security.Claims; using Volo.Abp.Security.Claims;
using Volo.Abp.Users;
namespace Volo.Abp.AspNetCore.Mvc.Client; namespace Volo.Abp.AspNetCore.Mvc.Client;
@ -18,17 +20,23 @@ public class RemoteDynamicClaimsPrincipalContributorCache : RemoteDynamicClaimsP
protected IDistributedCache<AbpDynamicClaimCacheItem> Cache { get; } protected IDistributedCache<AbpDynamicClaimCacheItem> Cache { get; }
protected IHttpClientFactory HttpClientFactory { get; } protected IHttpClientFactory HttpClientFactory { get; }
protected IRemoteServiceHttpClientAuthenticator HttpClientAuthenticator { get; } protected IRemoteServiceHttpClientAuthenticator HttpClientAuthenticator { get; }
protected IDistributedCache<ApplicationConfigurationDto> ApplicationConfigurationDtoCache { get; }
protected ICurrentUser CurrentUser { get; }
public RemoteDynamicClaimsPrincipalContributorCache( public RemoteDynamicClaimsPrincipalContributorCache(
IDistributedCache<AbpDynamicClaimCacheItem> cache, IDistributedCache<AbpDynamicClaimCacheItem> cache,
IHttpClientFactory httpClientFactory, IHttpClientFactory httpClientFactory,
IOptions<AbpClaimsPrincipalFactoryOptions> abpClaimsPrincipalFactoryOptions, IOptions<AbpClaimsPrincipalFactoryOptions> abpClaimsPrincipalFactoryOptions,
IRemoteServiceHttpClientAuthenticator httpClientAuthenticator) IRemoteServiceHttpClientAuthenticator httpClientAuthenticator,
IDistributedCache<ApplicationConfigurationDto> applicationConfigurationDtoCache,
ICurrentUser currentUser)
: base(abpClaimsPrincipalFactoryOptions) : base(abpClaimsPrincipalFactoryOptions)
{ {
Cache = cache; Cache = cache;
HttpClientFactory = httpClientFactory; HttpClientFactory = httpClientFactory;
HttpClientAuthenticator = httpClientAuthenticator; HttpClientAuthenticator = httpClientAuthenticator;
ApplicationConfigurationDtoCache = applicationConfigurationDtoCache;
CurrentUser = currentUser;
} }
protected async override Task<AbpDynamicClaimCacheItem?> GetCacheAsync(Guid userId, Guid? tenantId = null) protected async override Task<AbpDynamicClaimCacheItem?> GetCacheAsync(Guid userId, Guid? tenantId = null)
@ -49,6 +57,7 @@ public class RemoteDynamicClaimsPrincipalContributorCache : RemoteDynamicClaimsP
catch (Exception e) catch (Exception e)
{ {
Logger.LogWarning(e, $"Failed to refresh remote claims for user: {userId}"); Logger.LogWarning(e, $"Failed to refresh remote claims for user: {userId}");
await ApplicationConfigurationDtoCache.RemoveAsync(MvcCachedApplicationConfigurationClientHelper.CreateCacheKey(CurrentUser));
throw; throw;
} }
} }

2
framework/src/Volo.Abp.AspNetCore/Volo.Abp.AspNetCore.csproj

@ -20,6 +20,7 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Volo.Abp.AspNetCore.Abstractions\Volo.Abp.AspNetCore.Abstractions.csproj" />
<ProjectReference Include="..\Volo.Abp.Auditing\Volo.Abp.Auditing.csproj" /> <ProjectReference Include="..\Volo.Abp.Auditing\Volo.Abp.Auditing.csproj" />
<ProjectReference Include="..\Volo.Abp.Authorization\Volo.Abp.Authorization.csproj" /> <ProjectReference Include="..\Volo.Abp.Authorization\Volo.Abp.Authorization.csproj" />
<ProjectReference Include="..\Volo.Abp.ExceptionHandling\Volo.Abp.ExceptionHandling.csproj" /> <ProjectReference Include="..\Volo.Abp.ExceptionHandling\Volo.Abp.ExceptionHandling.csproj" />
@ -30,6 +31,7 @@
<ProjectReference Include="..\Volo.Abp.VirtualFileSystem\Volo.Abp.VirtualFileSystem.csproj" /> <ProjectReference Include="..\Volo.Abp.VirtualFileSystem\Volo.Abp.VirtualFileSystem.csproj" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" /> <PackageReference Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" />
<PackageReference Include="IdentityModel" /> <PackageReference Include="IdentityModel" />
<PackageReference Include="DeviceDetector.NET" />
</ItemGroup> </ItemGroup>
</Project> </Project>

3
framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/AbpAspNetCoreModule.cs

@ -25,7 +25,8 @@ namespace Volo.Abp.AspNetCore;
typeof(AbpHttpModule), typeof(AbpHttpModule),
typeof(AbpAuthorizationModule), typeof(AbpAuthorizationModule),
typeof(AbpValidationModule), typeof(AbpValidationModule),
typeof(AbpExceptionHandlingModule) typeof(AbpExceptionHandlingModule),
typeof(AbpAspNetCoreAbstractionsModule)
)] )]
public class AbpAspNetCoreModule : AbpModule public class AbpAspNetCoreModule : AbpModule
{ {

20
framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/Security/Claims/AbpDynamicClaimsMiddleware.cs

@ -1,4 +1,6 @@
using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
@ -16,8 +18,26 @@ public class AbpDynamicClaimsMiddleware : AbpMiddlewareBase, ITransientDependenc
{ {
if (context.RequestServices.GetRequiredService<IOptions<AbpClaimsPrincipalFactoryOptions>>().Value.IsDynamicClaimsEnabled) if (context.RequestServices.GetRequiredService<IOptions<AbpClaimsPrincipalFactoryOptions>>().Value.IsDynamicClaimsEnabled)
{ {
var authenticationType = context.User.Identity.AuthenticationType;
var abpClaimsPrincipalFactory = context.RequestServices.GetRequiredService<IAbpClaimsPrincipalFactory>(); var abpClaimsPrincipalFactory = context.RequestServices.GetRequiredService<IAbpClaimsPrincipalFactory>();
context.User = await abpClaimsPrincipalFactory.CreateDynamicAsync(context.User); context.User = await abpClaimsPrincipalFactory.CreateDynamicAsync(context.User);
if (context.User.Identity?.IsAuthenticated == false)
{
if (!authenticationType.IsNullOrWhiteSpace())
{
var authenticationSchemeProvider = context.RequestServices.GetRequiredService<IAuthenticationSchemeProvider>();
var scheme = await authenticationSchemeProvider.GetSchemeAsync(authenticationType);
if (scheme != null)
{
await context.SignOutAsync(scheme.Name);
}
}
else
{
await context.SignOutAsync();
}
}
} }
} }

1
framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/VirtualFileSystem/WebContentFileProvider.cs

@ -10,6 +10,7 @@ using Volo.Abp.VirtualFileSystem;
namespace Volo.Abp.AspNetCore.VirtualFileSystem; namespace Volo.Abp.AspNetCore.VirtualFileSystem;
[Dependency(ReplaceServices = true)]
public class WebContentFileProvider : IWebContentFileProvider, ISingletonDependency public class WebContentFileProvider : IWebContentFileProvider, ISingletonDependency
{ {
private readonly IVirtualFileProvider _virtualFileProvider; private readonly IVirtualFileProvider _virtualFileProvider;

30
framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/WebClientInfo/HttpContextWebClientInfoProvider.cs

@ -1,10 +1,12 @@
using System; using System;
using DeviceDetectorNET;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Volo.Abp.DependencyInjection; using Volo.Abp.DependencyInjection;
namespace Volo.Abp.AspNetCore.WebClientInfo; namespace Volo.Abp.AspNetCore.WebClientInfo;
[Dependency(ReplaceServices = true)]
public class HttpContextWebClientInfoProvider : IWebClientInfoProvider, ITransientDependency public class HttpContextWebClientInfoProvider : IWebClientInfoProvider, ITransientDependency
{ {
protected ILogger<HttpContextWebClientInfoProvider> Logger { get; } protected ILogger<HttpContextWebClientInfoProvider> Logger { get; }
@ -22,6 +24,8 @@ public class HttpContextWebClientInfoProvider : IWebClientInfoProvider, ITransie
public string? ClientIpAddress => GetClientIpAddress(); public string? ClientIpAddress => GetClientIpAddress();
public string? DeviceInfo => GetDeviceInfo();
protected virtual string? GetBrowserInfo() protected virtual string? GetBrowserInfo()
{ {
return HttpContextAccessor.HttpContext?.Request?.Headers?["User-Agent"]; return HttpContextAccessor.HttpContext?.Request?.Headers?["User-Agent"];
@ -39,4 +43,30 @@ public class HttpContextWebClientInfoProvider : IWebClientInfoProvider, ITransie
return null; return null;
} }
} }
protected virtual string? GetDeviceInfo()
{
string? deviceInfo = null;
var deviceDetector = new DeviceDetector(GetBrowserInfo());
deviceDetector.Parse();
if (!deviceDetector.IsParsed())
{
return deviceInfo;
}
var osInfo = deviceDetector.GetOs();
if (osInfo.Success)
{
deviceInfo = osInfo.Match.Name;
}
var clientInfo = deviceDetector.GetClient();
if (clientInfo.Success)
{
deviceInfo = deviceInfo.IsNullOrWhiteSpace() ? clientInfo.Match.Name : deviceInfo + " " + clientInfo.Match.Name;
}
return deviceInfo;
}
} }

2
framework/src/Volo.Abp.Http/Volo/Abp/Http/Modeling/ApplicationApiDescriptionModel.cs

@ -21,7 +21,7 @@ public class ApplicationApiDescriptionModel
{ {
return new ApplicationApiDescriptionModel return new ApplicationApiDescriptionModel
{ {
Modules = new ConcurrentDictionary<string, ModuleApiDescriptionModel>(), //TODO: Why ConcurrentDictionary? Modules = new Dictionary<string, ModuleApiDescriptionModel>(),
Types = new SortedDictionary<string, TypeApiDescriptionModel>() Types = new SortedDictionary<string, TypeApiDescriptionModel>()
}; };
} }

28
framework/src/Volo.Abp.Security/System/Security/Principal/AbpClaimsIdentityExtensions.cs

@ -276,4 +276,32 @@ public static class AbpClaimsIdentityExtensions
return principal; return principal;
} }
public static string? FindSessionId([NotNull] this IIdentity identity)
{
Check.NotNull(identity, nameof(identity));
var claimsIdentity = identity as ClaimsIdentity;
var sessionIdOrNull = claimsIdentity?.Claims?.FirstOrDefault(c => c.Type == AbpClaimTypes.SessionId);
if (sessionIdOrNull == null || sessionIdOrNull.Value.IsNullOrWhiteSpace())
{
return null;
}
return sessionIdOrNull.Value;
}
public static string? FindSessionId([NotNull] this ClaimsPrincipal principal)
{
Check.NotNull(principal, nameof(principal));
var sessionIdOrNull = principal.Claims?.FirstOrDefault(c => c.Type == AbpClaimTypes.SessionId);
if (sessionIdOrNull == null || sessionIdOrNull.Value.IsNullOrWhiteSpace())
{
return null;
}
return sessionIdOrNull.Value;
}
} }

5
framework/src/Volo.Abp.Security/Volo/Abp/Security/Claims/AbpClaimTypes.cs

@ -97,4 +97,9 @@ public static class AbpClaimTypes
/// Default: "remember_me". /// Default: "remember_me".
/// </summary> /// </summary>
public static string RememberMe { get; set; } = "remember_me"; public static string RememberMe { get; set; } = "remember_me";
/// <summary>
/// Default: "session_id".
/// </summary>
public static string SessionId { get; set; } = "session_id";
} }

12
framework/src/Volo.Abp.Security/Volo/Abp/Users/CurrentUserExtensions.cs

@ -70,4 +70,16 @@ public static class CurrentUserExtensions
{ {
return currentUser.FindClaimValue(AbpClaimTypes.ImpersonatorUserName); return currentUser.FindClaimValue(AbpClaimTypes.ImpersonatorUserName);
} }
public static string GetSessionId([NotNull] this ICurrentUser currentUser)
{
var sessionId = currentUser.FindSessionId();
Debug.Assert(sessionId != null, "sessionId != null");
return sessionId!;
}
public static string? FindSessionId([NotNull] this ICurrentUser currentUser)
{
return currentUser.FindClaimValue(AbpClaimTypes.SessionId);
}
} }

5
framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/ar.json

@ -13,7 +13,8 @@
"SavingWithThreeDot": "حفظ...", "SavingWithThreeDot": "حفظ...",
"Actions": "الإجراءات", "Actions": "الإجراءات",
"Delete": "حذف", "Delete": "حذف",
"SuccessfullyDeleted": "تم الحذف بنجاح", "SavedSuccessfully": "تم الحفظ بنجاح",
"DeletedSuccessfully": "تم الحذف بنجاح",
"Edit": "تعديل", "Edit": "تعديل",
"Refresh": "تحديث", "Refresh": "تحديث",
"Language": "لغة", "Language": "لغة",
@ -59,4 +60,4 @@
"Theme": "سمة", "Theme": "سمة",
"NotAssigned": "غيرمعتمد" "NotAssigned": "غيرمعتمد"
} }
} }

5
framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/cs.json

@ -13,7 +13,8 @@
"SavingWithThreeDot": "Ukládám...", "SavingWithThreeDot": "Ukládám...",
"Actions": "Akce", "Actions": "Akce",
"Delete": "Smazat", "Delete": "Smazat",
"SuccessfullyDeleted": "Úspěšně smazáno", "SavedSuccessfully": "Úspěšně uloženo",
"DeletedSuccessfully": "Úspěšně smazáno",
"Edit": "Upravit", "Edit": "Upravit",
"Refresh": "Obnovit", "Refresh": "Obnovit",
"Language": "Jazyk", "Language": "Jazyk",
@ -59,4 +60,4 @@
"Theme": "Téma", "Theme": "Téma",
"NotAssigned": "Nepřiřazena" "NotAssigned": "Nepřiřazena"
} }
} }

5
framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/de.json

@ -13,7 +13,8 @@
"SavingWithThreeDot": "Speichern...", "SavingWithThreeDot": "Speichern...",
"Actions": "Aktionen", "Actions": "Aktionen",
"Delete": "Löschen", "Delete": "Löschen",
"SuccessfullyDeleted": "Erfolgreich gelöscht", "SavedSuccessfully": "Erfolgreich gespeichert",
"DeletedSuccessfully": "Erfolgreich gelöscht",
"Edit": "Bearbeiten", "Edit": "Bearbeiten",
"Refresh": "Aktualisieren", "Refresh": "Aktualisieren",
"Language": "Sprache", "Language": "Sprache",
@ -59,4 +60,4 @@
"Theme": "Thema", "Theme": "Thema",
"NotAssigned": "Nicht zugeordnet" "NotAssigned": "Nicht zugeordnet"
} }
} }

7
framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/el.json

@ -13,7 +13,8 @@
"SavingWithThreeDot": "Αποθηκεύεται...", "SavingWithThreeDot": "Αποθηκεύεται...",
"Actions": "Ενέργειες", "Actions": "Ενέργειες",
"Delete": "Διαγραφή", "Delete": "Διαγραφή",
"SuccessfullyDeleted": "Διαγράφηκε με επιτυχία", "SavedSuccessfully": "Αποθηκεύτηκε με επιτυχία",
"DeletedSuccessfully": "Διαγράφηκε με επιτυχία",
"Edit": "Επεξεργασία", "Edit": "Επεξεργασία",
"Refresh": "Ανανέωση", "Refresh": "Ανανέωση",
"Language": "Γλώσσα", "Language": "Γλώσσα",
@ -49,8 +50,8 @@
"ItemWillBeDeletedMessageWithFormat": "Το {0} θα διαγραφεί", "ItemWillBeDeletedMessageWithFormat": "Το {0} θα διαγραφεί",
"ItemWillBeDeletedMessage": "Αυτό το στοιχείο θα διαγραφεί!", "ItemWillBeDeletedMessage": "Αυτό το στοιχείο θα διαγραφεί!",
"ManageYourAccount": "Διαχείριση Λογαριασμού", "ManageYourAccount": "Διαχείριση Λογαριασμού",
"OthersGroup":"άλλος", "OthersGroup": "άλλος",
"Today": "Σήμερα", "Today": "Σήμερα",
"Apply": "Ισχύουν" "Apply": "Ισχύουν"
} }
} }

5
framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/en-GB.json

@ -13,7 +13,8 @@
"SavingWithThreeDot": "Saving", "SavingWithThreeDot": "Saving",
"Actions": "Actions", "Actions": "Actions",
"Delete": "Delete", "Delete": "Delete",
"SuccessfullyDeleted": "Successfully deleted", "SavedSuccessfully": "Saved successfully",
"DeletedSuccessfully": "Deleted successfully",
"Edit": "Edit", "Edit": "Edit",
"Refresh": "Refresh", "Refresh": "Refresh",
"Language": "Language", "Language": "Language",
@ -54,4 +55,4 @@
"Today": "Today", "Today": "Today",
"Apply": "Apply" "Apply": "Apply"
} }
} }

3
framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/en.json

@ -13,7 +13,8 @@
"SavingWithThreeDot": "Saving...", "SavingWithThreeDot": "Saving...",
"Actions": "Actions", "Actions": "Actions",
"Delete": "Delete", "Delete": "Delete",
"SuccessfullyDeleted": "Successfully deleted", "SavedSuccessfully": "Saved successfully",
"DeletedSuccessfully": "Deleted successfully",
"Edit": "Edit", "Edit": "Edit",
"Refresh": "Refresh", "Refresh": "Refresh",
"Language": "Language", "Language": "Language",

5
framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/es.json

@ -13,7 +13,8 @@
"SavingWithThreeDot": "Guardando...", "SavingWithThreeDot": "Guardando...",
"Actions": "Opciones", "Actions": "Opciones",
"Delete": "Borrar", "Delete": "Borrar",
"SuccessfullyDeleted": "Eliminado con éxito", "SavedSuccessfully": "Guardado con éxito",
"DeletedSuccessfully": "Eliminado con éxito",
"Edit": "Editar", "Edit": "Editar",
"Refresh": "Actualizar", "Refresh": "Actualizar",
"Language": "Idioma", "Language": "Idioma",
@ -59,4 +60,4 @@
"Theme": "Tema", "Theme": "Tema",
"NotAssigned": "No asignado" "NotAssigned": "No asignado"
} }
} }

3
framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/fa.json

@ -13,7 +13,8 @@
"SavingWithThreeDot": "ذخیره...", "SavingWithThreeDot": "ذخیره...",
"Actions": "عملیات", "Actions": "عملیات",
"Delete": "حذف", "Delete": "حذف",
"SuccessfullyDeleted": "با موفقیت حذف شد", "SavedSuccessfully": "با موفقیت ذخیره شد",
"DeletedSuccessfully": "با موفقیت حذف شد",
"Edit": "ویرایش", "Edit": "ویرایش",
"Refresh": "رفرش", "Refresh": "رفرش",
"Language": "زبان", "Language": "زبان",

5
framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/fi.json

@ -13,7 +13,8 @@
"SavingWithThreeDot": "Tallennetaan...", "SavingWithThreeDot": "Tallennetaan...",
"Actions": "Toiminnot", "Actions": "Toiminnot",
"Delete": "Poista", "Delete": "Poista",
"SuccessfullyDeleted": "Poistettu onnistuneesti", "SavedSuccessfully": "Tallennettu onnistuneesti",
"DeletedSuccessfully": "Poistettu onnistuneesti",
"Edit": "Muokkaa", "Edit": "Muokkaa",
"Refresh": "Virkistä", "Refresh": "Virkistä",
"Language": "Kieli", "Language": "Kieli",
@ -59,4 +60,4 @@
"Theme": "Teema", "Theme": "Teema",
"NotAssigned": "Ei määritetty" "NotAssigned": "Ei määritetty"
} }
} }

5
framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/fr.json

@ -13,7 +13,8 @@
"SavingWithThreeDot": "Enregistrement...", "SavingWithThreeDot": "Enregistrement...",
"Actions": "Actions", "Actions": "Actions",
"Delete": "Supprimer", "Delete": "Supprimer",
"SuccessfullyDeleted": "Supprimé avec succès", "SavedSuccessfully": "Enregistré avec succès",
"DeletedSuccessfully": "Supprimé avec succès",
"Edit": "Modifier", "Edit": "Modifier",
"Refresh": "Actualiser", "Refresh": "Actualiser",
"Language": "Langue", "Language": "Langue",
@ -59,4 +60,4 @@
"Theme": "Thème", "Theme": "Thème",
"NotAssigned": "Non attribué" "NotAssigned": "Non attribué"
} }
} }

5
framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/hi.json

@ -13,7 +13,8 @@
"SavingWithThreeDot": "सहेजा जा रहा है...", "SavingWithThreeDot": "सहेजा जा रहा है...",
"Actions": "कार्रवाई", "Actions": "कार्रवाई",
"Delete": "हटाएं", "Delete": "हटाएं",
"SuccessfullyDeleted": "सफलतापूर्वक हटा दिया गया", "SavedSuccessfully": "सफलतापूर्वक सहेजा गया",
"DeletedSuccessfully": "सफलतापूर्वक हटा दिया गया",
"Edit": "संपादित करें", "Edit": "संपादित करें",
"Refresh": "ताज़ा करना", "Refresh": "ताज़ा करना",
"Language": "भाषा: हिन्दी", "Language": "भाषा: हिन्दी",
@ -59,4 +60,4 @@
"Theme": "विषय", "Theme": "विषय",
"NotAssigned": "सौंपा नहीं गया है" "NotAssigned": "सौंपा नहीं गया है"
} }
} }

5
framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/hr.json

@ -13,7 +13,8 @@
"SavingWithThreeDot": "Spremanje...", "SavingWithThreeDot": "Spremanje...",
"Actions": "Akcije", "Actions": "Akcije",
"Delete": "Izbrisati", "Delete": "Izbrisati",
"SuccessfullyDeleted": "Uspješno izbrisano", "SavedSuccessfully": "Uspešno zabeleženo",
"DeletedSuccessfully": "Uspješno izbrisano",
"Edit": "Uredi", "Edit": "Uredi",
"Refresh": "Osvježi", "Refresh": "Osvježi",
"Language": "Jezik", "Language": "Jezik",
@ -59,4 +60,4 @@
"Theme": "Tema", "Theme": "Tema",
"NotAssigned": "Nije dodijeljeno" "NotAssigned": "Nije dodijeljeno"
} }
} }

5
framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/hu.json

@ -13,7 +13,8 @@
"SavingWithThreeDot": "Mentés...", "SavingWithThreeDot": "Mentés...",
"Actions": "Műveletek", "Actions": "Műveletek",
"Delete": "Törlés", "Delete": "Törlés",
"SuccessfullyDeleted": "Sikeresen törölve", "SavedSuccessfully": "Sikeresen mentve",
"DeletedSuccessfully": "Sikeresen törölve",
"Edit": "Szerkesztés", "Edit": "Szerkesztés",
"Refresh": "Frissítés", "Refresh": "Frissítés",
"Language": "Nyelv", "Language": "Nyelv",
@ -59,4 +60,4 @@
"Theme": "Téma", "Theme": "Téma",
"NotAssigned": "Nem kijelölt" "NotAssigned": "Nem kijelölt"
} }
} }

5
framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/is.json

@ -13,7 +13,8 @@
"SavingWithThreeDot": "Er að vista...", "SavingWithThreeDot": "Er að vista...",
"Actions": "Aðgerðir", "Actions": "Aðgerðir",
"Delete": "Eyða", "Delete": "Eyða",
"SuccessfullyDeleted": "Tókst að eyða", "SavedSuccessfully": "Tókst að vista",
"DeletedSuccessfully": "Tókst að eyða",
"Edit": "Breyta", "Edit": "Breyta",
"Refresh": "Endurhlaða", "Refresh": "Endurhlaða",
"Language": "Tungumál", "Language": "Tungumál",
@ -59,4 +60,4 @@
"Theme": "Þema", "Theme": "Þema",
"NotAssigned": "Ekki skráður" "NotAssigned": "Ekki skráður"
} }
} }

5
framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/it.json

@ -13,7 +13,8 @@
"SavingWithThreeDot": "Salvataggio...", "SavingWithThreeDot": "Salvataggio...",
"Actions": "Azioni", "Actions": "Azioni",
"Delete": "Elimina", "Delete": "Elimina",
"SuccessfullyDeleted": "Eliminato con successo", "SavedSuccessfully": "Salvato con successo",
"DeletedSuccessfully": "Eliminato con successo",
"Edit": "Modifica", "Edit": "Modifica",
"Refresh": "Ricarica", "Refresh": "Ricarica",
"Language": "Lingua", "Language": "Lingua",
@ -59,4 +60,4 @@
"Theme": "Tema", "Theme": "Tema",
"NotAssigned": "Non assegnato" "NotAssigned": "Non assegnato"
} }
} }

5
framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/nl.json

@ -13,7 +13,8 @@
"SavingWithThreeDot": "Opslaan...", "SavingWithThreeDot": "Opslaan...",
"Actions": "Acties", "Actions": "Acties",
"Delete": "Verwijder", "Delete": "Verwijder",
"SuccessfullyDeleted": "Succesvol verwijderd", "SavedSuccessfully": "Succesvol opgeslagen",
"DeletedSuccessfully": "Succesvol verwijderd",
"Edit": "Bewerk", "Edit": "Bewerk",
"Refresh": "Ververs", "Refresh": "Ververs",
"Language": "Taal", "Language": "Taal",
@ -59,4 +60,4 @@
"Theme": "Thema", "Theme": "Thema",
"NotAssigned": "Niet toegekend" "NotAssigned": "Niet toegekend"
} }
} }

5
framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/pl-PL.json

@ -13,7 +13,8 @@
"SavingWithThreeDot": "Zapisywanie...", "SavingWithThreeDot": "Zapisywanie...",
"Actions": "Akcje", "Actions": "Akcje",
"Delete": "Usuń", "Delete": "Usuń",
"SuccessfullyDeleted": "Pomyślnie usunięto", "SavedSuccessfully": "Pomyślnie zapisano",
"DeletedSuccessfully": "Pomyślnie usunięto",
"Edit": "Edytuj", "Edit": "Edytuj",
"Refresh": "Odśwież", "Refresh": "Odśwież",
"Language": "Język", "Language": "Język",
@ -59,4 +60,4 @@
"Theme": "Temat", "Theme": "Temat",
"NotAssigned": "Nie przypisano" "NotAssigned": "Nie przypisano"
} }
} }

5
framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/pt-BR.json

@ -13,7 +13,8 @@
"SavingWithThreeDot": "Salvando...", "SavingWithThreeDot": "Salvando...",
"Actions": "Ações", "Actions": "Ações",
"Delete": "Excluir", "Delete": "Excluir",
"SuccessfullyDeleted": "Excluído com sucesso", "SavedSuccessfully": "Salvo com sucesso",
"DeletedSuccessfully": "Excluído com sucesso",
"Edit": "Editar", "Edit": "Editar",
"Refresh": "Atualizar", "Refresh": "Atualizar",
"Language": "Idioma", "Language": "Idioma",
@ -59,4 +60,4 @@
"Theme": "Tema", "Theme": "Tema",
"NotAssigned": "Não atribuído" "NotAssigned": "Não atribuído"
} }
} }

5
framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/ro-RO.json

@ -13,7 +13,8 @@
"SavingWithThreeDot": "Se salvează...", "SavingWithThreeDot": "Se salvează...",
"Actions": "Acţiuni", "Actions": "Acţiuni",
"Delete": "Şterge", "Delete": "Şterge",
"SuccessfullyDeleted": "Șters cu succes", "SavedSuccessfully": "Salvat cu succes",
"DeletedSuccessfully": "Șters cu succes",
"Edit": "Editează", "Edit": "Editează",
"Refresh": "Reîncarcă", "Refresh": "Reîncarcă",
"Language": "Limba", "Language": "Limba",
@ -59,4 +60,4 @@
"Theme": "Temă", "Theme": "Temă",
"NotAssigned": "Nealocat" "NotAssigned": "Nealocat"
} }
} }

5
framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/ru.json

@ -13,7 +13,8 @@
"SavingWithThreeDot": "Сохранение...", "SavingWithThreeDot": "Сохранение...",
"Actions": "Действия", "Actions": "Действия",
"Delete": "Удалить", "Delete": "Удалить",
"SuccessfullyDeleted": "Успешно удалено", "SavedSuccessfully": "Успешно сохранено",
"DeletedSuccessfully": "Успешно удалено",
"Edit": "Редактировать", "Edit": "Редактировать",
"Refresh": "Обновить", "Refresh": "Обновить",
"Language": "Язык", "Language": "Язык",
@ -59,4 +60,4 @@
"Theme": "Тема", "Theme": "Тема",
"NotAssigned": "Не назначен" "NotAssigned": "Не назначен"
} }
} }

5
framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/sk.json

@ -13,7 +13,8 @@
"SavingWithThreeDot": "Úkladanie...", "SavingWithThreeDot": "Úkladanie...",
"Actions": "Akcie", "Actions": "Akcie",
"Delete": "Odstrániť", "Delete": "Odstrániť",
"SuccessfullyDeleted": "Úspešne odstránené", "SavedSuccessfully": "Úspešne uložené",
"DeletedSuccessfully": "Úspešne odstránené",
"Edit": "Upraviť", "Edit": "Upraviť",
"Refresh": "Obnoviť", "Refresh": "Obnoviť",
"Language": "Jazyk", "Language": "Jazyk",
@ -59,4 +60,4 @@
"Theme": "Téma", "Theme": "Téma",
"NotAssigned": "Nepridelené" "NotAssigned": "Nepridelené"
} }
} }

5
framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/sl.json

@ -13,7 +13,8 @@
"SavingWithThreeDot": "Shranjujem...", "SavingWithThreeDot": "Shranjujem...",
"Actions": "Dejanja", "Actions": "Dejanja",
"Delete": "Izbriši", "Delete": "Izbriši",
"SuccessfullyDeleted": "Uspešno izbrisano", "SavedSuccessfully": "Uspešno shranjeno",
"DeletedSuccessfully": "Uspešno izbrisano",
"Edit": "Uredi", "Edit": "Uredi",
"Refresh": "Osveži", "Refresh": "Osveži",
"Language": "Jezik", "Language": "Jezik",
@ -59,4 +60,4 @@
"Theme": "Tema", "Theme": "Tema",
"NotAssigned": "Ni dodeljena" "NotAssigned": "Ni dodeljena"
} }
} }

3
framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/tr.json

@ -13,7 +13,8 @@
"SavingWithThreeDot": "Kaydediliyor...", "SavingWithThreeDot": "Kaydediliyor...",
"Actions": "İşlemler", "Actions": "İşlemler",
"Delete": "Sil", "Delete": "Sil",
"SuccessfullyDeleted": "Başarıyla silindi", "SavedSuccessfully": "Başarıyla kaydedildi",
"DeletedSuccessfully": "Başarıyla silindi",
"Edit": "Düzenle", "Edit": "Düzenle",
"Refresh": "Yenile", "Refresh": "Yenile",
"Language": "Dil", "Language": "Dil",

5
framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/vi.json

@ -13,7 +13,8 @@
"SavingWithThreeDot": "Đang lưu...", "SavingWithThreeDot": "Đang lưu...",
"Actions": "Hành động", "Actions": "Hành động",
"Delete": "Xóa", "Delete": "Xóa",
"SuccessfullyDeleted": "Đã xóa thành công", "SavedSuccessfully": "Đã lưu thành công",
"DeletedSuccessfully": "Đã xóa thành công",
"Edit": "Sửa", "Edit": "Sửa",
"Refresh": "Làm mới", "Refresh": "Làm mới",
"Language": "Ngôn ngữ", "Language": "Ngôn ngữ",
@ -59,4 +60,4 @@
"Theme": "chủ đề", "Theme": "chủ đề",
"NotAssigned": "Không được chỉ định" "NotAssigned": "Không được chỉ định"
} }
} }

5
framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/zh-Hans.json

@ -13,7 +13,8 @@
"SavingWithThreeDot": "保存中...", "SavingWithThreeDot": "保存中...",
"Actions": "操作", "Actions": "操作",
"Delete": "删除", "Delete": "删除",
"SuccessfullyDeleted": "删除成功", "SavedSuccessfully": "保存成功",
"DeletedSuccessfully": "删除成功",
"Edit": "编辑", "Edit": "编辑",
"Refresh": "刷新", "Refresh": "刷新",
"Language": "语言", "Language": "语言",
@ -59,4 +60,4 @@
"Theme": "主题", "Theme": "主题",
"NotAssigned": "未分配" "NotAssigned": "未分配"
} }
} }

5
framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/zh-Hant.json

@ -13,7 +13,8 @@
"SavingWithThreeDot": "保存中...", "SavingWithThreeDot": "保存中...",
"Actions": "操作", "Actions": "操作",
"Delete": "刪除", "Delete": "刪除",
"SuccessfullyDeleted": "刪除成功", "SavedSuccessfully": "保存成功",
"DeletedSuccessfully": "刪除成功",
"Edit": "修改", "Edit": "修改",
"Refresh": "更新", "Refresh": "更新",
"Language": "語言", "Language": "語言",
@ -59,4 +60,4 @@
"Theme": "主題", "Theme": "主題",
"NotAssigned": "未分配" "NotAssigned": "未分配"
} }
} }

6
modules/docs/src/Volo.Docs.Admin.Application/Volo/Docs/Admin/Documents/DocumentAdminAppService.cs

@ -57,7 +57,7 @@ namespace Volo.Docs.Admin.Documents
var versionCacheKey = CacheKeyGenerator.GenerateProjectVersionsCacheKey(project); var versionCacheKey = CacheKeyGenerator.GenerateProjectVersionsCacheKey(project);
await _versionCache.RemoveAsync(versionCacheKey, true); await _versionCache.RemoveAsync(versionCacheKey, true);
var documents = await _documentRepository.GetListByProjectId(project.Id); var documents = await _documentRepository.GetListWithoutDetailsByProjectId(project.Id);
var documentUpdateInfoCacheKeys = documents.Select(document => var documentUpdateInfoCacheKeys = documents.Select(document =>
CacheKeyGenerator.GenerateDocumentUpdateInfoCacheKey( CacheKeyGenerator.GenerateDocumentUpdateInfoCacheKey(
@ -69,10 +69,8 @@ namespace Volo.Docs.Admin.Documents
); );
await _documentUpdateCache.RemoveManyAsync(documentUpdateInfoCacheKeys); await _documentUpdateCache.RemoveManyAsync(documentUpdateInfoCacheKeys);
documents.ForEach(document => document.LastCachedTime = DateTime.MinValue);
await _documentRepository.UpdateManyAsync(documents); await _documentRepository.UpdateProjectLastCachedTimeAsync(project.Id, DateTime.MinValue);
} }
public virtual async Task PullAllAsync(PullAllDocumentInput input) public virtual async Task PullAllAsync(PullAllDocumentInput input)

2
modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/DocumentWithoutDetails.cs

@ -5,6 +5,8 @@ namespace Volo.Docs.Documents
public class DocumentWithoutDetails public class DocumentWithoutDetails
{ {
public Guid Id { get; set; } public Guid Id { get; set; }
public string Name { get; set; }
public virtual string Version { get; set; } public virtual string Version { get; set; }

3
modules/docs/src/Volo.Docs.Domain/Volo/Docs/Documents/IDocumentRepository.cs

@ -12,6 +12,9 @@ namespace Volo.Docs.Documents
Task<List<DocumentInfo>> GetUniqueListDocumentInfoAsync(CancellationToken cancellationToken = default); Task<List<DocumentInfo>> GetUniqueListDocumentInfoAsync(CancellationToken cancellationToken = default);
Task<List<Document>> GetListByProjectId(Guid projectId, CancellationToken cancellationToken = default); Task<List<Document>> GetListByProjectId(Guid projectId, CancellationToken cancellationToken = default);
Task UpdateProjectLastCachedTimeAsync(Guid projectId, DateTime cachedTime,
CancellationToken cancellationToken = default);
Task<Document> FindAsync(Guid projectId, Task<Document> FindAsync(Guid projectId,
string name, string name,

7
modules/docs/src/Volo.Docs.EntityFrameworkCore/Volo/Docs/Documents/EFCoreDocumentRepository.cs

@ -28,6 +28,7 @@ namespace Volo.Docs.Documents
Version = x.Version, Version = x.Version,
LanguageCode = x.LanguageCode, LanguageCode = x.LanguageCode,
Format = x.Format, Format = x.Format,
Name = x.Name
}) })
.ToListAsync(GetCancellationToken(cancellationToken)); .ToListAsync(GetCancellationToken(cancellationToken));
} }
@ -55,6 +56,12 @@ namespace Volo.Docs.Documents
return await (await GetDbSetAsync()).Where(d => d.ProjectId == projectId).ToListAsync(GetCancellationToken(cancellationToken)); return await (await GetDbSetAsync()).Where(d => d.ProjectId == projectId).ToListAsync(GetCancellationToken(cancellationToken));
} }
public async Task UpdateProjectLastCachedTimeAsync(Guid projectId, DateTime cachedTime,
CancellationToken cancellationToken = default)
{
await (await GetDbSetAsync()).Where(d => d.ProjectId == projectId).ExecuteUpdateAsync(x => x.SetProperty(d => d.LastCachedTime, cachedTime), GetCancellationToken(cancellationToken));
}
public virtual async Task<List<Document>> GetListAsync(Guid? projectId, string version, string name, CancellationToken cancellationToken = default) public virtual async Task<List<Document>> GetListAsync(Guid? projectId, string version, string name, CancellationToken cancellationToken = default)
{ {
return await (await GetDbSetAsync()) return await (await GetDbSetAsync())

14
modules/docs/src/Volo.Docs.MongoDB/Volo/Docs/Documents/MongoDocumentRepository.cs

@ -29,7 +29,8 @@ namespace Volo.Docs.Documents
Id = x.Id, Id = x.Id,
Version = x.Version, Version = x.Version,
LanguageCode = x.LanguageCode, LanguageCode = x.LanguageCode,
Format = x.Format Format = x.Format,
Name = x.Name
}) })
.ToListAsync(GetCancellationToken(cancellationToken)); .ToListAsync(GetCancellationToken(cancellationToken));
} }
@ -53,6 +54,17 @@ namespace Volo.Docs.Documents
return await (await GetMongoQueryableAsync(cancellationToken)).Where(d => d.ProjectId == projectId).ToListAsync(GetCancellationToken(cancellationToken)); return await (await GetMongoQueryableAsync(cancellationToken)).Where(d => d.ProjectId == projectId).ToListAsync(GetCancellationToken(cancellationToken));
} }
public async Task UpdateProjectLastCachedTimeAsync(Guid projectId, DateTime cachedTime,
CancellationToken cancellationToken = default)
{
var collection = await GetCollectionAsync(cancellationToken);
await collection.UpdateManyAsync(
Builders<Document>.Filter.Eq(x => x.ProjectId, projectId),
Builders<Document>.Update.Set(x => x.LastCachedTime, cachedTime),
cancellationToken: GetCancellationToken(cancellationToken)
);
}
public virtual async Task<Document> FindAsync(Guid projectId, string name, string languageCode, string version, public virtual async Task<Document> FindAsync(Guid projectId, string name, string languageCode, string version,
bool includeDetails = true, bool includeDetails = true,
CancellationToken cancellationToken = default) CancellationToken cancellationToken = default)

11
modules/docs/test/Volo.Docs.TestBase/Volo/Docs/DocumentRepository_Tests.cs

@ -1,4 +1,5 @@
using System.Threading.Tasks; using System;
using System.Threading.Tasks;
using Shouldly; using Shouldly;
using Volo.Abp.Modularity; using Volo.Abp.Modularity;
using Volo.Docs.Documents; using Volo.Docs.Documents;
@ -34,5 +35,13 @@ namespace Volo.Docs
(await DocumentRepository.GetListAsync()).ShouldBeEmpty(); (await DocumentRepository.GetListAsync()).ShouldBeEmpty();
} }
[Fact]
public async Task UpdateProjectLastCachedTimeAsync()
{
await DocumentRepository.UpdateProjectLastCachedTimeAsync(DocsTestData.ProjectId, DateTime.MinValue);
var documentsAfterClear = await DocumentRepository.GetListByProjectId(DocsTestData.ProjectId);
documentsAfterClear.ForEach(d => d.LastCachedTime.ShouldBe(DateTime.MinValue));
}
} }
} }

14
modules/identity/src/Volo.Abp.Identity.AspNetCore/Volo/Abp/Identity/AspNetCore/AbpIdentityAspNetCoreModule.cs

@ -1,5 +1,7 @@
using Microsoft.AspNetCore.Identity; using System;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Volo.Abp.Modularity; using Volo.Abp.Modularity;
using static Volo.Abp.Identity.AspNetCore.AbpSecurityStampValidatorCallback; using static Volo.Abp.Identity.AspNetCore.AbpSecurityStampValidatorCallback;
@ -45,9 +47,11 @@ public class AbpIdentityAspNetCoreModule : AbpModule
public override void PostConfigureServices(ServiceConfigurationContext context) public override void PostConfigureServices(ServiceConfigurationContext context)
{ {
Configure<SecurityStampValidatorOptions>(options => context.Services.AddOptions<SecurityStampValidatorOptions>()
{ .Configure<IServiceProvider>((securityStampValidatorOptions, serviceProvider) =>
options.UpdatePrincipal(); {
}); var abpRefreshingPrincipalOptions = serviceProvider.GetRequiredService<IOptions<AbpRefreshingPrincipalOptions>>().Value;
securityStampValidatorOptions.UpdatePrincipal(abpRefreshingPrincipalOptions);
});
} }
} }

17
modules/identity/src/Volo.Abp.Identity.AspNetCore/Volo/Abp/Identity/AspNetCore/AbpRefreshingPrincipalOptions.cs

@ -0,0 +1,17 @@
using System.Collections.Generic;
using Volo.Abp.Security.Claims;
namespace Volo.Abp.Identity.AspNetCore;
public class AbpRefreshingPrincipalOptions
{
public List<string> CurrentPrincipalKeepClaimTypes { get; set; }
public AbpRefreshingPrincipalOptions()
{
CurrentPrincipalKeepClaimTypes = new List<string>
{
AbpClaimTypes.SessionId
};
}
}

17
modules/identity/src/Volo.Abp.Identity.AspNetCore/Volo/Abp/Identity/AspNetCore/AbpSecurityStampValidatorCallback.cs

@ -1,5 +1,7 @@
using System.Linq; using System.Linq;
using System.Security.Principal;
using System.Threading.Tasks; using System.Threading.Tasks;
using JetBrains.Annotations;
using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Identity;
namespace Volo.Abp.Identity.AspNetCore; namespace Volo.Abp.Identity.AspNetCore;
@ -17,8 +19,9 @@ public class AbpSecurityStampValidatorCallback
/// This is needed to preserve claims such as idp, auth_time, amr. /// This is needed to preserve claims such as idp, auth_time, amr.
/// </summary> /// </summary>
/// <param name="context">The context.</param> /// <param name="context">The context.</param>
/// <param name="refreshingPrincipalOptions">The AbpRefreshingPrincipalOptions.</param>
/// <returns></returns> /// <returns></returns>
public static Task UpdatePrincipal(SecurityStampRefreshingPrincipalContext context) public static Task UpdatePrincipal(SecurityStampRefreshingPrincipalContext context, AbpRefreshingPrincipalOptions refreshingPrincipalOptions)
{ {
var newClaimTypes = context.NewPrincipal.Claims.Select(x => x.Type).ToArray(); var newClaimTypes = context.NewPrincipal.Claims.Select(x => x.Type).ToArray();
var currentClaimsToKeep = context.CurrentPrincipal.Claims.Where(x => !newClaimTypes.Contains(x.Type)).ToArray(); var currentClaimsToKeep = context.CurrentPrincipal.Claims.Where(x => !newClaimTypes.Contains(x.Type)).ToArray();
@ -26,6 +29,18 @@ public class AbpSecurityStampValidatorCallback
var id = context.NewPrincipal.Identities.First(); var id = context.NewPrincipal.Identities.First();
id.AddClaims(currentClaimsToKeep); id.AddClaims(currentClaimsToKeep);
if (refreshingPrincipalOptions.CurrentPrincipalKeepClaimTypes.Any())
{
foreach (var claimType in refreshingPrincipalOptions.CurrentPrincipalKeepClaimTypes)
{
var sessionIdClaim = context.CurrentPrincipal.Claims.FirstOrDefault(x => x.Type == claimType);
if (sessionIdClaim != null)
{
id.AddOrReplace(sessionIdClaim);
}
}
}
return Task.CompletedTask; return Task.CompletedTask;
} }
} }

4
modules/identity/src/Volo.Abp.Identity.AspNetCore/Volo/Abp/Identity/AspNetCore/SecurityStampValidatorOptionsExtensions.cs

@ -5,12 +5,12 @@ namespace Volo.Abp.Identity.AspNetCore;
public static class SecurityStampValidatorOptionsExtensions public static class SecurityStampValidatorOptionsExtensions
{ {
public static SecurityStampValidatorOptions UpdatePrincipal(this SecurityStampValidatorOptions options) public static SecurityStampValidatorOptions UpdatePrincipal(this SecurityStampValidatorOptions options, AbpRefreshingPrincipalOptions abpRefreshingPrincipalOptions)
{ {
var previousOnRefreshingPrincipal = options.OnRefreshingPrincipal; var previousOnRefreshingPrincipal = options.OnRefreshingPrincipal;
options.OnRefreshingPrincipal = async context => options.OnRefreshingPrincipal = async context =>
{ {
await SecurityStampValidatorCallback.UpdatePrincipal(context); await SecurityStampValidatorCallback.UpdatePrincipal(context, abpRefreshingPrincipalOptions);
if(previousOnRefreshingPrincipal != null) if(previousOnRefreshingPrincipal != null)
{ {
await previousOnRefreshingPrincipal.Invoke(context); await previousOnRefreshingPrincipal.Invoke(context);

14
modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/IdentitySessionConsts.cs

@ -0,0 +1,14 @@
namespace Volo.Abp.Identity;
public class IdentitySessionConsts
{
public static int MaxSessionIdLength { get; set; } = 128;
public static int MaxDeviceLength { get; set; } = 64;
public static int MaxDeviceInfoLength { get; set; } = 64;
public static int MaxClientIdLength { get; set; } = 64;
public static int MaxIpAddressesLength { get; set; } = 256;
}

10
modules/identity/src/Volo.Abp.Identity.Domain.Shared/Volo/Abp/Identity/IdentitySessionDevices.cs

@ -0,0 +1,10 @@
namespace Volo.Abp.Identity;
public static class IdentitySessionDevices
{
public const string Web = "Web";
public const string OAuth = "OAuth";
public const string Mobile = "Mobile";
}

2
modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IIdentitySecurityLogRepository.cs

@ -10,7 +10,7 @@ public interface IIdentitySecurityLogRepository : IBasicRepository<IdentitySecur
{ {
Task<List<IdentitySecurityLog>> GetListAsync( Task<List<IdentitySecurityLog>> GetListAsync(
string sorting = null, string sorting = null,
int maxResultCount = 50, int maxResultCount = int.MaxValue,
int skipCount = 0, int skipCount = 0,
DateTime? startTime = null, DateTime? startTime = null,
DateTime? endTime = null, DateTime? endTime = null,

35
modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IIdentitySessionRepository.cs

@ -0,0 +1,35 @@
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.Domain.Repositories;
namespace Volo.Abp.Identity;
public interface IIdentitySessionRepository : IBasicRepository<IdentitySession, Guid>
{
Task<IdentitySession> FindAsync(string sessionId, CancellationToken cancellationToken = default);
Task<IdentitySession> GetAsync(string sessionId, CancellationToken cancellationToken = default);
Task<List<IdentitySession>> GetListAsync(
string sorting = null,
int maxResultCount = int.MaxValue,
int skipCount = 0,
Guid? userId = null,
string device = null,
string clientId = null,
CancellationToken cancellationToken = default);
Task<long> GetCountAsync(
Guid? userId = null,
string device = null,
string clientId = null,
CancellationToken cancellationToken = default);
Task DeleteAllAsync(Guid userId, Guid? exceptSessionId = null, CancellationToken cancellationToken = default);
Task DeleteAllAsync(Guid userId, string device, Guid? exceptSessionId = null, CancellationToken cancellationToken = default);
Task DeleteAllAsync(TimeSpan inactiveTimeSpan, CancellationToken cancellationToken = default);
}

90
modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentitySession.cs

@ -0,0 +1,90 @@
using System;
using System.Collections.Generic;
using Volo.Abp.Domain.Entities;
using Volo.Abp.MultiTenancy;
namespace Volo.Abp.Identity;
public class IdentitySession : BasicAggregateRoot<Guid>, IMultiTenant
{
public virtual string SessionId { get; protected set; }
/// <summary>
/// Web, Mobile ...
/// </summary>
public virtual string Device { get; protected set; }
public virtual string DeviceInfo { get; protected set; }
public virtual Guid? TenantId { get; protected set; }
public virtual Guid UserId { get; protected set; }
public virtual string ClientId { get; set; }
public virtual string IpAddresses { get; protected set; }
public virtual DateTime SignedIn { get; protected set; }
public virtual DateTime? LastAccessed { get; protected set; }
protected IdentitySession()
{
}
public IdentitySession(
Guid id,
string sessionId,
string device,
string deviceInfo,
Guid userId,
Guid? tenantId,
string clientId,
string ipAddresses,
DateTime signedIn,
DateTime? lastAccessed = null)
{
Id = id;
SessionId = sessionId;
Device = device;
DeviceInfo = deviceInfo;
UserId = userId;
TenantId = tenantId;
ClientId = clientId;
IpAddresses = ipAddresses;
SignedIn = signedIn;
LastAccessed = lastAccessed;
}
public void SetSignedInTime(DateTime signedIn)
{
SignedIn = signedIn;
}
public void UpdateLastAccessedTime(DateTime? lastAccessed)
{
LastAccessed = lastAccessed;
}
public void SetIpAddresses(IEnumerable<string> ipAddresses)
{
IpAddresses = JoinAsString(ipAddresses);
}
public IEnumerable<string> GetIpAddresses()
{
return GetArrayFromString(IpAddresses);
}
private static string JoinAsString(IEnumerable<string> list)
{
var serialized = string.Join(",", list);
return serialized.IsNullOrWhiteSpace() ? null : serialized;
}
private string[] GetArrayFromString(string str)
{
return str?.Split(",", StringSplitOptions.RemoveEmptyEntries) ?? Array.Empty<string>();
}
}

3
modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/AbpIdentityEntityFrameworkCoreModule.cs

@ -17,9 +17,10 @@ public class AbpIdentityEntityFrameworkCoreModule : AbpModule
options.AddRepository<IdentityRole, EfCoreIdentityRoleRepository>(); options.AddRepository<IdentityRole, EfCoreIdentityRoleRepository>();
options.AddRepository<IdentityClaimType, EfCoreIdentityClaimTypeRepository>(); options.AddRepository<IdentityClaimType, EfCoreIdentityClaimTypeRepository>();
options.AddRepository<OrganizationUnit, EfCoreOrganizationUnitRepository>(); options.AddRepository<OrganizationUnit, EfCoreOrganizationUnitRepository>();
options.AddRepository<IdentitySecurityLog, EFCoreIdentitySecurityLogRepository>(); options.AddRepository<IdentitySecurityLog, EfCoreIdentitySecurityLogRepository>();
options.AddRepository<IdentityLinkUser, EfCoreIdentityLinkUserRepository>(); options.AddRepository<IdentityLinkUser, EfCoreIdentityLinkUserRepository>();
options.AddRepository<IdentityUserDelegation, EfCoreIdentityUserDelegationRepository>(); options.AddRepository<IdentityUserDelegation, EfCoreIdentityUserDelegationRepository>();
options.AddRepository<IdentitySession, EfCoreIdentitySessionRepository>();
}); });
} }
} }

6
modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EFCoreIdentitySecurityLogRepository.cs → modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreIdentitySecurityLogRepository.cs

@ -10,9 +10,9 @@ using Volo.Abp.EntityFrameworkCore;
namespace Volo.Abp.Identity.EntityFrameworkCore; namespace Volo.Abp.Identity.EntityFrameworkCore;
public class EFCoreIdentitySecurityLogRepository : EfCoreRepository<IIdentityDbContext, IdentitySecurityLog, Guid>, IIdentitySecurityLogRepository public class EfCoreIdentitySecurityLogRepository : EfCoreRepository<IIdentityDbContext, IdentitySecurityLog, Guid>, IIdentitySecurityLogRepository
{ {
public EFCoreIdentitySecurityLogRepository(IDbContextProvider<IIdentityDbContext> dbContextProvider) public EfCoreIdentitySecurityLogRepository(IDbContextProvider<IIdentityDbContext> dbContextProvider)
: base(dbContextProvider) : base(dbContextProvider)
{ {
@ -20,7 +20,7 @@ public class EFCoreIdentitySecurityLogRepository : EfCoreRepository<IIdentityDbC
public virtual async Task<List<IdentitySecurityLog>> GetListAsync( public virtual async Task<List<IdentitySecurityLog>> GetListAsync(
string sorting = null, string sorting = null,
int maxResultCount = 50, int maxResultCount = int.MaxValue,
int skipCount = 0, int skipCount = 0,
DateTime? startTime = null, DateTime? startTime = null,
DateTime? endTime = null, DateTime? endTime = null,

85
modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/EfCoreIdentitySessionRepository.cs

@ -0,0 +1,85 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Dynamic.Core;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Volo.Abp.Domain.Entities;
using Volo.Abp.Domain.Repositories.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore;
using Volo.Abp.Timing;
namespace Volo.Abp.Identity.EntityFrameworkCore;
public class EfCoreIdentitySessionRepository : EfCoreRepository<IIdentityDbContext, IdentitySession, Guid>, IIdentitySessionRepository
{
public EfCoreIdentitySessionRepository(IDbContextProvider<IIdentityDbContext> dbContextProvider)
: base(dbContextProvider)
{
}
public virtual async Task<IdentitySession> FindAsync(string sessionId, CancellationToken cancellationToken = default)
{
return await (await GetDbSetAsync()).FirstOrDefaultAsync(x => x.SessionId == sessionId, GetCancellationToken(cancellationToken));
}
public virtual async Task<IdentitySession> GetAsync(string sessionId, CancellationToken cancellationToken = default)
{
var session = await FindAsync(sessionId, cancellationToken);
if (session == null)
{
throw new EntityNotFoundException(typeof(IdentitySession));
}
return session;
}
public virtual async Task<List<IdentitySession>> GetListAsync(
string sorting = null,
int maxResultCount = int.MaxValue,
int skipCount = 0,
Guid? userId = null,
string device = null,
string clientId = null,
CancellationToken cancellationToken = default)
{
return await (await GetDbSetAsync())
.WhereIf(userId.HasValue, x => x.UserId == userId)
.WhereIf(!device.IsNullOrWhiteSpace(), x => x.Device == device)
.WhereIf(!clientId.IsNullOrWhiteSpace(), x => x.ClientId == clientId)
.OrderBy(sorting.IsNullOrWhiteSpace() ? $"{nameof(IdentitySession.LastAccessed)} desc" : sorting)
.PageBy(skipCount, maxResultCount)
.ToListAsync(GetCancellationToken(cancellationToken));
}
public virtual async Task<long> GetCountAsync(
Guid? userId = null,
string device = null,
string clientId = null,
CancellationToken cancellationToken = default)
{
return await (await GetDbSetAsync())
.WhereIf(userId.HasValue, x => x.UserId == userId)
.WhereIf(!device.IsNullOrWhiteSpace(), x => x.Device == device)
.WhereIf(!clientId.IsNullOrWhiteSpace(), x => x.ClientId == clientId)
.LongCountAsync(GetCancellationToken(cancellationToken));
}
public virtual async Task DeleteAllAsync(Guid userId, Guid? exceptSessionId = null, CancellationToken cancellationToken = default)
{
await DeleteAsync(x => x.UserId == userId && x.Id != exceptSessionId, cancellationToken: cancellationToken);
}
public virtual async Task DeleteAllAsync(Guid userId, string device, Guid? exceptSessionId = null, CancellationToken cancellationToken = default)
{
await DeleteAsync(x => x.UserId == userId && x.Device == device && x.Id != exceptSessionId, cancellationToken: cancellationToken);
}
public virtual async Task DeleteAllAsync(TimeSpan inactiveTimeSpan, CancellationToken cancellationToken = default)
{
var now = LazyServiceProvider.LazyGetRequiredService<IClock>().Now;
await DeleteDirectAsync(x => x.LastAccessed == null || x.LastAccessed < now.Subtract(inactiveTimeSpan), cancellationToken: cancellationToken);
}
}

2
modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IIdentityDbContext.cs

@ -20,4 +20,6 @@ public interface IIdentityDbContext : IEfCoreDbContext
DbSet<IdentityLinkUser> LinkUsers { get; } DbSet<IdentityLinkUser> LinkUsers { get; }
DbSet<IdentityUserDelegation> UserDelegations { get; } DbSet<IdentityUserDelegation> UserDelegations { get; }
DbSet<IdentitySession> Sessions { get; }
} }

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

@ -24,6 +24,8 @@ public class IdentityDbContext : AbpDbContext<IdentityDbContext>, IIdentityDbCon
public DbSet<IdentityUserDelegation> UserDelegations { get; set; } public DbSet<IdentityUserDelegation> UserDelegations { get; set; }
public DbSet<IdentitySession> Sessions { get; set; }
public IdentityDbContext(DbContextOptions<IdentityDbContext> options) public IdentityDbContext(DbContextOptions<IdentityDbContext> options)
: base(options) : base(options)
{ {

19
modules/identity/src/Volo.Abp.Identity.EntityFrameworkCore/Volo/Abp/Identity/EntityFrameworkCore/IdentityDbContextModelBuilderExtensions.cs

@ -279,6 +279,25 @@ public static class IdentityDbContextModelBuilderExtensions
b.ApplyObjectExtensionMappings(); b.ApplyObjectExtensionMappings();
}); });
builder.Entity<IdentitySession>(b =>
{
b.ToTable(AbpIdentityDbProperties.DbTablePrefix + "Sessions", AbpIdentityDbProperties.DbSchema);
b.ConfigureByConvention();
b.Property(x => x.SessionId).HasMaxLength(IdentitySessionConsts.MaxSessionIdLength).IsRequired();
b.Property(x => x.Device).HasMaxLength(IdentitySessionConsts.MaxDeviceLength).IsRequired();
b.Property(x => x.DeviceInfo).HasMaxLength(IdentitySessionConsts.MaxDeviceInfoLength);
b.Property(x => x.ClientId).HasMaxLength(IdentitySessionConsts.MaxClientIdLength);
b.Property(x => x.IpAddresses).HasMaxLength(IdentitySessionConsts.MaxIpAddressesLength);
b.HasIndex(x => x.SessionId);
b.HasIndex(x => x.Device );
b.HasIndex(x => new { x.TenantId, x.UserId });
b.ApplyObjectExtensionMappings();
});
builder.TryConfigureObjectExtensions<IdentityDbContext>(); builder.TryConfigureObjectExtensions<IdentityDbContext>();
} }
} }

2
modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/AbpIdentityMongoDbContext.cs

@ -21,6 +21,8 @@ public class AbpIdentityMongoDbContext : AbpMongoDbContext, IAbpIdentityMongoDbC
public IMongoCollection<IdentityUserDelegation> UserDelegations => Collection<IdentityUserDelegation>(); public IMongoCollection<IdentityUserDelegation> UserDelegations => Collection<IdentityUserDelegation>();
public IMongoCollection<IdentitySession> Sessions => Collection<IdentitySession>();
protected override void CreateModel(IMongoModelBuilder modelBuilder) protected override void CreateModel(IMongoModelBuilder modelBuilder)
{ {
base.CreateModel(modelBuilder); base.CreateModel(modelBuilder);

5
modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/AbpIdentityMongoDbContextExtensions.cs

@ -42,5 +42,10 @@ public static class AbpIdentityMongoDbContextExtensions
{ {
b.CollectionName = AbpIdentityDbProperties.DbTablePrefix + "UserDelegations"; b.CollectionName = AbpIdentityDbProperties.DbTablePrefix + "UserDelegations";
}); });
builder.Entity<IdentitySession>(b =>
{
b.CollectionName = AbpIdentityDbProperties.DbTablePrefix + "Sessions";
});
} }
} }

1
modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/AbpIdentityMongoDbModule.cs

@ -21,6 +21,7 @@ public class AbpIdentityMongoDbModule : AbpModule
options.AddRepository<IdentitySecurityLog, MongoIdentitySecurityLogRepository>(); options.AddRepository<IdentitySecurityLog, MongoIdentitySecurityLogRepository>();
options.AddRepository<IdentityLinkUser, MongoIdentityLinkUserRepository>(); options.AddRepository<IdentityLinkUser, MongoIdentityLinkUserRepository>();
options.AddRepository<IdentityUserDelegation, MongoIdentityUserDelegationRepository>(); options.AddRepository<IdentityUserDelegation, MongoIdentityUserDelegationRepository>();
options.AddRepository<IdentitySession, MongoIdentitySessionRepository>();
}); });
} }
} }

2
modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/IAbpIdentityMongoDbContext.cs

@ -20,4 +20,6 @@ public interface IAbpIdentityMongoDbContext : IAbpMongoDbContext
IMongoCollection<IdentityLinkUser> LinkUsers { get; } IMongoCollection<IdentityLinkUser> LinkUsers { get; }
IMongoCollection<IdentityUserDelegation> UserDelegations { get; } IMongoCollection<IdentityUserDelegation> UserDelegations { get; }
IMongoCollection<IdentitySession> Sessions { get; }
} }

2
modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentitySecurityLogRepository.cs

@ -21,7 +21,7 @@ public class MongoIdentitySecurityLogRepository :
public virtual async Task<List<IdentitySecurityLog>> GetListAsync( public virtual async Task<List<IdentitySecurityLog>> GetListAsync(
string sorting = null, string sorting = null,
int maxResultCount = 50, int maxResultCount = int.MaxValue,
int skipCount = 0, int skipCount = 0,
DateTime? startTime = null, DateTime? startTime = null,
DateTime? endTime = null, DateTime? endTime = null,

90
modules/identity/src/Volo.Abp.Identity.MongoDB/Volo/Abp/Identity/MongoDB/MongoIdentitySessionRepository.cs

@ -0,0 +1,90 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Dynamic.Core;
using System.Threading;
using System.Threading.Tasks;
using MongoDB.Driver;
using MongoDB.Driver.Linq;
using Volo.Abp.Domain.Entities;
using Volo.Abp.Domain.Repositories.MongoDB;
using Volo.Abp.MongoDB;
using Volo.Abp.Timing;
namespace Volo.Abp.Identity.MongoDB;
public class MongoIdentitySessionRepository : MongoDbRepository<IAbpIdentityMongoDbContext, IdentitySession, Guid>, IIdentitySessionRepository
{
public MongoIdentitySessionRepository(IMongoDbContextProvider<IAbpIdentityMongoDbContext> dbContextProvider)
: base(dbContextProvider)
{
}
public virtual async Task<IdentitySession> FindAsync(string sessionId, CancellationToken cancellationToken = default)
{
return await (await GetMongoQueryableAsync(GetCancellationToken(cancellationToken)))
.As<IMongoQueryable<IdentitySession>>()
.FirstOrDefaultAsync(x => x.SessionId == sessionId, GetCancellationToken(cancellationToken));
}
public virtual async Task<IdentitySession> GetAsync(string sessionId, CancellationToken cancellationToken = default)
{
var session = await FindAsync(sessionId, cancellationToken);
if (session == null)
{
throw new EntityNotFoundException(typeof(IdentitySession));
}
return session;
}
public virtual async Task<List<IdentitySession>> GetListAsync(
string sorting = null,
int maxResultCount = int.MaxValue,
int skipCount = 0,
Guid? userId = null,
string device = null,
string clientId = null,
CancellationToken cancellationToken = default)
{
return await (await GetMongoQueryableAsync(GetCancellationToken(cancellationToken)))
.WhereIf(userId.HasValue, x => x.UserId == userId)
.WhereIf(!device.IsNullOrWhiteSpace(), x => x.Device == device)
.WhereIf(!clientId.IsNullOrWhiteSpace(), x => x.ClientId == clientId)
.OrderBy(sorting.IsNullOrWhiteSpace() ? $"{nameof(IdentitySession.LastAccessed)} desc" : sorting)
.PageBy(skipCount, maxResultCount)
.As<IMongoQueryable<IdentitySession>>()
.ToListAsync(GetCancellationToken(cancellationToken));
}
public virtual async Task<long> GetCountAsync(
Guid? userId = null,
string device = null,
string clientId = null,
CancellationToken cancellationToken = default)
{
return await (await GetMongoQueryableAsync(GetCancellationToken(cancellationToken)))
.WhereIf(userId.HasValue, x => x.UserId == userId)
.WhereIf(!device.IsNullOrWhiteSpace(), x => x.Device == device)
.WhereIf(!clientId.IsNullOrWhiteSpace(), x => x.ClientId == clientId)
.As<IMongoQueryable<IdentitySession>>()
.LongCountAsync(GetCancellationToken(cancellationToken));
}
public virtual async Task DeleteAllAsync(Guid userId, Guid? exceptSessionId = null, CancellationToken cancellationToken = default)
{
await DeleteAsync(x => x.UserId == userId && x.Id != exceptSessionId, cancellationToken: cancellationToken);
}
public virtual async Task DeleteAllAsync(Guid userId, string device, Guid? exceptSessionId = null, CancellationToken cancellationToken = default)
{
await DeleteAsync(x => x.UserId == userId && x.Device == device && x.Id != exceptSessionId, cancellationToken: cancellationToken);
}
public virtual async Task DeleteAllAsync(TimeSpan inactiveTimeSpan, CancellationToken cancellationToken = default)
{
var now = LazyServiceProvider.LazyGetRequiredService<IClock>().Now;
await DeleteDirectAsync(x => x.LastAccessed == null || x.LastAccessed < now.Subtract(inactiveTimeSpan), cancellationToken: cancellationToken);
}
}

6
modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/Claims/AbpDefaultOpenIddictClaimsPrincipalHandler.cs

@ -26,6 +26,12 @@ public class AbpDefaultOpenIddictClaimsPrincipalHandler : IAbpOpenIddictClaimsPr
continue; continue;
} }
if (claim.Type == AbpClaimTypes.SessionId)
{
claim.SetDestinations(OpenIddictConstants.Destinations.AccessToken, OpenIddictConstants.Destinations.IdentityToken);
continue;
}
switch (claim.Type) switch (claim.Type)
{ {
case OpenIddictConstants.Claims.PreferredUsername: case OpenIddictConstants.Claims.PreferredUsername:

6
npm/ng-packs/packages/account-core/ng-package.json

@ -3,5 +3,9 @@
"dest": "../../dist/packages/account-core", "dest": "../../dist/packages/account-core",
"lib": { "lib": {
"entryFile": "src/public-api.ts" "entryFile": "src/public-api.ts"
} },
"allowedNonPeerDependencies": [
"@abp/ng.core",
"@abp/ng.theme.shared"
]
} }

6
npm/ng-packs/packages/account-core/package.json

@ -6,13 +6,9 @@
"type": "git", "type": "git",
"url": "https://github.com/abpframework/abp.git" "url": "https://github.com/abpframework/abp.git"
}, },
"peerDependencies": { "dependencies": {
"@abp/ng.core": "~8.1.0-rc.3", "@abp/ng.core": "~8.1.0-rc.3",
"@abp/ng.theme.shared": "~8.1.0-rc.3", "@abp/ng.theme.shared": "~8.1.0-rc.3",
"@angular/common": ">=12.0.0",
"@angular/core": ">=12.0.0"
},
"dependencies": {
"tslib": "^2.0.0" "tslib": "^2.0.0"
}, },
"publishConfig": { "publishConfig": {

31
npm/ng-packs/packages/account/src/lib/components/personal-settings/personal-settings.component.ts

@ -1,6 +1,6 @@
import { ProfileDto, ProfileService } from '@abp/ng.account.core/proxy'; import { ProfileDto, ProfileService } from '@abp/ng.account.core/proxy';
import { Confirmation, ConfirmationService, ToasterService } from '@abp/ng.theme.shared'; import { Confirmation, ConfirmationService, ToasterService } from '@abp/ng.theme.shared';
import { Component, Inject, Injector, OnInit, ViewEncapsulation } from '@angular/core'; import { Component, inject, Injector, OnInit } from '@angular/core';
import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms'; import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
import { finalize, filter } from 'rxjs/operators'; import { finalize, filter } from 'rxjs/operators';
import { Account } from '../../models/account'; import { Account } from '../../models/account';
@ -31,25 +31,24 @@ export class PersonalSettingsComponent
Account.PersonalSettingsComponentInputs, Account.PersonalSettingsComponentInputs,
Account.PersonalSettingsComponentOutputs Account.PersonalSettingsComponentOutputs
{ {
private readonly fb = inject(UntypedFormBuilder);
protected readonly toasterService = inject(ToasterService);
protected readonly profileService = inject(ProfileService);
protected readonly manageProfileState = inject(ManageProfileStateService);
protected readonly authService = inject(AuthService);
protected readonly confirmationService = inject(ConfirmationService);
protected readonly configState = inject(ConfigStateService);
protected readonly isPersonalSettingsChangedConfirmationActive = inject(
RE_LOGIN_CONFIRMATION_TOKEN,
);
private readonly injector = inject(Injector);
selected?: ProfileDto; selected?: ProfileDto;
form!: UntypedFormGroup; form!: UntypedFormGroup;
inProgress?: boolean; inProgress?: boolean;
constructor(
private fb: UntypedFormBuilder,
private toasterService: ToasterService,
private profileService: ProfileService,
private manageProfileState: ManageProfileStateService,
private readonly authService: AuthService,
private confirmationService: ConfirmationService,
private configState: ConfigStateService,
@Inject(RE_LOGIN_CONFIRMATION_TOKEN)
private isPersonalSettingsChangedConfirmationActive: boolean,
protected injector: Injector,
) {}
buildForm() { buildForm() {
this.selected = this.manageProfileState.getProfile(); this.selected = this.manageProfileState.getProfile();
if (!this.selected) { if (!this.selected) {
@ -76,10 +75,10 @@ export class PersonalSettingsComponent
this.configState.refreshAppState(); this.configState.refreshAppState();
this.toasterService.success('AbpAccount::PersonalSettingsSaved', 'Success', { life: 5000 }); this.toasterService.success('AbpAccount::PersonalSettingsSaved', 'Success', { life: 5000 });
if(isRefreshTokenExists){ if (isRefreshTokenExists) {
return this.authService.refreshToken(); return this.authService.refreshToken();
} }
if (isLogOutConfirmMessageVisible) { if (isLogOutConfirmMessageVisible) {
this.showLogoutConfirmMessage(); this.showLogoutConfirmMessage();
} }

2
npm/ng-packs/packages/components/extensible/src/lib/components/extensible-table/extensible-table.component.html

@ -3,8 +3,6 @@
[rows]="data" [rows]="data"
[count]="recordsTotal" [count]="recordsTotal"
[list]="list" [list]="list"
[offset]="list?.page"
(page)="setPage($event)"
(activate)="tableActivate.emit($event)" (activate)="tableActivate.emit($event)"
> >
@if (actionsTemplate || (actionList.length && hasAtLeastOnePermittedAction)) { @if (actionsTemplate || (actionList.length && hasAtLeastOnePermittedAction)) {

74
npm/ng-packs/packages/components/extensible/src/lib/components/extensible-table/extensible-table.component.ts

@ -1,20 +1,3 @@
import {
ABP,
ConfigStateService,
getShortDateFormat,
getShortDateShortTimeFormat,
getShortTimeFormat,
ListService,
LocalizationModule,
PermissionDirective,
PermissionService,
} from '@abp/ng.core';
import {
AsyncPipe,
formatDate,
NgComponentOutlet,
NgTemplateOutlet,
} from '@angular/common';
import { import {
ChangeDetectionStrategy, ChangeDetectionStrategy,
Component, Component,
@ -29,8 +12,31 @@ import {
TemplateRef, TemplateRef,
TrackByFunction, TrackByFunction,
} from '@angular/core'; } from '@angular/core';
import { AsyncPipe, formatDate, NgComponentOutlet, NgTemplateOutlet } from '@angular/common';
import { Observable } from 'rxjs'; import { Observable } from 'rxjs';
import { map } from 'rxjs/operators'; import { map } from 'rxjs/operators';
import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap';
import { NgxDatatableModule } from '@swimlane/ngx-datatable';
import {
ABP,
ConfigStateService,
getShortDateFormat,
getShortDateShortTimeFormat,
getShortTimeFormat,
ListService,
LocalizationModule,
PermissionDirective,
PermissionService,
} from '@abp/ng.core';
import {
AbpVisibleDirective,
NgxDatatableDefaultDirective,
NgxDatatableListDirective,
} from '@abp/ng.theme.shared';
import { ePropType } from '../../enums/props.enum'; import { ePropType } from '../../enums/props.enum';
import { EntityActionList } from '../../models/entity-actions'; import { EntityActionList } from '../../models/entity-actions';
import { EntityProp, EntityPropList } from '../../models/entity-props'; import { EntityProp, EntityPropList } from '../../models/entity-props';
@ -41,14 +47,7 @@ import {
EXTENSIONS_IDENTIFIER, EXTENSIONS_IDENTIFIER,
PROP_DATA_STREAM, PROP_DATA_STREAM,
} from '../../tokens/extensions.token'; } from '../../tokens/extensions.token';
import { NgxDatatableModule } from '@swimlane/ngx-datatable';
import { GridActionsComponent } from '../grid-actions/grid-actions.component'; import { GridActionsComponent } from '../grid-actions/grid-actions.component';
import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap';
import {
AbpVisibleDirective,
NgxDatatableDefaultDirective,
NgxDatatableListDirective,
} from '@abp/ng.theme.shared';
const DEFAULT_ACTIONS_COLUMN_WIDTH = 150; const DEFAULT_ACTIONS_COLUMN_WIDTH = 150;
@ -172,32 +171,7 @@ export class ExtensibleTableComponent<R = any> implements OnChanges {
); );
} }
setPage({ offset }) { ngOnChanges({ data }: SimpleChanges) {
this.list.page = offset;
}
ngOnChanges({ data, recordsTotal }: SimpleChanges) {
if (data?.currentValue.length < 1 && recordsTotal?.currentValue > 0) {
let maxPage = Math.floor(Number(recordsTotal?.currentValue / this.list.maxResultCount));
if(recordsTotal?.currentValue < this.list.maxResultCount) {
this.list.page = 0;
return;
}
if (recordsTotal?.currentValue % this.list.maxResultCount === 0) {
maxPage -= 1;
}
if (this.list.page < maxPage) {
this.list.page = this.list.page;
return;
}
this.list.page = maxPage;
return;
}
if (!data?.currentValue) return; if (!data?.currentValue) return;
if (data.currentValue.length < 1) { if (data.currentValue.length < 1) {

17
npm/ng-packs/packages/feature-management/src/lib/components/feature-management/feature-management.component.ts

@ -11,7 +11,7 @@ import {
LocaleDirection, LocaleDirection,
ToasterService, ToasterService,
} from '@abp/ng.theme.shared'; } from '@abp/ng.theme.shared';
import { Component, EventEmitter, Input, Output } from '@angular/core'; import { Component, EventEmitter, Input, Output, inject } from '@angular/core';
import { finalize } from 'rxjs/operators'; import { finalize } from 'rxjs/operators';
import { FeatureManagement } from '../../models/feature-management'; import { FeatureManagement } from '../../models/feature-management';
@ -31,6 +31,12 @@ export class FeatureManagementComponent
FeatureManagement.FeatureManagementComponentInputs, FeatureManagement.FeatureManagementComponentInputs,
FeatureManagement.FeatureManagementComponentOutputs FeatureManagement.FeatureManagementComponentOutputs
{ {
protected readonly track = inject(TrackByService);
protected readonly toasterService = inject(ToasterService);
protected readonly service = inject(FeaturesService);
protected readonly configState = inject(ConfigStateService);
protected readonly confirmationService = inject(ConfirmationService);
@Input() @Input()
providerKey: string; providerKey: string;
@ -72,14 +78,6 @@ export class FeatureManagementComponent
modalBusy = false; modalBusy = false;
constructor(
public readonly track: TrackByService,
private toasterService: ToasterService,
protected service: FeaturesService,
protected configState: ConfigStateService,
protected confirmationService: ConfirmationService,
) {}
openModal() { openModal() {
if (!this.providerName) { if (!this.providerName) {
throw new Error('providerName is required.'); throw new Error('providerName is required.');
@ -127,6 +125,7 @@ export class FeatureManagementComponent
.subscribe(() => { .subscribe(() => {
this.visible = false; this.visible = false;
this.toasterService.success('AbpFeatureManagement::Saved');
if (!this.providerKey) { if (!this.providerKey) {
// to refresh host's features // to refresh host's features
this.configState.refreshAppState().subscribe(); this.configState.refreshAppState().subscribe();

21
npm/ng-packs/packages/identity/src/lib/components/roles/roles.component.ts

@ -1,13 +1,13 @@
import { ListService, PagedAndSortedResultRequestDto, PagedResultDto } from '@abp/ng.core'; import { ListService, PagedAndSortedResultRequestDto, PagedResultDto } from '@abp/ng.core';
import { IdentityRoleDto, IdentityRoleService } from '@abp/ng.identity/proxy'; import { IdentityRoleDto, IdentityRoleService } from '@abp/ng.identity/proxy';
import { ePermissionManagementComponents } from '@abp/ng.permission-management'; import { ePermissionManagementComponents } from '@abp/ng.permission-management';
import {Confirmation, ConfirmationService, ToasterService} from '@abp/ng.theme.shared'; import { Confirmation, ConfirmationService, ToasterService } from '@abp/ng.theme.shared';
import { import {
EXTENSIONS_IDENTIFIER, EXTENSIONS_IDENTIFIER,
FormPropData, FormPropData,
generateFormFromProps, generateFormFromProps,
} from '@abp/ng.components/extensible'; } from '@abp/ng.components/extensible';
import { Component, Injector, OnInit } from '@angular/core'; import { Component, inject, Injector, OnInit } from '@angular/core';
import { UntypedFormGroup } from '@angular/forms'; import { UntypedFormGroup } from '@angular/forms';
import { finalize } from 'rxjs/operators'; import { finalize } from 'rxjs/operators';
import { eIdentityComponents } from '../../enums/components'; import { eIdentityComponents } from '../../enums/components';
@ -24,6 +24,12 @@ import { eIdentityComponents } from '../../enums/components';
], ],
}) })
export class RolesComponent implements OnInit { export class RolesComponent implements OnInit {
protected readonly list = inject(ListService<PagedAndSortedResultRequestDto>);
protected readonly confirmationService = inject(ConfirmationService);
protected readonly toasterService = inject(ToasterService);
private readonly injector = inject(Injector);
protected readonly service = inject(IdentityRoleService);
data: PagedResultDto<IdentityRoleDto> = { items: [], totalCount: 0 }; data: PagedResultDto<IdentityRoleDto> = { items: [], totalCount: 0 };
form!: UntypedFormGroup; form!: UntypedFormGroup;
@ -44,14 +50,6 @@ export class RolesComponent implements OnInit {
this.visiblePermissions = event; this.visiblePermissions = event;
}; };
constructor(
public readonly list: ListService<PagedAndSortedResultRequestDto>,
protected confirmationService: ConfirmationService,
private toasterService: ToasterService,
protected injector: Injector,
protected service: IdentityRoleService,
) {}
ngOnInit() { ngOnInit() {
this.hookToQuery(); this.hookToQuery();
} }
@ -90,6 +88,7 @@ export class RolesComponent implements OnInit {
.pipe(finalize(() => (this.modalBusy = false))) .pipe(finalize(() => (this.modalBusy = false)))
.subscribe(() => { .subscribe(() => {
this.isModalVisible = false; this.isModalVisible = false;
this.toasterService.success('AbpUi::SavedSuccessfully');
this.list.get(); this.list.get();
}); });
} }
@ -101,7 +100,7 @@ export class RolesComponent implements OnInit {
}) })
.subscribe((status: Confirmation.Status) => { .subscribe((status: Confirmation.Status) => {
if (status === Confirmation.Status.confirm) { if (status === Confirmation.Status.confirm) {
this.toasterService.success('AbpUi::SuccessfullyDeleted'); this.toasterService.success('AbpUi::DeletedSuccessfully');
this.service.delete(id).subscribe(() => this.list.get()); this.service.delete(id).subscribe(() => this.list.get());
} }
}); });

36
npm/ng-packs/packages/identity/src/lib/components/users/users.component.ts

@ -6,7 +6,12 @@ import {
IdentityUserService, IdentityUserService,
} from '@abp/ng.identity/proxy'; } from '@abp/ng.identity/proxy';
import { ePermissionManagementComponents } from '@abp/ng.permission-management'; import { ePermissionManagementComponents } from '@abp/ng.permission-management';
import {Confirmation, ConfirmationService, eFormComponets, ToasterService} from '@abp/ng.theme.shared'; import {
Confirmation,
ConfirmationService,
eFormComponets,
ToasterService,
} from '@abp/ng.theme.shared';
import { import {
EXTENSIONS_IDENTIFIER, EXTENSIONS_IDENTIFIER,
FormPropData, FormPropData,
@ -14,13 +19,19 @@ import {
} from '@abp/ng.components/extensible'; } from '@abp/ng.components/extensible';
import { import {
Component, Component,
inject,
Injector, Injector,
OnInit, OnInit,
TemplateRef, TemplateRef,
TrackByFunction, TrackByFunction,
ViewChild, ViewChild,
} from '@angular/core'; } from '@angular/core';
import { AbstractControl, UntypedFormArray, UntypedFormBuilder, UntypedFormGroup } from '@angular/forms'; import {
AbstractControl,
UntypedFormArray,
UntypedFormBuilder,
UntypedFormGroup,
} from '@angular/forms';
import { finalize, switchMap, tap } from 'rxjs/operators'; import { finalize, switchMap, tap } from 'rxjs/operators';
import { eIdentityComponents } from '../../enums/components'; import { eIdentityComponents } from '../../enums/components';
@ -36,6 +47,13 @@ import { eIdentityComponents } from '../../enums/components';
], ],
}) })
export class UsersComponent implements OnInit { export class UsersComponent implements OnInit {
protected readonly list = inject(ListService<GetIdentityUsersInput>);
protected readonly confirmationService = inject(ConfirmationService);
protected readonly service = inject(IdentityUserService);
protected readonly toasterService = inject(ToasterService);
private readonly fb = inject(UntypedFormBuilder);
private readonly injector = inject(Injector);
data: PagedResultDto<IdentityUserDto> = { items: [], totalCount: 0 }; data: PagedResultDto<IdentityUserDto> = { items: [], totalCount: 0 };
@ViewChild('modalContent', { static: false }) @ViewChild('modalContent', { static: false })
@ -61,7 +79,7 @@ export class UsersComponent implements OnInit {
entityDisplayName: string; entityDisplayName: string;
inputKey=eFormComponets.FormCheckboxComponent inputKey = eFormComponets.FormCheckboxComponent;
trackByFn: TrackByFunction<AbstractControl> = (index, item) => Object.keys(item)[0] || index; trackByFn: TrackByFunction<AbstractControl> = (index, item) => Object.keys(item)[0] || index;
@ -73,15 +91,6 @@ export class UsersComponent implements OnInit {
return ((this.form.get('roleNames') as UntypedFormArray)?.controls as UntypedFormGroup[]) || []; return ((this.form.get('roleNames') as UntypedFormArray)?.controls as UntypedFormGroup[]) || [];
} }
constructor(
public readonly list: ListService<GetIdentityUsersInput>,
protected confirmationService: ConfirmationService,
protected service: IdentityUserService,
private toasterService: ToasterService,
protected fb: UntypedFormBuilder,
protected injector: Injector,
) {}
ngOnInit() { ngOnInit() {
this.hookToQuery(); this.hookToQuery();
} }
@ -158,6 +167,7 @@ export class UsersComponent implements OnInit {
.pipe(finalize(() => (this.modalBusy = false))) .pipe(finalize(() => (this.modalBusy = false)))
.subscribe(() => { .subscribe(() => {
this.isModalVisible = false; this.isModalVisible = false;
this.toasterService.success('AbpUi::SavedSuccessfully');
this.list.get(); this.list.get();
}); });
} }
@ -170,7 +180,7 @@ export class UsersComponent implements OnInit {
.subscribe((status: Confirmation.Status) => { .subscribe((status: Confirmation.Status) => {
if (status === Confirmation.Status.confirm) { if (status === Confirmation.Status.confirm) {
this.service.delete(id).subscribe(() => { this.service.delete(id).subscribe(() => {
this.toasterService.success('AbpUi::SuccessfullyDeleted'); this.toasterService.success('AbpUi::DeletedSuccessfully');
this.list.get(); this.list.get();
}); });
} }

48
npm/ng-packs/packages/permission-management/src/lib/components/permission-management.component.ts

@ -7,11 +7,12 @@ import {
ProviderInfoDto, ProviderInfoDto,
UpdatePermissionDto, UpdatePermissionDto,
} from '@abp/ng.permission-management/proxy'; } from '@abp/ng.permission-management/proxy';
import { LocaleDirection } from '@abp/ng.theme.shared'; import { LocaleDirection, ToasterService } from '@abp/ng.theme.shared';
import { import {
Component, Component,
ElementRef, ElementRef,
EventEmitter, EventEmitter,
inject,
Input, Input,
Output, Output,
QueryList, QueryList,
@ -41,16 +42,21 @@ type PermissionWithGroupName = PermissionGrantInfoDto & {
overflow-y: scroll; overflow-y: scroll;
} }
.scroll-in-modal { .scroll-in-modal {
overflow:auto; overflow: auto;
max-height: calc(100vh - 15rem) max-height: calc(100vh - 15rem);
} }
`, `,
], ],
}) })
export class PermissionManagementComponent export class PermissionManagementComponent
implements implements
PermissionManagement.PermissionManagementComponentInputs, PermissionManagement.PermissionManagementComponentInputs,
PermissionManagement.PermissionManagementComponentOutputs { PermissionManagement.PermissionManagementComponentOutputs
{
protected readonly service = inject(PermissionsService);
protected readonly configState = inject(ConfigStateService);
protected readonly toasterService = inject(ToasterService);
@Input() @Input()
readonly providerName!: string; readonly providerName!: string;
@ -117,8 +123,6 @@ export class PermissionManagementComponent
trackByFn: TrackByFunction<PermissionGroupDto> = (_, item) => item.name; trackByFn: TrackByFunction<PermissionGroupDto> = (_, item) => item.name;
constructor(protected service: PermissionsService, protected configState: ConfigStateService) { }
getChecked(name: string) { getChecked(name: string) {
return (this.permissions.find(per => per.name === name) || { isGranted: false }).isGranted; return (this.permissions.find(per => per.name === name) || { isGranted: false }).isGranted;
} }
@ -130,19 +134,20 @@ export class PermissionManagementComponent
return; return;
} }
const margin = `margin-${(document.body.dir as LocaleDirection) === 'rtl' ? 'right' : 'left' const margin = `margin-${
}.px`; (document.body.dir as LocaleDirection) === 'rtl' ? 'right' : 'left'
}.px`;
const permissions = const permissions =
(this.data.groups.find(group => group.name === this.selectedGroup?.name) || {}).permissions || (this.data.groups.find(group => group.name === this.selectedGroup?.name) || {}).permissions ||
[]; [];
this.selectedGroupPermissions = permissions.map( this.selectedGroupPermissions = permissions.map(
permission => permission =>
({ ({
...permission, ...permission,
style: { [margin]: findMargin(permissions, permission) }, style: { [margin]: findMargin(permissions, permission) },
isGranted: (this.permissions.find(per => per.name === permission.name) || {}).isGranted, isGranted: (this.permissions.find(per => per.name === permission.name) || {}).isGranted,
} as unknown as PermissionWithStyle), }) as unknown as PermissionWithStyle,
); );
} }
@ -199,19 +204,19 @@ export class PermissionManagementComponent
if (per.name === clickedPermissions.parentName) { if (per.name === clickedPermissions.parentName) {
parentPermission = per; parentPermission = per;
} }
}) });
this.permissions.forEach(per => { this.permissions.forEach(per => {
if (parentPermission.name === per.parentName) { if (parentPermission.name === per.parentName) {
per.isGranted && childPermissionGrantedCount++; per.isGranted && childPermissionGrantedCount++;
} }
}) });
if (childPermissionGrantedCount === 1 && !parentPermission.isGranted) { if (childPermissionGrantedCount === 1 && !parentPermission.isGranted) {
this.permissions = this.permissions.map(per => { this.permissions = this.permissions.map(per => {
if (per.name === parentPermission.name) { if (per.name === parentPermission.name) {
per.isGranted = true; per.isGranted = true;
} }
return per; return per;
}) });
} }
return; return;
} }
@ -220,16 +225,16 @@ export class PermissionManagementComponent
per.isGranted = false; per.isGranted = false;
} }
return per; return per;
}) });
} }
updateSelectedGroupPermissions(clickedPermissions: PermissionGrantInfoDto) { updateSelectedGroupPermissions(clickedPermissions: PermissionGrantInfoDto) {
this.selectedGroupPermissions = this.selectedGroupPermissions.map(per => { this.selectedGroupPermissions = this.selectedGroupPermissions.map(per => {
if (per.name === clickedPermissions.name) { if (per.name === clickedPermissions.name) {
per.isGranted = !per.isGranted per.isGranted = !per.isGranted;
} }
return per; return per;
}) });
} }
setTabCheckboxState() { setTabCheckboxState() {
@ -310,7 +315,7 @@ export class PermissionManagementComponent
const changedPermissions: UpdatePermissionDto[] = this.permissions const changedPermissions: UpdatePermissionDto[] = this.permissions
.filter(per => .filter(per =>
(unchangedPermissions.find(unchanged => unchanged.name === per.name) || {}).isGranted === (unchangedPermissions.find(unchanged => unchanged.name === per.name) || {}).isGranted ===
per.isGranted per.isGranted
? false ? false
: true, : true,
) )
@ -332,6 +337,7 @@ export class PermissionManagementComponent
) )
.subscribe(() => { .subscribe(() => {
this.visible = false; this.visible = false;
this.toasterService.success('AbpUi::SavedSuccessfully');
}); });
} }

23
npm/ng-packs/packages/tenant-management/src/lib/components/tenants/tenants.component.ts

@ -1,13 +1,13 @@
import { ListService, PagedResultDto } from '@abp/ng.core'; import { ListService, PagedResultDto } from '@abp/ng.core';
import { eFeatureManagementComponents } from '@abp/ng.feature-management'; import { eFeatureManagementComponents } from '@abp/ng.feature-management';
import { GetTenantsInput, TenantDto, TenantService } from '@abp/ng.tenant-management/proxy'; import { GetTenantsInput, TenantDto, TenantService } from '@abp/ng.tenant-management/proxy';
import {Confirmation, ConfirmationService, ToasterService} from '@abp/ng.theme.shared'; import { Confirmation, ConfirmationService, ToasterService } from '@abp/ng.theme.shared';
import { import {
EXTENSIONS_IDENTIFIER, EXTENSIONS_IDENTIFIER,
FormPropData, FormPropData,
generateFormFromProps, generateFormFromProps,
} from '@abp/ng.components/extensible'; } from '@abp/ng.components/extensible';
import { Component, Injector, OnInit } from '@angular/core'; import { Component, inject, Injector, OnInit } from '@angular/core';
import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms'; import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
import { finalize } from 'rxjs/operators'; import { finalize } from 'rxjs/operators';
import { eTenantManagementComponents } from '../../enums/components'; import { eTenantManagementComponents } from '../../enums/components';
@ -24,6 +24,13 @@ import { eTenantManagementComponents } from '../../enums/components';
], ],
}) })
export class TenantsComponent implements OnInit { export class TenantsComponent implements OnInit {
protected readonly list = inject(ListService<GetTenantsInput>);
protected readonly confirmationService = inject(ConfirmationService);
protected readonly service = inject(TenantService);
protected readonly toasterService = inject(ToasterService);
private readonly fb = inject(UntypedFormBuilder);
private readonly injector = inject(Injector);
data: PagedResultDto<TenantDto> = { items: [], totalCount: 0 }; data: PagedResultDto<TenantDto> = { items: [], totalCount: 0 };
selected!: TenantDto; selected!: TenantDto;
@ -48,15 +55,6 @@ export class TenantsComponent implements OnInit {
this.visibleFeatures = value; this.visibleFeatures = value;
}; };
constructor(
public readonly list: ListService<GetTenantsInput>,
private injector: Injector,
private confirmationService: ConfirmationService,
private service: TenantService,
private toasterService: ToasterService,
private fb: UntypedFormBuilder,
) {}
ngOnInit() { ngOnInit() {
this.hookToQuery(); this.hookToQuery();
} }
@ -93,6 +91,7 @@ export class TenantsComponent implements OnInit {
.pipe(finalize(() => (this.modalBusy = false))) .pipe(finalize(() => (this.modalBusy = false)))
.subscribe(() => { .subscribe(() => {
this.isModalVisible = false; this.isModalVisible = false;
this.toasterService.success('AbpUi::SavedSuccessfully');
this.list.get(); this.list.get();
}); });
} }
@ -108,7 +107,7 @@ export class TenantsComponent implements OnInit {
) )
.subscribe((status: Confirmation.Status) => { .subscribe((status: Confirmation.Status) => {
if (status === Confirmation.Status.confirm) { if (status === Confirmation.Status.confirm) {
this.toasterService.success('AbpUi::SuccessfullyDeleted'); this.toasterService.success('AbpUi::DeletedSuccessfully');
this.service.delete(id).subscribe(() => this.list.get()); this.service.delete(id).subscribe(() => this.list.get());
} }
}); });

99
npm/ng-packs/packages/theme-shared/src/lib/directives/ngx-datatable-list.directive.ts

@ -1,20 +1,19 @@
import { ListService, LocalizationService } from '@abp/ng.core';
import { import {
ChangeDetectorRef, ChangeDetectorRef,
Directive, Directive,
Inject,
Input, Input,
OnChanges, OnChanges,
OnDestroy,
OnInit, OnInit,
Optional, DoCheck,
SimpleChanges, SimpleChanges,
inject,
DestroyRef
} from '@angular/core'; } from '@angular/core';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { DatatableComponent } from '@swimlane/ngx-datatable'; import { DatatableComponent } from '@swimlane/ngx-datatable';
import { Subscription } from 'rxjs'; import { ListService, LocalizationService } from '@abp/ng.core';
import { import {
defaultNgxDatatableMessages, defaultNgxDatatableMessages,
NgxDatatableMessages,
NGX_DATATABLE_MESSAGES, NGX_DATATABLE_MESSAGES,
} from '../tokens/ngx-datatable-messages.token'; } from '../tokens/ngx-datatable-messages.token';
@ -24,22 +23,39 @@ import {
standalone: true, standalone: true,
exportAs: 'ngxDatatableList', exportAs: 'ngxDatatableList',
}) })
export class NgxDatatableListDirective implements OnChanges, OnDestroy, OnInit { export class NgxDatatableListDirective implements OnChanges, OnInit, DoCheck {
private subscription = new Subscription();
private querySubscription = new Subscription();
@Input() list!: ListService; @Input() list!: ListService;
constructor( protected readonly table = inject(DatatableComponent);
private table: DatatableComponent, protected readonly cdRef = inject(ChangeDetectorRef);
private cdRef: ChangeDetectorRef, protected readonly destroyRef = inject(DestroyRef);
private localizationService: LocalizationService, protected readonly localizationService = inject(LocalizationService);
@Optional() @Inject(NGX_DATATABLE_MESSAGES) private ngxDatatableMessages: NgxDatatableMessages, protected readonly ngxDatatableMessages = inject(NGX_DATATABLE_MESSAGES, { optional: true });
) {
constructor() {
this.setInitialValues(); this.setInitialValues();
} }
private setInitialValues() { ngDoCheck(): void {
this.refreshPageIfDataExist();
}
ngOnInit() {
this.subscribeToPage();
this.subscribeToSort();
}
ngOnChanges({ list }: SimpleChanges) {
this.subscribeToQuery();
if (!list.firstChange) return;
const { maxResultCount, page } = list.currentValue;
this.table.limit = maxResultCount;
this.table.offset = page;
}
protected setInitialValues() {
this.table.externalPaging = true; this.table.externalPaging = true;
this.table.externalSorting = true; this.table.externalSorting = true;
@ -53,8 +69,8 @@ export class NgxDatatableListDirective implements OnChanges, OnDestroy, OnInit {
}; };
} }
private subscribeToSort() { protected subscribeToSort() {
const sub = this.table.sort.subscribe(({ sorts: [{ prop, dir }] }) => { this.table.sort.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(({ sorts: [{ prop, dir }] }) => {
if (prop === this.list.sortKey && this.list.sortOrder === 'desc') { if (prop === this.list.sortKey && this.list.sortOrder === 'desc') {
this.list.sortKey = ''; this.list.sortKey = '';
this.list.sortOrder = ''; this.list.sortOrder = '';
@ -65,34 +81,45 @@ export class NgxDatatableListDirective implements OnChanges, OnDestroy, OnInit {
this.list.sortOrder = dir; this.list.sortOrder = dir;
} }
}); });
this.subscription.add(sub);
} }
private subscribeToQuery() { protected subscribeToPage() {
if (!this.querySubscription.closed) this.querySubscription.unsubscribe(); this.table.page.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(({ offset }) => {
this.setTablePage(offset);
});
}
this.querySubscription = this.list.query$.subscribe(() => { protected subscribeToQuery() {
this.list.query$.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(() => {
const offset = this.list.page; const offset = this.list.page;
if (this.table.offset !== offset) this.table.offset = offset; if (this.table.offset !== offset) this.table.offset = offset;
}); });
} }
ngOnChanges({ list }: SimpleChanges) { protected setTablePage(pageNum: number) {
this.subscribeToQuery(); this.list.page = pageNum;
this.table.offset = pageNum;
}
if (!list.firstChange) return; protected refreshPageIfDataExist() {
if (this.table.rows.length < 1 && this.table.count > 0) {
let maxPage = Math.floor(Number(this.table.count / this.list.maxResultCount));
const { maxResultCount, page } = list.currentValue; if (this.table.count < this.list.maxResultCount) {
this.table.limit = maxResultCount; this.setTablePage(0);
this.table.offset = page; return;
} }
ngOnDestroy() { if (this.table.count % this.list.maxResultCount === 0) {
this.subscription.unsubscribe(); maxPage -= 1;
this.querySubscription.unsubscribe(); }
}
ngOnInit() { if (this.list.page < maxPage) {
this.subscribeToSort(); this.setTablePage(this.list.page);
return;
}
this.setTablePage(maxPage);
}
} }
} }

2
npm/ng-packs/packages/theme-shared/src/lib/services/create-error-component.service.ts

@ -23,7 +23,7 @@ export class CreateErrorComponentService {
protected readonly rendererFactory = inject(RendererFactory2); protected readonly rendererFactory = inject(RendererFactory2);
protected readonly cfRes = inject(ComponentFactoryResolver); protected readonly cfRes = inject(ComponentFactoryResolver);
protected readonly routerEvents = inject(RouterEvents); protected readonly routerEvents = inject(RouterEvents);
protected readonly injector = inject(Injector); private readonly injector = inject(Injector);
protected readonly httpErrorConfig = inject(HTTP_ERROR_CONFIG); protected readonly httpErrorConfig = inject(HTTP_ERROR_CONFIG);
componentRef: ComponentRef<HttpErrorWrapperComponent> | null = null; componentRef: ComponentRef<HttpErrorWrapperComponent> | null = null;

1
nupkg/common.ps1

@ -97,6 +97,7 @@ $projects = (
"framework/src/Volo.Abp.AspNetCore.Authentication.JwtBearer", "framework/src/Volo.Abp.AspNetCore.Authentication.JwtBearer",
"framework/src/Volo.Abp.AspNetCore.Authentication.OAuth", "framework/src/Volo.Abp.AspNetCore.Authentication.OAuth",
"framework/src/Volo.Abp.AspNetCore.Authentication.OpenIdConnect", "framework/src/Volo.Abp.AspNetCore.Authentication.OpenIdConnect",
"framework/src/Volo.Abp.AspNetCore.Abstractions",
"framework/src/Volo.Abp.AspNetCore", "framework/src/Volo.Abp.AspNetCore",
"framework/src/Volo.Abp.AspNetCore.Mvc.Dapr", "framework/src/Volo.Abp.AspNetCore.Mvc.Dapr",
"framework/src/Volo.Abp.AspNetCore.Mvc.Dapr.EventBus", "framework/src/Volo.Abp.AspNetCore.Mvc.Dapr.EventBus",

54
templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/20240125061235_Initial.Designer.cs → templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/20240312033651_Initial.Designer.cs

@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore;
namespace MyCompanyName.MyProjectName.Blazor.Server.Migrations namespace MyCompanyName.MyProjectName.Blazor.Server.Migrations
{ {
[DbContext(typeof(MyProjectNameDbContext))] [DbContext(typeof(MyProjectNameDbContext))]
[Migration("20240125061235_Initial")] [Migration("20240312033651_Initial")]
partial class Initial partial class Initial
{ {
/// <inheritdoc /> /// <inheritdoc />
@ -647,6 +647,58 @@ namespace MyCompanyName.MyProjectName.Blazor.Server.Migrations
b.ToTable("AbpSecurityLogs", (string)null); b.ToTable("AbpSecurityLogs", (string)null);
}); });
modelBuilder.Entity("Volo.Abp.Identity.IdentitySession", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<string>("ClientId")
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.Property<string>("Device")
.IsRequired()
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.Property<string>("DeviceInfo")
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.Property<string>("IpAddresses")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<DateTime?>("LastAccessed")
.HasColumnType("datetime2");
b.Property<string>("SessionId")
.IsRequired()
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
b.Property<DateTime>("SignedIn")
.HasColumnType("datetime2");
b.Property<Guid?>("TenantId")
.HasColumnType("uniqueidentifier")
.HasColumnName("TenantId");
b.Property<Guid>("UserId")
.HasColumnType("uniqueidentifier");
b.HasKey("Id");
b.HasIndex("Device");
b.HasIndex("SessionId");
b.HasIndex("TenantId", "UserId");
b.ToTable("AbpSessions", (string)null);
});
modelBuilder.Entity("Volo.Abp.Identity.IdentityUser", b => modelBuilder.Entity("Volo.Abp.Identity.IdentityUser", b =>
{ {
b.Property<Guid>("Id") b.Property<Guid>("Id")

38
templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/20240125061235_Initial.cs → templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/20240312033651_Initial.cs

@ -255,6 +255,26 @@ namespace MyCompanyName.MyProjectName.Blazor.Server.Migrations
table.PrimaryKey("PK_AbpSecurityLogs", x => x.Id); table.PrimaryKey("PK_AbpSecurityLogs", x => x.Id);
}); });
migrationBuilder.CreateTable(
name: "AbpSessions",
columns: table => new
{
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
SessionId = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: false),
Device = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: false),
DeviceInfo = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: true),
TenantId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
UserId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
ClientId = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: true),
IpAddresses = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: true),
SignedIn = table.Column<DateTime>(type: "datetime2", nullable: false),
LastAccessed = table.Column<DateTime>(type: "datetime2", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_AbpSessions", x => x.Id);
});
migrationBuilder.CreateTable( migrationBuilder.CreateTable(
name: "AbpSettingDefinitions", name: "AbpSettingDefinitions",
columns: table => new columns: table => new
@ -896,6 +916,21 @@ namespace MyCompanyName.MyProjectName.Blazor.Server.Migrations
table: "AbpSecurityLogs", table: "AbpSecurityLogs",
columns: new[] { "TenantId", "UserId" }); columns: new[] { "TenantId", "UserId" });
migrationBuilder.CreateIndex(
name: "IX_AbpSessions_Device",
table: "AbpSessions",
column: "Device");
migrationBuilder.CreateIndex(
name: "IX_AbpSessions_SessionId",
table: "AbpSessions",
column: "SessionId");
migrationBuilder.CreateIndex(
name: "IX_AbpSessions_TenantId_UserId",
table: "AbpSessions",
columns: new[] { "TenantId", "UserId" });
migrationBuilder.CreateIndex( migrationBuilder.CreateIndex(
name: "IX_AbpSettingDefinitions_Name", name: "IX_AbpSettingDefinitions_Name",
table: "AbpSettingDefinitions", table: "AbpSettingDefinitions",
@ -1032,6 +1067,9 @@ namespace MyCompanyName.MyProjectName.Blazor.Server.Migrations
migrationBuilder.DropTable( migrationBuilder.DropTable(
name: "AbpSecurityLogs"); name: "AbpSecurityLogs");
migrationBuilder.DropTable(
name: "AbpSessions");
migrationBuilder.DropTable( migrationBuilder.DropTable(
name: "AbpSettingDefinitions"); name: "AbpSettingDefinitions");

52
templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/Migrations/MyProjectNameDbContextModelSnapshot.cs

@ -644,6 +644,58 @@ namespace MyCompanyName.MyProjectName.Blazor.Server.Migrations
b.ToTable("AbpSecurityLogs", (string)null); b.ToTable("AbpSecurityLogs", (string)null);
}); });
modelBuilder.Entity("Volo.Abp.Identity.IdentitySession", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<string>("ClientId")
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.Property<string>("Device")
.IsRequired()
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.Property<string>("DeviceInfo")
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.Property<string>("IpAddresses")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<DateTime?>("LastAccessed")
.HasColumnType("datetime2");
b.Property<string>("SessionId")
.IsRequired()
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
b.Property<DateTime>("SignedIn")
.HasColumnType("datetime2");
b.Property<Guid?>("TenantId")
.HasColumnType("uniqueidentifier")
.HasColumnName("TenantId");
b.Property<Guid>("UserId")
.HasColumnType("uniqueidentifier");
b.HasKey("Id");
b.HasIndex("Device");
b.HasIndex("SessionId");
b.HasIndex("TenantId", "UserId");
b.ToTable("AbpSessions", (string)null);
});
modelBuilder.Entity("Volo.Abp.Identity.IdentityUser", b => modelBuilder.Entity("Volo.Abp.Identity.IdentityUser", b =>
{ {
b.Property<Guid>("Id") b.Property<Guid>("Id")

54
templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20240125061501_Initial.Designer.cs → templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20240312033906_Initial.Designer.cs

@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore;
namespace MyCompanyName.MyProjectName.Migrations namespace MyCompanyName.MyProjectName.Migrations
{ {
[DbContext(typeof(MyProjectNameDbContext))] [DbContext(typeof(MyProjectNameDbContext))]
[Migration("20240125061501_Initial")] [Migration("20240312033906_Initial")]
partial class Initial partial class Initial
{ {
/// <inheritdoc /> /// <inheritdoc />
@ -647,6 +647,58 @@ namespace MyCompanyName.MyProjectName.Migrations
b.ToTable("AbpSecurityLogs", (string)null); b.ToTable("AbpSecurityLogs", (string)null);
}); });
modelBuilder.Entity("Volo.Abp.Identity.IdentitySession", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<string>("ClientId")
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.Property<string>("Device")
.IsRequired()
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.Property<string>("DeviceInfo")
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.Property<string>("IpAddresses")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<DateTime?>("LastAccessed")
.HasColumnType("datetime2");
b.Property<string>("SessionId")
.IsRequired()
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
b.Property<DateTime>("SignedIn")
.HasColumnType("datetime2");
b.Property<Guid?>("TenantId")
.HasColumnType("uniqueidentifier")
.HasColumnName("TenantId");
b.Property<Guid>("UserId")
.HasColumnType("uniqueidentifier");
b.HasKey("Id");
b.HasIndex("Device");
b.HasIndex("SessionId");
b.HasIndex("TenantId", "UserId");
b.ToTable("AbpSessions", (string)null);
});
modelBuilder.Entity("Volo.Abp.Identity.IdentityUser", b => modelBuilder.Entity("Volo.Abp.Identity.IdentityUser", b =>
{ {
b.Property<Guid>("Id") b.Property<Guid>("Id")

67
templates/app/aspnet-core/src/MyCompanyName.MyProjectName.EntityFrameworkCore/Migrations/20240125061248_Initial.cs → templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/20240312033906_Initial.cs

@ -45,27 +45,6 @@ namespace MyCompanyName.MyProjectName.Migrations
table.PrimaryKey("PK_AbpAuditLogs", x => x.Id); table.PrimaryKey("PK_AbpAuditLogs", x => x.Id);
}); });
migrationBuilder.CreateTable(
name: "AbpBackgroundJobs",
columns: table => new
{
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
JobName = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: false),
JobArgs = table.Column<string>(type: "nvarchar(max)", maxLength: 1048576, nullable: false),
TryCount = table.Column<short>(type: "smallint", nullable: false, defaultValue: (short)0),
CreationTime = table.Column<DateTime>(type: "datetime2", nullable: false),
NextTryTime = table.Column<DateTime>(type: "datetime2", nullable: false),
LastTryTime = table.Column<DateTime>(type: "datetime2", nullable: true),
IsAbandoned = table.Column<bool>(type: "bit", nullable: false, defaultValue: false),
Priority = table.Column<byte>(type: "tinyint", nullable: false, defaultValue: (byte)15),
ExtraProperties = table.Column<string>(type: "nvarchar(max)", nullable: false),
ConcurrencyStamp = table.Column<string>(type: "nvarchar(40)", maxLength: 40, nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_AbpBackgroundJobs", x => x.Id);
});
migrationBuilder.CreateTable( migrationBuilder.CreateTable(
name: "AbpClaimTypes", name: "AbpClaimTypes",
columns: table => new columns: table => new
@ -276,6 +255,26 @@ namespace MyCompanyName.MyProjectName.Migrations
table.PrimaryKey("PK_AbpSecurityLogs", x => x.Id); table.PrimaryKey("PK_AbpSecurityLogs", x => x.Id);
}); });
migrationBuilder.CreateTable(
name: "AbpSessions",
columns: table => new
{
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
SessionId = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: false),
Device = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: false),
DeviceInfo = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: true),
TenantId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
UserId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
ClientId = table.Column<string>(type: "nvarchar(64)", maxLength: 64, nullable: true),
IpAddresses = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: true),
SignedIn = table.Column<DateTime>(type: "datetime2", nullable: false),
LastAccessed = table.Column<DateTime>(type: "datetime2", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_AbpSessions", x => x.Id);
});
migrationBuilder.CreateTable( migrationBuilder.CreateTable(
name: "AbpSettingDefinitions", name: "AbpSettingDefinitions",
columns: table => new columns: table => new
@ -802,11 +801,6 @@ namespace MyCompanyName.MyProjectName.Migrations
table: "AbpAuditLogs", table: "AbpAuditLogs",
columns: new[] { "TenantId", "UserId", "ExecutionTime" }); columns: new[] { "TenantId", "UserId", "ExecutionTime" });
migrationBuilder.CreateIndex(
name: "IX_AbpBackgroundJobs_IsAbandoned_NextTryTime",
table: "AbpBackgroundJobs",
columns: new[] { "IsAbandoned", "NextTryTime" });
migrationBuilder.CreateIndex( migrationBuilder.CreateIndex(
name: "IX_AbpEntityChanges_AuditLogId", name: "IX_AbpEntityChanges_AuditLogId",
table: "AbpEntityChanges", table: "AbpEntityChanges",
@ -922,6 +916,21 @@ namespace MyCompanyName.MyProjectName.Migrations
table: "AbpSecurityLogs", table: "AbpSecurityLogs",
columns: new[] { "TenantId", "UserId" }); columns: new[] { "TenantId", "UserId" });
migrationBuilder.CreateIndex(
name: "IX_AbpSessions_Device",
table: "AbpSessions",
column: "Device");
migrationBuilder.CreateIndex(
name: "IX_AbpSessions_SessionId",
table: "AbpSessions",
column: "SessionId");
migrationBuilder.CreateIndex(
name: "IX_AbpSessions_TenantId_UserId",
table: "AbpSessions",
columns: new[] { "TenantId", "UserId" });
migrationBuilder.CreateIndex( migrationBuilder.CreateIndex(
name: "IX_AbpSettingDefinitions_Name", name: "IX_AbpSettingDefinitions_Name",
table: "AbpSettingDefinitions", table: "AbpSettingDefinitions",
@ -1022,9 +1031,6 @@ namespace MyCompanyName.MyProjectName.Migrations
migrationBuilder.DropTable( migrationBuilder.DropTable(
name: "AbpAuditLogActions"); name: "AbpAuditLogActions");
migrationBuilder.DropTable(
name: "AbpBackgroundJobs");
migrationBuilder.DropTable( migrationBuilder.DropTable(
name: "AbpClaimTypes"); name: "AbpClaimTypes");
@ -1061,6 +1067,9 @@ namespace MyCompanyName.MyProjectName.Migrations
migrationBuilder.DropTable( migrationBuilder.DropTable(
name: "AbpSecurityLogs"); name: "AbpSecurityLogs");
migrationBuilder.DropTable(
name: "AbpSessions");
migrationBuilder.DropTable( migrationBuilder.DropTable(
name: "AbpSettingDefinitions"); name: "AbpSettingDefinitions");

52
templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/Migrations/MyProjectNameDbContextModelSnapshot.cs

@ -644,6 +644,58 @@ namespace MyCompanyName.MyProjectName.Migrations
b.ToTable("AbpSecurityLogs", (string)null); b.ToTable("AbpSecurityLogs", (string)null);
}); });
modelBuilder.Entity("Volo.Abp.Identity.IdentitySession", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<string>("ClientId")
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.Property<string>("Device")
.IsRequired()
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.Property<string>("DeviceInfo")
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.Property<string>("IpAddresses")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<DateTime?>("LastAccessed")
.HasColumnType("datetime2");
b.Property<string>("SessionId")
.IsRequired()
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
b.Property<DateTime>("SignedIn")
.HasColumnType("datetime2");
b.Property<Guid?>("TenantId")
.HasColumnType("uniqueidentifier")
.HasColumnName("TenantId");
b.Property<Guid>("UserId")
.HasColumnType("uniqueidentifier");
b.HasKey("Id");
b.HasIndex("Device");
b.HasIndex("SessionId");
b.HasIndex("TenantId", "UserId");
b.ToTable("AbpSessions", (string)null);
});
modelBuilder.Entity("Volo.Abp.Identity.IdentityUser", b => modelBuilder.Entity("Volo.Abp.Identity.IdentityUser", b =>
{ {
b.Property<Guid>("Id") b.Property<Guid>("Id")

54
templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/20240125061101_Initial.Designer.cs → templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/Migrations/20240321011533_Initial.Designer.cs

@ -13,7 +13,7 @@ using Volo.Abp.EntityFrameworkCore;
namespace MyCompanyName.MyProjectName.Host.Migrations namespace MyCompanyName.MyProjectName.Host.Migrations
{ {
[DbContext(typeof(MyProjectNameDbContext))] [DbContext(typeof(MyProjectNameDbContext))]
[Migration("20240125061101_Initial")] [Migration("20240321011533_Initial")]
partial class Initial partial class Initial
{ {
/// <inheritdoc /> /// <inheritdoc />
@ -647,6 +647,58 @@ namespace MyCompanyName.MyProjectName.Host.Migrations
b.ToTable("AbpSecurityLogs", (string)null); b.ToTable("AbpSecurityLogs", (string)null);
}); });
modelBuilder.Entity("Volo.Abp.Identity.IdentitySession", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<string>("ClientId")
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.Property<string>("Device")
.IsRequired()
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.Property<string>("DeviceInfo")
.HasMaxLength(64)
.HasColumnType("nvarchar(64)");
b.Property<string>("IpAddresses")
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<DateTime?>("LastAccessed")
.HasColumnType("datetime2");
b.Property<string>("SessionId")
.IsRequired()
.HasMaxLength(128)
.HasColumnType("nvarchar(128)");
b.Property<DateTime>("SignedIn")
.HasColumnType("datetime2");
b.Property<Guid?>("TenantId")
.HasColumnType("uniqueidentifier")
.HasColumnName("TenantId");
b.Property<Guid>("UserId")
.HasColumnType("uniqueidentifier");
b.HasKey("Id");
b.HasIndex("Device");
b.HasIndex("SessionId");
b.HasIndex("TenantId", "UserId");
b.ToTable("AbpSessions", (string)null);
});
modelBuilder.Entity("Volo.Abp.Identity.IdentityUser", b => modelBuilder.Entity("Volo.Abp.Identity.IdentityUser", b =>
{ {
b.Property<Guid>("Id") b.Property<Guid>("Id")

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save