Browse Source

Merge branch 'dev' into json

pull/13357/head
maliming 4 years ago
parent
commit
4106efdd1e
  1. 5
      abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/ar.json
  2. 5
      abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/cs.json
  3. 10
      abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json
  4. 5
      abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/fi.json
  5. 5
      abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/fr.json
  6. 5
      abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/hi.json
  7. 12
      abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/hu.json
  8. 5
      abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/it.json
  9. 5
      abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/pt-BR.json
  10. 5
      abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/sk.json
  11. 12
      abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/zh-Hans.json
  12. 5
      abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/zh-Hant.json
  13. 18
      docs/en/UI/Angular/Account-Module.md
  14. 219
      docs/en/UI/Angular/Theme-Configurations.md
  15. 2
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ContentFormatters/RemoteStreamContentOutputFormatter.cs
  16. 10
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Uow/AbpUowActionFilter.cs
  17. 10
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Uow/AbpUowPageFilter.cs
  18. 31
      framework/src/Volo.Abp.BackgroundJobs.Abstractions/Volo/Abp/BackgroundJobs/BackgroundJobExecuter.cs
  19. 8
      framework/src/Volo.Abp.BlazoriseUI/Volo.Abp.BlazoriseUI.csproj
  20. 8
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Bundling/BundlingService.cs
  21. 1
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Licensing/DeveloperApiKeyResult.cs
  22. 8
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/DatabaseManagementSystemChangeStep.cs
  23. 2
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Files/FileEntryExtensions.cs
  24. 9
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/RemoveUnnecessaryPortsStep.cs
  25. 14
      framework/src/Volo.Abp.Core/Microsoft/Extensions/DependencyInjection/ServiceCollectionConfigurationExtensions.cs
  26. 34
      framework/src/Volo.Abp.Core/Volo/Abp/AbpApplicationBase.cs
  27. 3
      framework/src/Volo.Abp.Core/Volo/Abp/IApplicationNameAccessor.cs
  28. 2
      framework/src/Volo.Abp.EntityFrameworkCore.PostgreSql/Volo.Abp.EntityFrameworkCore.PostgreSql.csproj
  29. 21
      framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/ContentFormatters/RemoteStreamContentTestController.cs
  30. 21
      framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/ContentFormatters/RemoteStreamContentTestController_Tests.cs
  31. 32
      framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/ExceptionHandling/ExceptionHandingUnitOfWork.cs
  32. 10
      framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/ExceptionHandling/ExceptionTestController.cs
  33. 24
      framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/ExceptionHandling/ExceptionTestController_Tests.cs
  34. 5
      framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/ExceptionHandling/ExceptionTestPage.cshtml.cs
  35. 25
      framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/ExceptionHandling/ExceptionTestPage_Tests.cs
  36. 8
      framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Uow/UnitOfWorkMiddleware_Exception_Rollback_Tests.cs
  37. 8
      framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Uow/UnitOfWorkPageFilter_Exception_Rollback_Tests.cs
  38. 33
      framework/test/Volo.Abp.BackgroundJobs.Tests/Volo/Abp/BackgroundJobs/BackgroundJobExecuter_Tests.cs
  39. 12
      framework/test/Volo.Abp.BackgroundJobs.Tests/Volo/Abp/BackgroundJobs/MyAsyncJob.cs
  40. 12
      framework/test/Volo.Abp.BackgroundJobs.Tests/Volo/Abp/BackgroundJobs/MyAsyncJobArgs.cs
  41. 14
      framework/test/Volo.Abp.BackgroundJobs.Tests/Volo/Abp/BackgroundJobs/MyJob.cs
  42. 13
      framework/test/Volo.Abp.BackgroundJobs.Tests/Volo/Abp/BackgroundJobs/MyJobArgs.cs
  43. 51
      framework/test/Volo.Abp.Core.Tests/Volo/Abp/AbpApplication_Initialize_Tests.cs
  44. 2
      modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/en.json
  45. 2
      modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/tr.json
  46. 2
      modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp.HangFire/appsettings.json
  47. 2
      modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp/appsettings.json
  48. 19
      modules/basic-theme/src/Volo.Abp.AspNetCore.Components.Web.BasicTheme/Themes/Basic/RedirectToLogin.razor
  49. 13
      modules/basic-theme/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/LoginDisplay.razor.cs
  50. 17
      modules/basic-theme/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/WebAssemblyRedirectToLogin.razor
  51. 2
      modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Dockerfile
  52. 2
      modules/blob-storing-database/host/BlobStoring.Database.Host.ConsoleApp/src/BlobStoring.Database.Host.ConsoleApp.ConsoleApp/appsettings.json
  53. 2
      modules/blogging/app/Volo.BloggingTestApp/appsettings.json
  54. 2
      modules/cms-kit/database/Dockerfile
  55. 4
      modules/cms-kit/host/Volo.CmsKit.HttpApi.Host/Dockerfile
  56. 4
      modules/cms-kit/host/Volo.CmsKit.HttpApi.Host/appsettings.json
  57. 4
      modules/cms-kit/host/Volo.CmsKit.IdentityServer/Dockerfile
  58. 2
      modules/cms-kit/host/Volo.CmsKit.IdentityServer/appsettings.json
  59. 2
      modules/cms-kit/host/Volo.CmsKit.Web.Unified/appsettings.json
  60. 4
      modules/docs/app/VoloDocs.Migrator/Dockerfile
  61. 2
      modules/docs/app/VoloDocs.Migrator/appsettings.json
  62. 4
      modules/docs/app/VoloDocs.Web/Dockerfile
  63. 2
      modules/docs/app/VoloDocs.Web/appsettings.json
  64. 47
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AspNetIdentity/AbpUserClaimsFactory.cs
  65. 2
      modules/openiddict/app/OpenIddict.Demo.Server/appsettings.json
  66. 2
      modules/setting-management/app/Volo.Abp.SettingManagement.DemoApp/appsettings.json
  67. 5
      npm/ng-packs/packages/account/src/lib/account.module.ts
  68. 47
      npm/ng-packs/packages/account/src/lib/components/personal-settings/personal-settings.component.ts
  69. 1
      npm/ng-packs/packages/account/src/lib/models/config-options.ts
  70. 1
      npm/ng-packs/packages/account/src/lib/tokens/index.ts
  71. 5
      npm/ng-packs/packages/account/src/lib/tokens/re-login-confirmation.token.ts
  72. 1
      npm/ng-packs/packages/components/tree/src/lib/components/tree.component.html
  73. 19
      npm/ng-packs/packages/components/tree/src/lib/components/tree.component.ts
  74. 62
      templates/app-nolayers/angular/src/app/home/home.component.spec.ts
  75. 3
      templates/app-nolayers/angular/src/test.ts
  76. 8
      templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server.Mongo/MyCompanyName.MyProjectName.Blazor.Server.Mongo.csproj
  77. 8
      templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/MyCompanyName.MyProjectName.Blazor.Server.csproj
  78. 2
      templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/appsettings.json
  79. 4
      templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host.Mongo/MyCompanyName.MyProjectName.Host.Mongo.csproj
  80. 4
      templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/MyCompanyName.MyProjectName.Host.csproj
  81. 2
      templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/appsettings.json
  82. 4
      templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc.Mongo/MyCompanyName.MyProjectName.Mvc.Mongo.csproj
  83. 4
      templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/MyCompanyName.MyProjectName.Mvc.csproj
  84. 2
      templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/appsettings.json
  85. 100
      templates/app/angular/src/app/home/home.component.spec.ts
  86. 4
      templates/app/angular/src/test.ts
  87. 4
      templates/app/aspnet-core/common.props
  88. 2
      templates/app/aspnet-core/src/MyCompanyName.MyProjectName.AuthServer/MyCompanyName.MyProjectName.AuthServer.csproj
  89. 2
      templates/app/aspnet-core/src/MyCompanyName.MyProjectName.AuthServer/appsettings.json
  90. 6
      templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server.Tiered/MyCompanyName.MyProjectName.Blazor.Server.Tiered.csproj
  91. 4
      templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server/MyCompanyName.MyProjectName.Blazor.Server.csproj
  92. 2
      templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server/appsettings.json
  93. 4
      templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/MyCompanyName.MyProjectName.Blazor.csproj
  94. 139
      templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/wwwroot/global.css
  95. 4
      templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/wwwroot/global.js
  96. 4
      templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/wwwroot/index.html
  97. 2
      templates/app/aspnet-core/src/MyCompanyName.MyProjectName.DbMigrator/appsettings.json
  98. 2
      templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.Host/appsettings.json
  99. 2
      templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.HostWithIds/appsettings.json
  100. 2
      templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Web/appsettings.json

5
abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/ar.json

@ -190,7 +190,7 @@
"ChangingDevelopers": "هل يمكنني تغيير المطورين المسجلين لمنظمتي في المستقبل؟",
"ChangingDevelopersExplanation": "بالإضافة إلى إضافة مطورين جدد إلى الترخيص الخاص بك ، يمكنك أيضًا تغيير المطورين الحاليين (يمكنك إزالة مطور وإضافة مطور جديد إلى نفس المقعد) دون أي تكلفة إضافية.",
"WhenShouldIRenewMyLicense": "متى يجب أن أجدد رخصتي؟",
"WhenShouldIRenewMyLicenseExplanation": "إذا جددت ترخيصك في غضون <strong> شهر واحد </ strong> بعد انتهاء صلاحية الترخيص ، فسيتم تطبيق الخصومات التالية: ترخيص الفريق {0}٪ خصم ، ترخيص تجاري {1}٪ خصم ، ترخيص Enterprise {2}٪ خصم . إذا قمت بتجديد ترخيصك بعد <strong> شهر واحد </ strong> من تاريخ انتهاء صلاحية الترخيص ، فسيكون سعر التجديد هو نفسه سعر شراء الترخيص ولن يكون هناك خصم على التجديد.",
"WhenShouldIRenewMyLicenseExplanation": "إذا قمت بتجديد ترخيصك في غضون <strong> شهر واحد </ strong> بعد انتهاء صلاحية ترخيصك ، فسيتم تطبيق الخصومات التالية: ترخيص الفريق {0}؛ رخصة تجارية {1} ؛ ترخيص المؤسسة {2}. ومع ذلك ، إذا جددت ترخيصك بعد <strong> شهر واحد </ strong> من تاريخ انتهاء صلاحية الترخيص ، فسيكون سعر التجديد هو نفسه سعر شراء الترخيص ولن يكون هناك خصم على التجديد.",
"TrialPlan": "هل لديك خطة تجريبية؟",
"DoYouAcceptBankWireTransfer": "هل تقبل التحويل البنكي؟",
"DoYouAcceptBankWireTransferExplanation": "نعم ، نحن نقبل التحويل البنكي. <br /> بعد إرسال رسوم الترخيص عبر التحويل المصرفي ، أرسل لنا بريدًا إلكترونيًا على accounting@abp.io إيصالك ونوع الترخيص المطلوب. معلومات حسابنا المصرفي الدولي:",
@ -380,6 +380,7 @@
"TrialLicenseExpiredInfo": "انتهت فترة الترخيص التجريبي الخاص بك!",
"CommercialNewsletterConfirmationMessage": "أوافق على <a href=\"https://commercial.abp.io/TermsConditions\"> البنود والشروط </a> و <a href=\"https://commercial.abp.io/Privacy\"> سياسة الخصوصية </a>.",
"RenewLicenseEarly": "إذا قمت بتجديد رخصتي في وقت مبكر ، هل سأحصل على السنة كاملة؟",
"RenewLicenseEarylExplanation": "عند تجديد الترخيص الخاص بك قبل تاريخ انتهاء الترخيص الخاص بك ، ستتم إضافة سنة واحدة إلى تاريخ انتهاء الترخيص الخاص بك. على سبيل المثال ، إذا انتهت صلاحية ترخيصك في {0} -06-06 وقمت بتجديده في {0} -01-01 ، فسيكون تاريخ انتهاء صلاحية الترخيص الجديد {1} -06-06."
"RenewLicenseEarylExplanation": "عند تجديد الترخيص الخاص بك قبل تاريخ انتهاء الترخيص الخاص بك ، ستتم إضافة سنة واحدة إلى تاريخ انتهاء الترخيص الخاص بك. على سبيل المثال ، إذا انتهت صلاحية ترخيصك في {0} -06-06 وقمت بتجديده في {0} -01-01 ، فسيكون تاريخ انتهاء صلاحية الترخيص الجديد {1} -06-06.",
"discountForYears": "{0}٪ خصم لمدة {1} سنة (سنوات)"
}
}

5
abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/cs.json

@ -190,7 +190,7 @@
"ChangingDevelopers": "Mohu v budoucnu změnit registrované vývojáře své organizace?",
"ChangingDevelopersExplanation": "Kromě přidání nových vývojářů do vaší licence můžete také změnit stávající vývojáře (můžete odebrat vývojáře a přidat nového na stejné místo) bez jakýchkoli dalších nákladů.",
"WhenShouldIRenewMyLicense": "Kdy bych měl obnovit licenci?",
"WhenShouldIRenewMyLicenseExplanation": "Pokud si licenci obnovíte do <strong>1 měsíce</strong> po vypršení platnosti licence, budou uplatněny následující slevy: Týmová licence {0}% sleva, Obchodní licence {1}% sleva, Enterprise License {2}% sleva . Pokud si licenci obnovíte <strong>1 měsíc</strong> po datu vypršení platnosti vaší licence, cena za obnovení bude stejná jako cena nákupu licence a na obnovení nebude poskytnuta žádná sleva.",
"WhenShouldIRenewMyLicenseExplanation": "Pokud si licenci obnovíte do <strong>1 měsíce</strong> po vypršení platnosti licence, budou uplatněny následující slevy: Týmová licence {0}; Obchodní licence {1}; Enterprise Licence {2}. Pokud však licenci obnovíte po <strong>1 měsíci</strong> od data vypršení platnosti vaší licence, cena za obnovení bude stejná jako cena za zakoupení licence a na obnovení nebude poskytnuta žádná sleva.",
"TrialPlan": "Máte zkušební plán?",
"DoYouAcceptBankWireTransfer": "Přijímáte bankovní převod?",
"DoYouAcceptBankWireTransferExplanation": "Ano, přijímáme bankovní převod.<br />Po zaslání licenčního poplatku bankovním převodem nám zašlete e-mail na adresu accounting@abp.io potvrzení a požadovaný typ licence. Informace o našem mezinárodním bankovním účtu:",
@ -381,6 +381,7 @@
"CommercialNewsletterConfirmationMessage": "I agree to the <a href=\"https://commercial.abp.io/TermsConditions\">Terms & Conditions</a> and <a href=\"https://commercial.abp.io/Privacy\">Privacy Policy</a>.",
"ContinueWithNewOrganization": "Pokračujte s novou organizací",
"RenewLicenseEarly": "Pokud si předčasně obnovím licenci, dostanu celý rok?",
"RenewLicenseEarylExplanation": "Když obnovíte licenci před datem vypršení platnosti licence, bude k datu vypršení platnosti licence přidán 1 rok. Pokud například platnost vaší licence vyprší dne {0}-06-06 a obnovíte ji dne {0}-01-01, bude vaše nové datum vypršení platnosti licence {1}-06-06."
"RenewLicenseEarylExplanation": "Když obnovíte licenci před datem vypršení platnosti licence, bude k datu vypršení platnosti licence přidán 1 rok. Pokud například platnost vaší licence vyprší dne {0}-06-06 a obnovíte ji dne {0}-01-01, bude vaše nové datum vypršení platnosti licence {1}-06-06.",
"discountForYears": "{0}% sleva po dobu {1} let"
}
}

10
abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/en.json

@ -202,10 +202,11 @@
"WhatHappensWhenLicenseEndsExplanation4": "You can not install new modules and themes added to the ABP Commercial platform after your license ends.",
"WhatHappensWhenLicenseEndsExplanation5": "You can not use the ABP Suite.",
"WhatHappensWhenLicenseEndsExplanation6": "You can not get the <a href=\"{0}\">premium support</a> anymore.",
"WhatHappensWhenLicenseEndsExplanation7": "You can extend (renew) your license if you want to continue getting these benefits. If you extend your license within <strong>1 month</strong> after your license expires, the following discounts will be applied: Team License {0}% discount, Business License {1}% discount, Enterprise License {2}% discount.",
"WhatHappensWhenLicenseEndsExplanation7": "You can extend (renew) your license if you want to continue getting these benefits. If you extend your license within <strong>1 month</strong> after your license expires, the following discounts will be applied: Team License {0}; Business License {1}; Enterprise License {2}.",
"discountForYears": "{0}% discount for {1} year(s)",
"WhatHappensWhenLicenseEndsExplanation8": "The ABP projects you generated are not stored on our servers. Therefore, it is your responsibility to keep the source code you download. When your license expires, there's no way to get your generated ABP project source code.",
"WhenShouldIRenewMyLicense": "When should I renew my license?",
"WhenShouldIRenewMyLicenseExplanation": "If you renew your license within <strong>1 month</strong> after your license expires, the following discounts will be applied: Team License {0}% discount, Business License {1}% discount, Enterprise License {2}% discount. However, if you renew your license after <strong>1 month</strong> since the expiry date of your license, the renewal price will be the same as the license purchase price and there will be no discount on your renewal.",
"WhenShouldIRenewMyLicenseExplanation": "If you renew your license within <strong>1 month</strong> after your license expires, the following discounts will be applied: Team License {0}; Business License {1}; Enterprise License {2}. However, if you renew your license after <strong>1 month</strong> since the expiry date of your license, the renewal price will be the same as the license purchase price and there will be no discount on your renewal.",
"TrialPlan": "Do you have a trial plan?",
"TrialPlanExplanation": "It has a 14 days trial period for the ABP Commercial team license. For more information visit <a href={0} target='_blank'>here</a>. Furthermore, for the Team licenses we provide a 30 days money-back guarantee. You can just request a refund in the first 30 days. For the Business and Enterprise licenses, we provide 60% refund in 30 days. This is because Business and Enterprise licenses include the full source code of all the modules and the themes.",
"DoYouAcceptBankWireTransfer": "Do you accept bank wire transfers?",
@ -564,7 +565,7 @@
"MyOrganizations_Detail_PaymentProviderInfo": "If you have purchased your license through <i>{0}</i> gateway, it sends the PDF invoice to your email address, see <a href=\"{1}\" target=\"_blank\">{0} invoicing.</a>",
"MyOrganizations_Detail_PayUInfo": "If you have purchased through the <i>PayU</i> gateway, click the \"Request Invoice\" button and fill in the billing information.",
"MyOrganizations_Detail_ConclusionInfo": "Your invoice request will be concluded within {0} business days.",
"ExtendYourLicense": "Extend your {0} license",
"ExtendYourLicense": "Extend your <span class=\"text-primary\">{0}</span> license",
"Continue": "Continue",
"PurchaseLicense": "Purchase {0} license",
"DownloadInvoiceModal_DownloadInvoice": "Download Invoice",
@ -746,6 +747,9 @@
"SeeWhatToldAboutAbpCommercial": "See what has been told about ABP Commercial and write your thoughts if you want.",
"BlazoriseLicense": "Do we need to buy Blazorise license?",
"BlazoriseLicenseExplanation": "We have an agreement between Volosoft and Megabit, with this agreement Blazorise license is bundled with ABP Commercial products therefore our customers do not need to purchase an extra Blazorise license.",
"ExtendPaymentInfoSection_DeveloperPrice": "{0} x Developer(s) Price",
"ExtendPaymentInfoSection_DiscountRate": "Discount {0}%",
"TotalNetPrice": "Total Net Price",
"EFCore": "Entity Framework Core",
"All": "All",
"Mvc": "MVC",

5
abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/fi.json

@ -190,7 +190,7 @@
"ChangingDevelopers": "Voinko muuttaa organisaationi rekisteröityneitä kehittäjiä tulevaisuudessa?",
"ChangingDevelopersExplanation": "Uusien kehittäjien lisäämisen lisenssiin lisäksi voit myös muuttaa olemassa olevia kehittäjiä (voit poistaa kehittäjän ja lisätä uuden samalle paikalle) ilman lisäkustannuksia.",
"WhenShouldIRenewMyLicense": "Milloin minun pitäisi uusia lisenssini?",
"WhenShouldIRenewMyLicenseExplanation": "Jos uusit lisenssisi <strong>1 kuukauden</strong> kuluessa lisenssin vanhenemisesta, seuraavat alennukset sovelletaan: Team License {0} % alennus, Business License {1} % alennus, Enterprise License {2} % alennus . Jos uusit lisenssisi <strong>1 kuukauden</strong> lisenssin päättymispäivän jälkeen, uusimishinta on sama kuin lisenssin ostohinta, eikä uusimisesta saa alennusta.",
"WhenShouldIRenewMyLicenseExplanation": "Jos uusit lisenssisi <strong>1 kuukauden</strong> kuluessa lisenssin vanhenemisesta, seuraavat alennukset sovelletaan: Team License {0} ; Business License {1} ; Enterprise License {2} ; . Jos uusit lisenssisi <strong>1 kuukauden</strong> lisenssin päättymispäivän jälkeen, uusimishinta on sama kuin lisenssin ostohinta, eikä uusimisesta saa alennusta.",
"TrialPlan": "Onko sinulla kokeilusuunnitelma?",
"DoYouAcceptBankWireTransfer": "Hyväksytkö pankkisiirron?",
"DoYouAcceptBankWireTransferExplanation": "Kyllä, hyväksymme pankkisiirron.<br />Kun olet lähettänyt lisenssimaksun pankkisiirrolla, lähetä meille sähköposti osoitteeseen accounting@abp.io kuittisi ja pyydetty lisenssityyppi. Kansainväliset pankkitilitietomme:",
@ -381,6 +381,7 @@
"CommercialNewsletterConfirmationMessage": "Hyväksyn <a href=\"https://commercial.abp.io/TermsConditions\">käyttöehdot</a> ja <a href=\"https://commercial.abp.io/Privacy\">tietosuojakäytännön </a>.",
"ContinueWithNewOrganization": "Jatka uudessa organisaatiossa",
"RenewLicenseEarly": "Jos uusin ajokorttini etuajassa, saanko koko vuoden?",
"RenewLicenseEarylExplanation": "Kun uusit lisenssisi ennen lisenssin vanhenemispäivää, lisenssin voimassaolopäivään lisätään 1 vuosi. Jos lisenssisi vanhenee esimerkiksi {0}-06-06 ja uusit sen {0}-01-01, uusi lisenssisi päättymispäivä on {1}-06-06."
"RenewLicenseEarylExplanation": "Kun uusit lisenssisi ennen lisenssin vanhenemispäivää, lisenssin voimassaolopäivään lisätään 1 vuosi. Jos lisenssisi vanhenee esimerkiksi {0}-06-06 ja uusit sen {0}-01-01, uusi lisenssisi päättymispäivä on {1}-06-06.",
"discountForYears": "{0}% de remise pendant {1} an(s)"
}
}

5
abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/fr.json

@ -190,7 +190,7 @@
"ChangingDevelopers": "Puis-je changer les développeurs enregistrés de mon organisation à l'avenir?",
"ChangingDevelopersExplanation": "En plus d'ajouter de nouveaux développeurs à votre licence, vous pouvez également modifier les développeurs existants (vous pouvez supprimer un développeur et en ajouter un nouveau sur le même siège) sans aucun coût supplémentaire.",
"WhenShouldIRenewMyLicense": "Quand dois-je renouveler ma licence?",
"WhenShouldIRenewMyLicenseExplanation": "Si vous renouvelez votre licence dans un délai de <strong>1 mois</strong> après l'expiration de votre licence, les remises suivantes seront appliquées : licence d'équipe {0} % de remise, licence d'entreprise {1} % de remise, licence d'entreprise {2} % de remise . Si vous renouvelez votre licence <strong>1 mois</strong> après la date d'expiration de votre licence, le prix de renouvellement sera le même que le prix d'achat de la licence et il n'y aura aucune remise sur votre renouvellement.",
"WhenShouldIRenewMyLicenseExplanation": "Si vous renouvelez votre licence dans <strong>1 mois</strong> après l'expiration de votre licence, les remises suivantes seront appliquées : licence d'équipe {0} ; licence commerciale {1} ; licence d'entreprise {2}. Toutefois, si vous renouveler votre licence après <strong>1 mois</strong> depuis la date d'expiration de votre licence, le prix de renouvellement sera le même que le prix d'achat de la licence et il n'y aura pas de remise sur votre renouvellement.",
"TrialPlan": "Avez-vous un plan d'essai?",
"DoYouAcceptBankWireTransfer": "Acceptez-vous les virements bancaires?",
"DoYouAcceptBankWireTransferExplanation": "Oui, nous acceptons les virements bancaires.<br />Après avoir envoyé les frais de licence par virement bancaire, envoyez-nous par e-mail à accounting@abp.io votre reçu et le type de licence demandé. Nos coordonnées bancaires internationales :",
@ -381,6 +381,7 @@
"CommercialNewsletterConfirmationMessage": "J'accepte les <a href=\"https://commercial.abp.io/TermsConditions\">Conditions générales</a> et la <a href=\"https://commercial.abp.io/Privacy\">Politique de confidentialité </a>.",
"ContinueWithNewOrganization": "Continuer avec une nouvelle organisation",
"RenewLicenseEarly": "Si je renouvelle ma licence plus tôt, obtiendrai-je l'année complète ?",
"RenewLicenseEarylExplanation": "Lorsque vous renouvelez votre licence avant la date d'expiration de votre licence, 1 an sera ajouté à la date d'expiration de votre licence. Par exemple, si votre licence expire le {0}-06-06 et que vous la renouvelez le {0}-01-01, la nouvelle date d'expiration de votre licence sera le {1}-06-06."
"RenewLicenseEarylExplanation": "Lorsque vous renouvelez votre licence avant la date d'expiration de votre licence, 1 an sera ajouté à la date d'expiration de votre licence. Par exemple, si votre licence expire le {0}-06-06 et que vous la renouvelez le {0}-01-01, la nouvelle date d'expiration de votre licence sera le {1}-06-06.",
"discountForYears": "{0} % de remise pendentif {1} an(s)"
}
}

5
abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/hi.json

@ -190,7 +190,7 @@
"ChangingDevelopers": "क्या मैं भविष्य में अपने संगठन के पंजीकृत डेवलपर्स को बदल सकता हूं?",
"ChangingDevelopersExplanation": "अपने लाइसेंस में नए डेवलपर्स को जोड़ने के अलावा, आप मौजूदा डेवलपर्स को भी बदल सकते हैं (आप एक डेवलपर को हटा सकते हैं और एक ही सीट पर एक नया जोड़ सकते हैं) बिना किसी अतिरिक्त लागत के।",
"WhenShouldIRenewMyLicense": "मुझे अपना लाइसेंस कब नवीनीकृत करना चाहिए?",
"WhenShouldIRenewMyLicenseExplanation": "यदि आप अपने लाइसेंस की समय सीमा समाप्त होने के बाद <strong>1 महीने</strong> के भीतर अपना लाइसेंस नवीनीकृत करते हैं, तो निम्नलिखित छूटें लागू होंगी: टीम लाइसेंस {0}% छूट, व्यवसाय लाइसेंस {1}% छूट, एंटरप्राइज़ लाइसेंस {2}% छूट . यदि आप अपने लाइसेंस की समाप्ति तिथि के बाद <strong>1 महीने</strong> अपने लाइसेंस का नवीनीकरण करते हैं, तो नवीनीकरण मूल्य लाइसेंस खरीद मूल्य के समान होगा और आपके नवीनीकरण पर कोई छूट नहीं होगी।",
"WhenShouldIRenewMyLicenseExplanation": "यदि आप अपने लाइसेंस की समय सीमा समाप्त होने के बाद <strong>1 महीने</strong> के भीतर अपना लाइसेंस नवीनीकृत करते हैं, तो निम्नलिखित छूटें लागू होंगी: टीम लाइसेंस {0} ; व्यवसाय लाइसेंस {1} ; एंटरप्राइज़ लाइसेंस {2} . यदि आप अपने लाइसेंस की समाप्ति तिथि के बाद <strong>1 महीने</strong> अपने लाइसेंस का नवीनीकरण करते हैं, तो नवीनीकरण मूल्य लाइसेंस खरीद मूल्य के समान होगा और आपके नवीनीकरण पर कोई छूट नहीं होगी।",
"TrialPlan": "क्या आपके पास एक परीक्षण योजना है?",
"DoYouAcceptBankWireTransfer": "क्या आप बैंक वायर ट्रांसफर स्वीकार करते हैं?",
"DoYouAcceptBankWireTransferExplanation": "हां, हम बैंक वायर ट्रांसफर स्वीकार करते हैं।<br />बैंक हस्तांतरण के माध्यम से लाइसेंस शुल्क भेजने के बाद, हमें अपनी रसीद और अनुरोधित लाइसेंस के प्रकार accounting@abp.io पर ईमेल करें। हमारे अंतरराष्ट्रीय बैंक खाते की जानकारी:",
@ -378,6 +378,7 @@
"TrialLicenseExpireMessage": "आप परीक्षण लाइसेंस का उपयोग कर रहे हैं और आपका परीक्षण लाइसेंस {0} को समाप्त हो जाएगा।",
"TryForFree": "मुफ्त में आजमाइये",
"TrialLicenseExpiredInfo": "आपके परीक्षण लाइसेंस की अवधि समाप्त हो गई है!",
"CommercialNewsletterConfirmationMessage": "मैं <a href=\"https://commercial.abp.io/TermsConditions\">नियम और शर्तों</a> और <a href=\"https://commercial.abp.io/Privacy\">गोपनीयता नीति से सहमत हूं </a>."
"CommercialNewsletterConfirmationMessage": "मैं <a href=\"https://commercial.abp.io/TermsConditions\">नियम और शर्तों</a> और <a href=\"https://commercial.abp.io/Privacy\">गोपनीयता नीति से सहमत हूं </a>.",
"discountForYears": "{1}वर्ष(वर्षों) के लिए {0}% छूट"
}
}

12
abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/hu.json

@ -202,10 +202,11 @@
"WhatHappensWhenLicenseEndsExplanation4": "A licensz lejárta után nem telepíthet új modulokat és témákat az ABP Commercial platformhoz.",
"WhatHappensWhenLicenseEndsExplanation5": "Az ABP Suite nem használható.",
"WhatHappensWhenLicenseEndsExplanation6": "A <a href=\"{0}\">prémium támogatást</a> már nem kaphatja meg.",
"WhatHappensWhenLicenseEndsExplanation7": "Meghosszabbíthatja (megújíthatja) az engedélyét, ha továbbra is igénybe kívánja venni ezeket az előnyöket. Ha a licensz lejártát követő <strong>1 hónapon</strong> belül meghosszabbítja a licenszet, a következő kedvezmények érvényesek: Team License {0}% kedvezmény, Business License {1}% kedvezmény, Enterprise License {2}% kedvezmény.",
"WhatHappensWhenLicenseEndsExplanation7": "Meghosszabbíthatja (megújíthatja) a licencét, ha továbbra is szeretné igénybe venni ezeket az előnyöket. Ha a licenc lejártát követő <strong>1 hónapon belül</strong> meghosszabbítja licencét, a következő kedvezmények érvényesek: Csapat Licenc {0}; Üzleti licenc {1}; Vállalati licenc {2}.",
"discountForYears": "{0}% kedvezmény {1} évre",
"WhatHappensWhenLicenseEndsExplanation8": "Az Ön által generált ABP projekteket nem tároljuk a szervereinken. Ezért az Ön felelőssége a letöltött forráskód megőrzése. Amikor a licensze lejár, nincs mód a generált ABP projekt forráskódjának lekérésére.",
"WhenShouldIRenewMyLicense": "Mikor kell megújítanom a jogosítványomat?",
"WhenShouldIRenewMyLicenseExplanation": "Ha a licenc lejártát követő <strong>1 hónapon belül</strong> megújítja a licencet, a következő kedvezmények érvényesek: Csapatlicenc {0}% kedvezmény, Üzleti licenc {1}% kedvezmény, Vállalati licenc {2}% kedvezmény . Ha megújítja a licencet <strong>1 hónappal</strong> a licenc lejárati dátuma után, a megújítási ár megegyezik a licenc vásárlási árával, és nem jár kedvezmény a megújításra.",
"WhenShouldIRenewMyLicenseExplanation": "Ha a licenc lejártát követő <strong>1 hónapon belül</strong> megújítja a licencet, a következő kedvezmények érvényesek: Csapatlicenc {0}; Üzleti engedély {1}; Vállalati licenc {2}. Ha azonban a licenc lejárati dátuma óta <strong>1 hónap</strong> után megújítja a licencet, a megújítási ár megegyezik a licenc vásárlási árával, és nem jár kedvezmény a megújításra.",
"TrialPlan": "Van próbaterv?",
"TrialPlanExplanation": "14 napos próbaidővel rendelkezik az ABP Commercial csapat licenszéhez. További információért látogasson el <a href={0} target='_blank'>ide</a> . Továbbá a Team licenszekre 30 napos pénz-visszafizetési garanciát biztosítunk. Az első 30 napban csak visszatérítést kérhet. A Business és Enterprise licenszek esetén 30 napon belül 60%-os visszatérítést biztosítunk. Ennek az az oka, hogy a Business és Enterprise licenszek tartalmazzák az összes modul és téma teljes forráskódját.",
"DoYouAcceptBankWireTransfer": "Elfogadja a banki átutalást?",
@ -564,7 +565,7 @@
"MyOrganizations_Detail_PaymentProviderInfo": "Ha licenszét a <i>(z) {0}</i> átjárón keresztül vásárolta, az elküldi a PDF számlát az Ön e-mail címére, lásd: <a href=\"{1}\" target=\"_blank\">{0} számlázás.</a>",
"MyOrganizations_Detail_PayUInfo": "Ha a <i>PayU</i> átjárón keresztül vásárolt, kattintson a \"Számla kérése\" gombra, és töltse ki a számlázási adatokat.",
"MyOrganizations_Detail_ConclusionInfo": "Számlakérését {0} munkanapon belül lezárjuk.",
"ExtendYourLicense": "Hosszabbítsa meg {0} licenszét",
"ExtendYourLicense": "Hosszabbítsa meg <span class=\"text-primary\">{0}</span> licenszét",
"Continue": "Folytatni",
"PurchaseLicense": "Vásároljon {0} licencet",
"DownloadInvoiceModal_DownloadInvoice": "Számla letöltése",
@ -743,6 +744,9 @@
"Testimonial_ShortDescription_3": "A beépített funkciókból indulunk ki, és csak arra koncentrálunk, amit valóban meg kell írnunk.",
"Testimonial_ShortDescription_4": "Az ABP Commercial volt a legjobban megfelelő az igényeinknek.",
"OnlineReviewersOnAbpCommercial": "Online vélemények az ABP Commercial-ról",
"SeeWhatToldAboutAbpCommercial": "Tekintse meg, mit mondtak az ABP Commercialról, és írja le gondolatait, ha akarja."
"SeeWhatToldAboutAbpCommercial": "Tekintse meg, mit mondtak az ABP Commercialról, és írja le gondolatait, ha akarja.",
"ExtendPaymentInfoSection_DeveloperPrice": "{0} x Developer(s) Price",
"ExtendPaymentInfoSection_DiscountRate": "Kedvezmény: {0}%",
"TotalNetPrice": "Total Net Price"
}
}

5
abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/it.json

@ -190,7 +190,7 @@
"ChangingDevelopers": "Posso cambiare gli sviluppatori registrati della mia organizzazione in futuro?",
"ChangingDevelopersExplanation": "Oltre ad aggiungere nuovi sviluppatori alla tua licenza, puoi anche Modifica gli sviluppatori esistenti (puoi rimuovere uno sviluppatore e aggiungerne uno nuovo alla stessa postazione) senza alcun costo aggiuntivo.",
"WhenShouldIRenewMyLicense": "Quando devo rinnovare la mia licenza?",
"WhenShouldIRenewMyLicenseExplanation": "Se rinnovi la licenza entro <strong>1 mese</strong> dopo la scadenza della licenza, verranno applicati i seguenti sconti: Licenza Team {0}% di sconto, Licenza Business {1}% di sconto, Licenza Enterprise {2}% di sconto . Se rinnovi la licenza <strong>1 mese</strong> dopo la data di scadenza della licenza, il prezzo di rinnovo sarà lo stesso del prezzo di acquisto della licenza e non ci saranno sconti sul rinnovo.",
"WhenShouldIRenewMyLicenseExplanation": "Se rinnovi la licenza entro <strong>1 mese</strong> dopo la scadenza della licenza, verranno applicati i seguenti sconti: Licenza Team {0} ; Licenza Business {1} ; Licenza Enterprise {2} . Se rinnovi la licenza <strong>1 mese</strong> dopo la data di scadenza della licenza, il prezzo di rinnovo sarà lo stesso del prezzo di acquisto della licenza e non ci saranno sconti sul rinnovo.",
"TrialPlan": "Hai un piano di prova?",
"DoYouAcceptBankWireTransfer": "Accettate bonifici bancari?",
"DoYouAcceptBankWireTransferExplanation": "Sì, accettiamo bonifico bancario.<br />Dopo aver inviato il canone tramite bonifico bancario, inviaci un'e-mail a accounting@abp.io con la ricevuta e il tipo di licenza richiesta. Le nostre informazioni sul conto bancario internazionale:",
@ -378,6 +378,7 @@
"TrialLicenseExpireMessage": "Stai utilizzando la licenza di prova e la tua licenza di prova scadrà il {0}.",
"TryForFree": "Prova gratis",
"TrialLicenseExpiredInfo": "Il periodo della tua licenza di prova è scaduto!",
"CommercialNewsletterConfirmationMessage": "Accetto i <a href=\"https://commercial.abp.io/TermsConditions\">Termini e condizioni</a> e la <a href=\"https://commercial.abp.io/Privacy\">Informativa sulla privacy </a>."
"CommercialNewsletterConfirmationMessage": "Accetto i <a href=\"https://commercial.abp.io/TermsConditions\">Termini e condizioni</a> e la <a href=\"https://commercial.abp.io/Privacy\">Informativa sulla privacy </a>.",
"discountForYears": "{0}% di sconto per {1} anno/i"
}
}

5
abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/pt-BR.json

@ -190,7 +190,7 @@
"ChangingDevelopers": "Posso mudar os desenvolvedores registrados da minha organização no futuro?",
"ChangingDevelopersExplanation": "Além de adicionar novos desenvolvedores à sua licença, você também pode alterar os desenvolvedores existentes (você pode remover um desenvolvedor e adicionar um novo ao mesmo assento) sem nenhum custo adicional.",
"WhenShouldIRenewMyLicense": "Quando devo renovar minha licença?",
"WhenShouldIRenewMyLicenseExplanation": "Se você renovar sua licença em <strong> 1 mês </strong> após a expiração da licença, os seguintes descontos serão aplicados: Licença de equipe {0}% de desconto, Licença de negócios {1}% de desconto, Licença empresarial {2}% de desconto . Se você renovar sua licença <strong> 1 mês </strong> após a data de expiração de sua licença, o preço de renovação será o mesmo que o preço de compra da licença e não haverá desconto em sua renovação.",
"WhenShouldIRenewMyLicenseExplanation": "Se você renovar sua licença em <strong> 1 mês </strong> após a expiração da licença, os seguintes descontos serão aplicados: Licença de equipe {0} ; Licença de negócios {1} ; Licença empresarial {2} . Se você renovar sua licença <strong> 1 mês </strong> após a data de expiração de sua licença, o preço de renovação será o mesmo que o preço de compra da licença e não haverá desconto em sua renovação.",
"TrialPlan": "Você tem um plano experimental?",
"DoYouAcceptBankWireTransfer": "Você aceita transferência bancária?",
"DoYouAcceptBankWireTransferExplanation": "Sim, aceitamos transferência bancária. <br /> Após enviar a taxa de licença por transferência bancária, envie-nos um e-mail para accounting@abp.io com seu recibo e o tipo de licença solicitada. Nossas informações de conta bancária internacional:",
@ -378,6 +378,7 @@
"TrialLicenseExpireMessage": "Você está usando a licença de teste e sua licença de teste irá expirar em {0}.",
"TryForFree": "Experimentar gratuitamente",
"TrialLicenseExpiredInfo": "Seu período de licença de teste expirou!",
"CommercialNewsletterConfirmationMessage": "Eu concordo com os <a href=\"https://commercial.abp.io/TermsConditions\"> Termos e Condições </a> e a <a href=\"https://commercial.abp.io/Privacy\"> Política de Privacidade </a>"
"CommercialNewsletterConfirmationMessage": "Eu concordo com os <a href=\"https://commercial.abp.io/TermsConditions\"> Termos e Condições </a> e a <a href=\"https://commercial.abp.io/Privacy\"> Política de Privacidade </a>",
"discountForYears": "{0}% de desconto por {1} ano(s)"
}
}

5
abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/sk.json

@ -190,7 +190,7 @@
"ChangingDevelopers": "Môžem v budúcnosti zmeniť registrovaných vývojárov svojej organizácie?",
"ChangingDevelopersExplanation": "Okrem pridávania nových vývojárov do licencie môžete tiež meniť existujúcich vývojárov (môžete odstrániť vývojára a pridať nového na to isté miesto) bez akýchkoľvek ďalších nákladov.",
"WhenShouldIRenewMyLicense": "Kedy si mám obnoviť licenciu?",
"WhenShouldIRenewMyLicenseExplanation": "Ak si licenciu obnovíte do <strong>1 mesiaca</strong> po vypršaní platnosti licencie, budú sa uplatňovať tieto zľavy: Tímová licencia {0}% zľava, Obchodná licencia {1}% zľava, Enterprise licencia {2}% zľava . Ak si licenciu obnovíte <strong>1 mesiac</strong> po dátume skončenia platnosti licencie, cena za obnovenie bude rovnaká ako cena za nákup licencie a na obnovenie nebude poskytnutá žiadna zľava.",
"WhenShouldIRenewMyLicenseExplanation": "Ak si licenciu obnovíte do <strong>1 mesiaca</strong> po vypršaní platnosti licencie, budú sa uplatňovať tieto zľavy: Tímová licencia {0} ; Obchodná licencia {1} ; Enterprise licencia {2} . Ak si licenciu obnovíte <strong>1 mesiac</strong> po dátume skončenia platnosti licencie, cena za obnovenie bude rovnaká ako cena za nákup licencie a na obnovenie nebude poskytnutá žiadna zľava.",
"TrialPlan": "Máte skúšobný plán?",
"DoYouAcceptBankWireTransfer": "Prijímate bankový prevod?",
"DoYouAcceptBankWireTransferExplanation": "Áno, akceptujeme bankový prevod.<br />Po odoslaní licenčného poplatku bankovým prevodom nám pošlite e-mail na adresu accounting@abp.io svoje potvrdenie a požadovaný typ licencie. Informácie o našom medzinárodnom bankovom účte:",
@ -378,6 +378,7 @@
"TrialLicenseExpireMessage": "Používate skúšobnú licenciu a platnosť vašej skúšobnej licencie vyprší {0}.",
"TryForFree": "Skúste zadarmo",
"TrialLicenseExpiredInfo": "Vaše skúšobné licenčné obdobie vypršalo!",
"CommercialNewsletterConfirmationMessage": "I agree to the <a href=\"https://commercial.abp.io/TermsConditions\">Terms & Conditions</a> and <a href=\"https://commercial.abp.io/Privacy\">Privacy Policy</a>."
"CommercialNewsletterConfirmationMessage": "I agree to the <a href=\"https://commercial.abp.io/TermsConditions\">Terms & Conditions</a> and <a href=\"https://commercial.abp.io/Privacy\">Privacy Policy</a>.",
"discountForYears": "{0} % odpusteného prívesku {1} an(ov)"
}
}

12
abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/zh-Hans.json

@ -202,10 +202,11 @@
"WhatHappensWhenLicenseEndsExplanation4": "你不能在你的许可证到期后安装ABP商业平台上添加的新模块和主题。",
"WhatHappensWhenLicenseEndsExplanation5": "你不能使用ABP Suite。",
"WhatHappensWhenLicenseEndsExplanation6": "你不能再获得<a href=\"{0}\">高级支持</a>。",
"WhatHappensWhenLicenseEndsExplanation7": "如果你想继续获得这些奖励,你可以继续续费你的许可证。如果你在许可证到期后<strong>1个月</strong>内续费,将会应用以下折扣:团队许可证{0}%折扣,商业许可证{1}%折扣,企业许可证{2}%折扣。",
"WhatHappensWhenLicenseEndsExplanation7": "如果您想继续获得这些好处,您可以延长(续订)您的许可证。 如果您在许可证到期后 <strong>1 个月</strong>内延长许可证,将应用以下折扣:团队许可证 {0}; 营业执照{1}; 企业许可证 {2}。",
"discountForYears": "{0}% 折扣 {1} 年",
"WhatHappensWhenLicenseEndsExplanation8": "您生成的 ABP 项目未存储在我们的服务器上。 因此,您有责任保留下载的源代码。 当您的许可证到期时,将无法获取您生成的 ABP 项目源代码。",
"WhenShouldIRenewMyLicense": "我什么时候应该续订我的许可?",
"WhenShouldIRenewMyLicenseExplanation": "如果您在许可证到期后 <strong>1 个月</strong>内续订许可证,将享受以下折扣:团队许可证 {0}% 折扣、商业许可证 {1}% 折扣、企业许可证 {2}% 折扣 . 如果您在许可证到期后 <strong>1 个月</strong>续订许可证,续订价格将与许可证购买价格相同,并且续订不会有折扣。",
"WhenShouldIRenewMyLicenseExplanation": "如果您在许可证到期后 <strong>1 个月</strong> 内续订许可证,将适用以下折扣:团队许可证 {0}; 营业执照{1}; 企业许可证 {2}。 但是,如果您在许可证到期后 <strong>1 个月</strong>续订许可证,续订价格将与许可证购买价格相同,并且您的续订不会有任何折扣。",
"TrialPlan": "你们有试用计划吗?",
"TrialPlanExplanation": "ABP商业团队许可证有14天的试用期。若要了解更多信息,请访问<a href={0} target='_blank'>这里</a>。此外,我们为团队许可证提供30天的金额返还保证。你只需要在30天内请求退款。商业和企业许可证将提供60%的金额返还保证。这是因为商业和企业许可证包含了所有模块和主题的全部源代码。",
"DoYouAcceptBankWireTransfer": "你们接受银行电汇吗?",
@ -564,7 +565,7 @@
"MyOrganizations_Detail_PaymentProviderInfo": "如果您通过 <i>{0}</i> 网关购买了许可证,它会将 PDF 发票发送到您的电子邮件地址,请参阅 <a href=\"{1}\" target=\"_blank\"> {0} 发票。</a>",
"MyOrganizations_Detail_PayUInfo": "如果您是通过<i>PayU</i>网关购买的,请点击\"索取发票\"按钮并填写账单信息。",
"MyOrganizations_Detail_ConclusionInfo": "您的发票申请将在 {0} 个工作日内完成。",
"ExtendYourLicense": "延长您的 {0} 许可",
"ExtendYourLicense": "延长您的 <span class=\"text-primary\">{0}</span> 许可",
"Continue": "继续",
"PurchaseLicense": "购买 {0} 许可证",
"DownloadInvoiceModal_DownloadInvoice": "下载发票",
@ -737,6 +738,9 @@
"GetConfirmationEmail": "<a href=\"javascript:void(0);\" id=\"{0}\">点击这里获取确认邮件</a> 如果你还没有收到。",
"WhichLicenseTypeYouAreInterestedIn": "你感兴趣的许可证类型是什么?",
"BlazoriseLicense": "我们是否需要购买Blazorise许可证?",
"BlazoriseLicenseExplanation": "我公司Volosoft和公司Megabit之间有合作协议,根据此协议,购买将同时包含了Blazorise许可证与ABP商业产品,因此我们的客户不需要再额外购买Blazorise许可证。"
"BlazoriseLicenseExplanation": "我公司Volosoft和公司Megabit之间有合作协议,根据此协议,购买将同时包含了Blazorise许可证与ABP商业产品,因此我们的客户不需要再额外购买Blazorise许可证。",
"ExtendPaymentInfoSection_DeveloperPrice": "{0} x 开发者价格",
"ExtendPaymentInfoSection_DiscountRate": "折扣 {0}%",
"TotalNetPrice": "总净价"
}
}

5
abp_io/AbpIoLocalization/AbpIoLocalization/Commercial/Localization/Resources/zh-Hant.json

@ -192,7 +192,7 @@
"ChangingDevelopers": "我將來可以更改我組織的註冊開發人員嗎?",
"ChangingDevelopersExplanation": "除了將新的開發人員添加到你的許可中之外,你還可以更改現有的開發人員(可以刪除一個開發人員並將新的開發人員添加到同一位置),而無需任何額外費用.",
"WhenShouldIRenewMyLicense": "我什麽時候應該續訂我的許可?",
"WhenShouldIRenewMyLicenseExplanation": "如果您在許可證到期後 <strong>1 個月</strong>內續訂許可證,將享受以下折扣:團隊許可證 {0}% 折扣、商業許可證 {1}% 折扣、企業許可證 {2}% 折扣 . 如果您在許可證到期後 <strong>1 個月</strong>續訂許可證,續訂價格將與許可證購買價格相同,並且續訂不會有折扣。",
"WhenShouldIRenewMyLicenseExplanation": "如果您在許可證到期後 <strong>1 個月</strong>內續訂許可證,將享受以下折扣:團隊許可證 {0} ; 商業許可證 {1} ;企業許可證 {2}. 如果您在許可證到期後 <strong>1 個月</strong>續訂許可證,續訂價格將與許可證購買價格相同,並且續訂不會有折扣。",
"TrialPlan": "你們有試用計劃嗎?",
"DoYouAcceptBankWireTransfer": "你們接受銀行電匯嗎?",
"DoYouAcceptBankWireTransferExplanation": "是的,我們接受銀行電匯。<br />在通過銀行轉賬發送許可費後,將您的收據和所需的許可類型通過電子郵件發送至accounting@abp.io。 我們的國際銀行賬戶信息:",
@ -382,6 +382,7 @@
"TrialLicenseExpiredInfo": "您的試用許可期限已過!",
"CommercialNewsletterConfirmationMessage": "我同意<a href=\"https://commercial.abp.io/TermsConditions\">條款和條件</a>和<a href=\"https://commercial.abp.io/Privacy\">隱私政策</a>。",
"BlazoriseLicense": "我们是否需要购买Blazorise许可证?",
"BlazoriseLicenseExplanation": "我公司Volosoft和公司Megabit之间有合作协议,根据此协议,购买将同时包含了Blazorise许可证与ABP商业产品,因此我们的客户不需要再额外购买Blazorise许可证。"
"BlazoriseLicenseExplanation": "我公司Volosoft和公司Megabit之间有合作协议,根据此协议,购买将同时包含了Blazorise许可证与ABP商业产品,因此我们的客户不需要再额外购买Blazorise许可证。",
"discountForYears": "{0}% 折扣 {1} 年"
}
}

18
docs/en/UI/Angular/Account-Module.md

@ -95,6 +95,24 @@ export class AppRoutingModule {}
Before v4.3, the "My account" link in the current user dropdown on the top bar redirected the user to MVC's profile management page. As of v4.3, if you added the account module to your project, the same link will land on a page in the Angular UI account module instead.
### Personal Info Page Confirm Message
When the user changes their own data on the personal settings tab in My Account, The data can not update the CurrentUser key of Application-Configuration. The information of the user is stored in claims. The only way to apply this information to the CurrentUser of Application-Configuration is user should log out and log in. When the Refresh-Token feature is implemented, it will be fixed. So We've added a confirmation alert.
If you want to disable these warning, You should set `isPersonalSettingsChangedConfirmationActive` false
```js
// app-routing.module.ts
const routes: Routes = [
//...
{
path: 'account',
loadChildren: () => import('@volo/abp.ng.account/public').then(m => m.AccountPublicModule.forLazy({ isPersonalSettingsChangedConfirmationActive:false })),
},
//...
export class AppRoutingModule {}
```
### Security Logs Page [COMMERCIAL]
Before v4.3, the "Security Logs" link in the current user dropdown on the top bar redirected the user to MVC's security logs page. As of v4.3, if you added the account module to your project, the same link will land on a page in the Angular UI account public module instead.

219
docs/en/UI/Angular/Theme-Configurations.md

@ -1,3 +1,220 @@
# Angular UI: Theme Configurations
> This document is in draft version.
Theme packages no longer import styles as CSS modules as of ABP version 6.0. The following style settings need to be included to the angular.json file in order for theme packages to load styles.
## Lepton X Lite
```json
{
"input": "node_modules/@volo/ngx-lepton-x.lite/assets/css/bootstrap-dim.css",
"inject": false,
"bundleName": "bootstrap-dim"
},
{
"input": "node_modules/@volo/ngx-lepton-x.lite/assets/css/ng-bundle.css",
"inject": false,
"bundleName": "ng-bundle"
},
{
"input": "node_modules/@volo/ngx-lepton-x.lite/assets/css/side-menu/layout-bundle.css",
"inject": false,
"bundleName": "layout-bundle"
},
{
"input": "node_modules/@abp/ng.theme.lepton-x/assets/css/abp-bundle.css",
"inject": false,
"bundleName": "abp-bundle"
},
{
"input": "node_modules/@volo/ngx-lepton-x.lite/assets/css/bootstrap-dim.rtl.css",
"inject": false,
"bundleName": "bootstrap-dim.rtl"
},
{
"input": "node_modules/@volo/ngx-lepton-x.lite/assets/css/ng-bundle.rtl.css",
"inject": false,
"bundleName": "ng-bundle.rtl"
},
{
"input": "node_modules/@volo/ngx-lepton-x.lite/assets/css/side-menu/layout-bundle.rtl.css",
"inject": false,
"bundleName": "layout-bundle.rtl"
},
{
"input": "node_modules/@abp/ng.theme.lepton-x/assets/css/abp-bundle.rtl.css",
"inject": false,
"bundleName": "abp-bundle.rtl"
},
```
## Theme Basic
```json
{
"input": "node_modules/bootstrap/dist/css/bootstrap.rtl.min.css",
"inject": false,
"bundleName": "bootstrap-rtl.min"
},
{
"input": "node_modules/bootstrap/dist/css/bootstrap.min.css",
"inject": true,
"bundleName": "bootstrap-ltr.min"
},
```
## Lepton X
```json
{
"input": "node_modules/@volosoft/ngx-lepton-x/assets/css/dark.css",
"inject": false,
"bundleName": "dark"
},
{
"input": "node_modules/@volosoft/ngx-lepton-x/assets/css/light.css",
"inject": false,
"bundleName": "light"
},
{
"input": "node_modules/@volosoft/ngx-lepton-x/assets/css/dim.css",
"inject": false,
"bundleName": "dim"
},
{
"input": "node_modules/@volosoft/ngx-lepton-x/assets/css/bootstrap-dim.css",
"inject": false,
"bundleName": "bootstrap-dim"
},
{
"input": "node_modules/@volosoft/ngx-lepton-x/assets/css/bootstrap-dark.css",
"inject": false,
"bundleName": "bootstrap-dark"
},
{
"input": "node_modules/@volosoft/ngx-lepton-x/assets/css/bootstrap-light.css",
"inject": false,
"bundleName": "bootstrap-light"
},
{
"input": "node_modules/@volosoft/ngx-lepton-x/assets/css/ng-bundle.css",
"inject": false,
"bundleName": "ng-bundle"
},
{
"input": "node_modules/@volosoft/ngx-lepton-x/assets/css/side-menu/layout-bundle.css",
"inject": false,
"bundleName": "layout-bundle"
},
{
"input": "node_modules/@volosoft/abp.ng.theme.lepton-x/assets/css/abp-bundle.css",
"inject": false,
"bundleName": "abp-bundle"
},
{
"input": "node_modules/@volosoft/ngx-lepton-x/assets/css/dark.rtl.css",
"inject": false,
"bundleName": "dark.rtl"
},
{
"input": "node_modules/@volosoft/ngx-lepton-x/assets/css/light.rtl.css",
"inject": false,
"bundleName": "light.rtl"
},
{
"input": "node_modules/@volosoft/ngx-lepton-x/assets/css/dim.rtl.css",
"inject": false,
"bundleName": "dim.rtl"
},
{
"input": "node_modules/@volosoft/ngx-lepton-x/assets/css/bootstrap-dim.rtl.css",
"inject": false,
"bundleName": "bootstrap-dim.rtl"
},
{
"input": "node_modules/@volosoft/ngx-lepton-x/assets/css/bootstrap-dark.rtl.css",
"inject": false,
"bundleName": "bootstrap-dark.rtl"
},
{
"input": "node_modules/@volosoft/ngx-lepton-x/assets/css/bootstrap-light.rtl.css",
"inject": false,
"bundleName": "bootstrap-light.rtl"
},
{
"input": "node_modules/@volosoft/ngx-lepton-x/assets/css/ng-bundle.rtl.css",
"inject": false,
"bundleName": "ng-bundle.rtl"
},
{
"input": "node_modules/@volosoft/ngx-lepton-x/assets/css/side-menu/layout-bundle.rtl.css",
"inject": false,
"bundleName": "layout-bundle.rtl"
},
{
"input": "node_modules/@volosoft/abp.ng.theme.lepton-x/assets/css/abp-bundle.rtl.css",
"inject": false,
"bundleName": "abp-bundle.rtl"
}
```
## Theme Lepton
```json
{
"input": "node_modules/@volo/abp.ng.theme.lepton/dist/global/styles/lepton1.min.css",
"inject": false,
"bundleName": "lepton1"
},
{
"input": "node_modules/@volo/abp.ng.theme.lepton/dist/global/styles/lepton2.min.css",
"inject": false,
"bundleName": "lepton2"
},
{
"input": "node_modules/@volo/abp.ng.theme.lepton/dist/global/styles/lepton3.min.css",
"inject": false,
"bundleName": "lepton3"
},
{
"input": "node_modules/@volo/abp.ng.theme.lepton/dist/global/styles/lepton4.min.css",
"inject": false,
"bundleName": "lepton4"
},
{
"input": "node_modules/@volo/abp.ng.theme.lepton/dist/global/styles/lepton5.min.css",
"inject": false,
"bundleName": "lepton5"
},
{
"input": "node_modules/@volo/abp.ng.theme.lepton/dist/global/styles/lepton6.min.css",
"inject": false,
"bundleName": "lepton6"
},
{
"input": "node_modules/@volo/abp.ng.theme.lepton/dist/global/styles/lepton1.rtl.min.css",
"inject": false,
"bundleName": "lepton1.rtl"
},
{
"input": "node_modules/@volo/abp.ng.theme.lepton/dist/global/styles/lepton2.rtl.min.css",
"inject": false,
"bundleName": "lepton2.rtl"
},
{
"input": "node_modules/@volo/abp.ng.theme.lepton/dist/global/styles/lepton3.rtl.min.css",
"inject": false,
"bundleName": "lepton3.rtl"
},
{
"input": "node_modules/@volo/abp.ng.theme.lepton/dist/global/styles/lepton4.rtl.min.css",
"inject": false,
"bundleName": "lepton4.rtl"
},
{
"input": "node_modules/@volo/abp.ng.theme.lepton/dist/global/styles/lepton5.rtl.min.css",
"inject": false,
"bundleName": "lepton5.rtl"
},
{
"input": "node_modules/@volo/abp.ng.theme.lepton/dist/global/styles/lepton6.rtl.min.css",
"inject": false,
"bundleName": "lepton6.rtl"
},
```

2
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/ContentFormatters/RemoteStreamContentOutputFormatter.cs

@ -27,7 +27,7 @@ public class RemoteStreamContentOutputFormatter : OutputFormatter
context.HttpContext.Response.ContentType = remoteStream.ContentType;
context.HttpContext.Response.ContentLength = remoteStream.ContentLength;
if (!remoteStream.FileName.IsNullOrWhiteSpace())
if (!remoteStream.FileName.IsNullOrWhiteSpace() && !context.HttpContext.Response.Headers.ContainsKey(HeaderNames.ContentDisposition))
{
var contentDisposition = new ContentDispositionHeaderValue("attachment");
contentDisposition.SetHttpFileName(remoteStream.FileName);

10
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Uow/AbpUowActionFilter.cs

@ -98,7 +98,15 @@ public class AbpUowActionFilter : IAsyncActionFilter, ITransientDependency
var currentUow = unitOfWorkManager.Current;
if (currentUow != null)
{
await currentUow.SaveChangesAsync(context.HttpContext.RequestAborted);
try
{
await currentUow.SaveChangesAsync(context.HttpContext.RequestAborted);
}
catch (Exception e)
{
await currentUow.RollbackAsync(context.HttpContext.RequestAborted);
throw;
}
}
}

10
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Uow/AbpUowPageFilter.cs

@ -104,7 +104,15 @@ public class AbpUowPageFilter : IAsyncPageFilter, ITransientDependency
var currentUow = unitOfWorkManager.Current;
if (currentUow != null)
{
await currentUow.SaveChangesAsync(context.HttpContext.RequestAborted);
try
{
await currentUow.SaveChangesAsync(context.HttpContext.RequestAborted);
}
catch (Exception e)
{
await currentUow.RollbackAsync(context.HttpContext.RequestAborted);
throw;
}
}
}

31
framework/src/Volo.Abp.BackgroundJobs.Abstractions/Volo/Abp/BackgroundJobs/BackgroundJobExecuter.cs

@ -6,6 +6,7 @@ using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.DependencyInjection;
using Volo.Abp.ExceptionHandling;
using Volo.Abp.MultiTenancy;
namespace Volo.Abp.BackgroundJobs;
@ -14,9 +15,12 @@ public class BackgroundJobExecuter : IBackgroundJobExecuter, ITransientDependenc
public ILogger<BackgroundJobExecuter> Logger { protected get; set; }
protected AbpBackgroundJobOptions Options { get; }
protected ICurrentTenant CurrentTenant { get; }
public BackgroundJobExecuter(IOptions<AbpBackgroundJobOptions> options)
public BackgroundJobExecuter(IOptions<AbpBackgroundJobOptions> options, ICurrentTenant currentTenant)
{
CurrentTenant = currentTenant;
Options = options.Value;
Logger = NullLogger<BackgroundJobExecuter>.Instance;
@ -40,14 +44,18 @@ public class BackgroundJobExecuter : IBackgroundJobExecuter, ITransientDependenc
try
{
if (jobExecuteMethod.Name == nameof(IAsyncBackgroundJob<object>.ExecuteAsync))
using(CurrentTenant.Change(GetJobArgsTenantId(context.JobArgs)))
{
await ((Task)jobExecuteMethod.Invoke(job, new[] { context.JobArgs }));
}
else
{
jobExecuteMethod.Invoke(job, new[] { context.JobArgs });
if (jobExecuteMethod.Name == nameof(IAsyncBackgroundJob<object>.ExecuteAsync))
{
await ((Task)jobExecuteMethod.Invoke(job, new[] { context.JobArgs }));
}
else
{
jobExecuteMethod.Invoke(job, new[] { context.JobArgs });
}
}
}
catch (Exception ex)
{
@ -64,4 +72,13 @@ public class BackgroundJobExecuter : IBackgroundJobExecuter, ITransientDependenc
};
}
}
protected virtual Guid? GetJobArgsTenantId(object jobArgs)
{
return jobArgs switch
{
IMultiTenant multiTenantJobArgs => multiTenantJobArgs.TenantId,
_ => CurrentTenant.Id
};
}
}

8
framework/src/Volo.Abp.BlazoriseUI/Volo.Abp.BlazoriseUI.csproj

@ -14,10 +14,10 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Blazorise" Version="1.0.6" />
<PackageReference Include="Blazorise.DataGrid" Version="1.0.6" />
<PackageReference Include="Blazorise.Snackbar" Version="1.0.6" />
<PackageReference Include="Blazorise.Components" Version="1.0.6" />
<PackageReference Include="Blazorise" Version="1.1.2" />
<PackageReference Include="Blazorise.DataGrid" Version="1.1.2" />
<PackageReference Include="Blazorise.Snackbar" Version="1.1.2" />
<PackageReference Include="Blazorise.Components" Version="1.1.2" />
</ItemGroup>
</Project>

8
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Bundling/BundlingService.cs

@ -108,15 +108,15 @@ public class BundlingService : IBundlingService, ITransientDependency
Parameters = parameters
};
scriptContext.BundleDefinitions.AddIfNotContains(
x => x.Source == "_framework/blazor.webassembly.js",
() => new BundleDefinition { Source = "_framework/blazor.webassembly.js" });
foreach (var bundleDefinition in bundleDefinitions)
{
var contributor = CreateContributorInstance(bundleDefinition.BundleContributorType);
contributor.AddScripts(scriptContext);
}
scriptContext.BundleDefinitions.AddIfNotContains(
x => x.Source == "_framework/blazor.webassembly.js",
() => new BundleDefinition { Source = "_framework/blazor.webassembly.js" });
return scriptContext;
}

1
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Licensing/DeveloperApiKeyResult.cs

@ -13,6 +13,7 @@ public class DeveloperApiKeyResult
public string ErrorMessage { get; set; }
public LicenseErrorType? ErrorType { get; set; }
public LicenseType LicenseType { get; set; }
public bool IsTrialLicense { get; set; }
public enum LicenseErrorType
{

8
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Building/Steps/DatabaseManagementSystemChangeStep.cs

@ -98,7 +98,13 @@ public class DatabaseManagementSystemChangeStep : ProjectBuildPipelineStep
var oldUseMethod = "UseSqlServer";
var efCoreModuleClass = context.Files.First(f => f.Name.EndsWith("EntityFrameworkCoreModule.cs", StringComparison.OrdinalIgnoreCase));
var efCoreModuleClass = context.Files.FirstOrDefault(f => f.Name.EndsWith("EntityFrameworkCoreModule.cs", StringComparison.OrdinalIgnoreCase));
if(efCoreModuleClass == null)
{
return;
}
efCoreModuleClass.ReplaceText(oldUseMethod, newUseMethodForEfModule);
var dbContextFactoryFile = context.Files.FirstOrDefault(f => f.Name.EndsWith($"{(_hasDbMigrations ? "Migrations" : string.Empty)}DbContextFactoryBase.cs", StringComparison.OrdinalIgnoreCase))

2
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Files/FileEntryExtensions.cs

@ -120,7 +120,7 @@ public static class FileEntryExtensions
}
}
if ((i + 1 < lines.Length) && (lines[i + 1].Contains("<TEMPLATE-REMOVE")))
if (i < lines.Length - 1 && lines[i+1].Contains("<TEMPLATE-REMOVE"))
{
continue;
}

9
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/ProjectBuilding/Templates/RemoveUnnecessaryPortsStep.cs

@ -58,8 +58,13 @@ public class RemoveUnnecessaryPortsStep : ProjectBuildPipelineStep
f.Name.Contains("MyCompanyName.MyProjectName.DbMigrator") && f.Name.EndsWith("appsettings.json"));
var appSettingsJsonObject = JObject.Parse(dbMigratorAppSettings.Content);
var authServerJsonObject = (JObject)appSettingsJsonObject["IdentityServer"] ?? (JObject)appSettingsJsonObject["OpenIddict"];
var clientsJsonObject = (JObject)authServerJsonObject["Clients"] ?? (JObject)authServerJsonObject["Applications"];
var authServerJsonObject = (JObject)appSettingsJsonObject?["IdentityServer"] ?? (JObject)appSettingsJsonObject["OpenIddict"];
var clientsJsonObject = (JObject)authServerJsonObject?["Clients"] ?? (JObject)authServerJsonObject?["Applications"];
if (clientsJsonObject == null)
{
return;
}
if (context.BuildArgs.UiFramework != UiFramework.Blazor)
{

14
framework/src/Volo.Abp.Core/Microsoft/Extensions/DependencyInjection/ServiceCollectionConfigurationExtensions.cs

@ -1,6 +1,8 @@
using Microsoft.Extensions.Configuration;
using JetBrains.Annotations;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Hosting;
using Volo.Abp;
namespace Microsoft.Extensions.DependencyInjection;
@ -11,7 +13,15 @@ public static class ServiceCollectionConfigurationExtensions
return services.Replace(ServiceDescriptor.Singleton<IConfiguration>(configuration));
}
[NotNull]
public static IConfiguration GetConfiguration(this IServiceCollection services)
{
return services.GetConfigurationOrNull() ??
throw new AbpException("Could not find an implementation of " + typeof(IConfiguration).AssemblyQualifiedName + " in the service collection.");
}
[CanBeNull]
public static IConfiguration GetConfigurationOrNull(this IServiceCollection services)
{
var hostBuilderContext = services.GetSingletonInstanceOrNull<HostBuilderContext>();
if (hostBuilderContext?.Configuration != null)
@ -19,6 +29,6 @@ public static class ServiceCollectionConfigurationExtensions
return hostBuilderContext.Configuration as IConfigurationRoot;
}
return services.GetSingletonInstance<IConfiguration>();
return services.GetSingletonInstanceOrNull<IConfiguration>();
}
}

34
framework/src/Volo.Abp.Core/Volo/Abp/AbpApplicationBase.cs

@ -23,7 +23,7 @@ public abstract class AbpApplicationBase : IAbpApplication
public IServiceCollection Services { get; }
public IReadOnlyList<IAbpModuleDescriptor> Modules { get; }
public string ApplicationName { get; }
private bool _configuredServices;
@ -43,8 +43,8 @@ public abstract class AbpApplicationBase : IAbpApplication
var options = new AbpApplicationCreationOptions(services);
optionsAction?.Invoke(options);
ApplicationName = options.ApplicationName;
ApplicationName = GetApplicationName(options);
services.AddSingleton<IAbpApplication>(this);
services.AddSingleton<IApplicationNameAccessor>(this);
@ -147,7 +147,7 @@ public abstract class AbpApplicationBase : IAbpApplication
public virtual async Task ConfigureServicesAsync()
{
CheckMultipleConfigureServices();
var context = new ServiceConfigurationContext(Services);
Services.AddSingleton(context);
@ -312,4 +312,30 @@ public abstract class AbpApplicationBase : IAbpApplication
_configuredServices = true;
}
private static string GetApplicationName(AbpApplicationCreationOptions options)
{
if (!string.IsNullOrWhiteSpace(options.ApplicationName))
{
return options.ApplicationName;
}
var configuration = options.Services.GetConfigurationOrNull();
if (configuration != null)
{
var appNameConfig = configuration["ApplicationName"];
if (!string.IsNullOrWhiteSpace(appNameConfig))
{
return appNameConfig;
}
}
var entryAssembly = Assembly.GetEntryAssembly();
if (entryAssembly != null)
{
return entryAssembly.GetName().Name;
}
return null;
}
}

3
framework/src/Volo.Abp.Core/Volo/Abp/IApplicationNameAccessor.cs

@ -1,3 +1,5 @@
using JetBrains.Annotations;
namespace Volo.Abp;
public interface IApplicationNameAccessor
@ -7,5 +9,6 @@ public interface IApplicationNameAccessor
/// This is useful for systems with multiple applications, to distinguish
/// resources of the applications located together.
/// </summary>
[CanBeNull]
string ApplicationName { get; }
}

2
framework/src/Volo.Abp.EntityFrameworkCore.PostgreSql/Volo.Abp.EntityFrameworkCore.PostgreSql.csproj

@ -19,7 +19,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="7.0.0-rc.1" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="7.0.0-rc.2" />
</ItemGroup>
</Project>

21
framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/ContentFormatters/RemoteStreamContentTestController.cs

@ -19,6 +19,27 @@ public class RemoteStreamContentTestController : AbpController
memoryStream.Position = 0;
return new RemoteStreamContent(memoryStream, "download.rtf", "application/rtf");
}
[HttpGet]
[Route("Download-With-Custom-Content-Disposition")]
public async Task<IRemoteStreamContent> Download_With_Custom_Content_Disposition_Async()
{
var memoryStream = new MemoryStream();
await memoryStream.WriteAsync(Encoding.UTF8.GetBytes("DownloadAsync"));
memoryStream.Position = 0;
Response.Headers.Add("Content-Disposition", "attachment; filename=myDownload.rtf");
return new RemoteStreamContent(memoryStream, "download.rtf", "application/rtf");
}
[HttpGet]
[Route("Download_With_Chinese_File_Name")]
public async Task<IRemoteStreamContent> Download_With_Chinese_File_Name_Async()
{
var memoryStream = new MemoryStream();
await memoryStream.WriteAsync(Encoding.UTF8.GetBytes("DownloadAsync"));
memoryStream.Position = 0;
return new RemoteStreamContent(memoryStream, "下载文件.rtf", "application/rtf");
}
[HttpPost]
[Route("Upload")]

21
framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/ContentFormatters/RemoteStreamContentTestController_Tests.cs

@ -3,6 +3,7 @@ using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using Shouldly;
using Xunit;
@ -19,6 +20,26 @@ public class RemoteStreamContentTestController_Tests : AspNetCoreMvcTestBase
result.Content.Headers.ContentLength.ShouldBe("DownloadAsync".Length);
(await result.Content.ReadAsStringAsync()).ShouldBe("DownloadAsync");
}
[Fact]
public async Task Download_With_Custom_Content_Disposition_Async()
{
var result = await GetResponseAsync("/api/remote-stream-content-test/download-with-custom-content-disposition");
result.Content.Headers.ContentType?.ToString().ShouldBe("application/rtf");
result.Content.Headers.ContentDisposition?.FileName.ShouldBe("myDownload.rtf");
result.Content.Headers.ContentLength.ShouldBe("DownloadAsync".Length);
(await result.Content.ReadAsStringAsync()).ShouldBe("DownloadAsync");
}
[Fact]
public async Task Download_With_Chinese_File_Name_Async()
{
var result = await GetResponseAsync("/api/remote-stream-content-test/download_with_chinese_file_name");
result.Content.Headers.ContentType?.ToString().ShouldBe("application/rtf");
result.Content.Headers.ContentDisposition?.FileNameStar.ShouldBe("下载文件.rtf");
result.Content.Headers.ContentLength.ShouldBe("DownloadAsync".Length);
(await result.Content.ReadAsStringAsync()).ShouldBe("DownloadAsync");
}
[Fact]
public async Task UploadAsync()

32
framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/ExceptionHandling/ExceptionHandingUnitOfWork.cs

@ -0,0 +1,32 @@
using System;
using System.Data;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Volo.Abp.Data;
using Volo.Abp.Uow;
using Volo.Abp.Users;
namespace Volo.Abp.AspNetCore.Mvc.ExceptionHandling;
public class ExceptionHandingUnitOfWork : UnitOfWork
{
public ExceptionHandingUnitOfWork(
IServiceProvider serviceProvider,
IUnitOfWorkEventPublisher unitOfWorkEventPublisher,
IOptions<AbpUnitOfWorkDefaultOptions> options)
: base(serviceProvider, unitOfWorkEventPublisher, options)
{
}
public async override Task SaveChangesAsync(CancellationToken cancellationToken = default)
{
if (ServiceProvider.GetRequiredService<ICurrentUser>().Id == Guid.Empty)
{
throw new AbpDbConcurrencyException();
}
await base.SaveChangesAsync(cancellationToken);
}
}

10
framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/ExceptionHandling/ExceptionTestController.cs

@ -1,4 +1,5 @@
using Microsoft.AspNetCore.Mvc;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Volo.Abp.Authorization;
namespace Volo.Abp.AspNetCore.Mvc.ExceptionHandling;
@ -26,4 +27,11 @@ public class ExceptionTestController : AbpController
{
throw new AbpAuthorizationException("This is a sample exception!");
}
[HttpGet]
[Route("ExceptionOnUowSaveChange")]
public Task<string> ExceptionOnUowSaveChangeAsync()
{
return Task.FromResult("OK");
}
}

24
framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/ExceptionHandling/ExceptionTestController_Tests.cs

@ -3,12 +3,14 @@ using System.Net;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Hosting;
using NSubstitute;
using Shouldly;
using Volo.Abp.ExceptionHandling;
using Volo.Abp.Http;
using Volo.Abp.Security.Claims;
using Volo.Abp.Uow;
using Xunit;
namespace Volo.Abp.AspNetCore.Mvc.ExceptionHandling;
@ -31,6 +33,8 @@ public class ExceptionTestController_Tests : AspNetCoreMvcTestBase
_fakeExceptionSubscriber = Substitute.For<IExceptionSubscriber>();
services.AddSingleton(_fakeExceptionSubscriber);
services.Replace(ServiceDescriptor.Transient<IUnitOfWork, ExceptionHandingUnitOfWork>());
}
[Fact]
@ -93,4 +97,24 @@ public class ExceptionTestController_Tests : AspNetCoreMvcTestBase
.HandleAsync(Arg.Any<ExceptionNotificationContext>());
#pragma warning restore 4014
}
[Fact]
public async Task Should_Handle_Exception_On_Uow_SaveChangeAsync()
{
FakeRequiredService.Claims.AddRange(new[]
{
new Claim(AbpClaimTypes.UserId, Guid.Empty.ToString())
});
var result = await GetResponseAsObjectAsync<RemoteServiceErrorResponse>("/api/exception-test/ExceptionOnUowSaveChange", HttpStatusCode.Conflict);
result.Error.ShouldNotBeNull();
result.Error.Message.ShouldBe("The data you have submitted has already changed by another user/client. Please discard the changes you've done and try from the beginning.");
#pragma warning disable 4014
_fakeExceptionSubscriber
.Received()
.HandleAsync(Arg.Any<ExceptionNotificationContext>());
#pragma warning restore 4014
}
}

5
framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/ExceptionHandling/ExceptionTestPage.cshtml.cs

@ -36,4 +36,9 @@ public class ExceptionTestPage : AbpPageModel
{
throw new AbpAuthorizationException("This is a sample exception!");
}
public Task<JsonResult> OnGetExceptionOnUowSaveChangeAsync()
{
return Task.FromResult(new JsonResult("OK"));
}
}

25
framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/ExceptionHandling/ExceptionTestPage_Tests.cs

@ -3,12 +3,14 @@ using System.Net;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Hosting;
using NSubstitute;
using Shouldly;
using Volo.Abp.ExceptionHandling;
using Volo.Abp.Http;
using Volo.Abp.Security.Claims;
using Volo.Abp.Uow;
using Xunit;
namespace Volo.Abp.AspNetCore.Mvc.ExceptionHandling;
@ -31,6 +33,8 @@ public class ExceptionTestPage_Tests : AspNetCoreMvcTestBase
_fakeExceptionSubscriber = Substitute.For<IExceptionSubscriber>();
services.AddSingleton(_fakeExceptionSubscriber);
services.Replace(ServiceDescriptor.Transient<IUnitOfWork, ExceptionHandingUnitOfWork>());
}
[Fact]
@ -140,4 +144,25 @@ public class ExceptionTestPage_Tests : AspNetCoreMvcTestBase
.HandleAsync(Arg.Any<ExceptionNotificationContext>());
#pragma warning restore 4014
}
[Fact]
public async Task Should_Handle_Exception_On_Uow_SaveChangeAsync()
{
_fakeRequiredService.Claims.AddRange(new[]
{
new Claim(AbpClaimTypes.UserId, Guid.Empty.ToString())
});
var result = await GetResponseAsObjectAsync<RemoteServiceErrorResponse>("/api/exception-test/ExceptionOnUowSaveChange", HttpStatusCode.Conflict);
result.Error.ShouldNotBeNull();
result.Error.Message.ShouldBe("The data you have submitted has already changed by another user/client. Please discard the changes you've done and try from the beginning.");
#pragma warning disable 4014
_fakeExceptionSubscriber
.Received()
.HandleAsync(Arg.Any<ExceptionNotificationContext>());
#pragma warning restore 4014
}
}

8
framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Uow/UnitOfWorkMiddleware_Exception_Rollback_Tests.cs

@ -2,15 +2,23 @@
using System.Net;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Hosting;
using Shouldly;
using Volo.Abp.Http;
using Volo.Abp.Json;
using Volo.Abp.Uow;
using Xunit;
namespace Volo.Abp.AspNetCore.Mvc.Uow;
public class UnitOfWorkMiddleware_Exception_Rollback_Tests : AspNetCoreMvcTestBase
{
protected override void ConfigureServices(HostBuilderContext context, IServiceCollection services)
{
services.Replace(ServiceDescriptor.Transient<IUnitOfWork, TestUnitOfWork>());
}
[Fact]
public async Task Should_Rollback_Transaction_For_Handled_Exceptions()
{

8
framework/test/Volo.Abp.AspNetCore.Mvc.Tests/Volo/Abp/AspNetCore/Mvc/Uow/UnitOfWorkPageFilter_Exception_Rollback_Tests.cs

@ -2,15 +2,23 @@
using System.Net;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Hosting;
using Shouldly;
using Volo.Abp.Http;
using Volo.Abp.Json;
using Volo.Abp.Uow;
using Xunit;
namespace Volo.Abp.AspNetCore.Mvc.Uow;
public class UnitOfWorkPageFilter_Exception_Rollback_Tests : AspNetCoreMvcTestBase
{
protected override void ConfigureServices(HostBuilderContext context, IServiceCollection services)
{
services.Replace(ServiceDescriptor.Transient<IUnitOfWork, TestUnitOfWork>());
}
[Fact]
public async Task Should_Rollback_Transaction_For_Handled_Exceptions()
{

33
framework/test/Volo.Abp.BackgroundJobs.Tests/Volo/Abp/BackgroundJobs/BackgroundJobExecuter_Tests.cs

@ -1,3 +1,4 @@
using System;
using System.Threading.Tasks;
using Shouldly;
using Xunit;
@ -58,4 +59,36 @@ public class BackgroundJobExecuter_Tests : BackgroundJobsTestBase
jobObject.ExecutedValues.ShouldContain("42");
}
[Fact]
public async Task Should_Change_TenantId_If_EventData_Is_MultiTenant()
{
//Arrange
var tenantId = Guid.NewGuid();
var jobObject = GetRequiredService<MyJob>();
var asyncJobObject = GetRequiredService<MyAsyncJob>();
//Act
await _backgroundJobExecuter.ExecuteAsync(
new JobExecutionContext(
ServiceProvider,
typeof(MyJob),
new MyJobArgs("42", tenantId)
)
);
await _backgroundJobExecuter.ExecuteAsync(
new JobExecutionContext(
ServiceProvider,
typeof(MyAsyncJob),
new MyAsyncJobArgs("42", tenantId)
)
);
//Assert
jobObject.TenantId.ShouldBe(tenantId);
asyncJobObject.TenantId.ShouldBe(tenantId);
}
}

12
framework/test/Volo.Abp.BackgroundJobs.Tests/Volo/Abp/BackgroundJobs/MyAsyncJob.cs

@ -2,17 +2,27 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
using Volo.Abp.MultiTenancy;
namespace Volo.Abp.BackgroundJobs;
public class MyAsyncJob : AsyncBackgroundJob<MyAsyncJobArgs>, ISingletonDependency
{
public List<string> ExecutedValues { get; } = new List<string>();
public Guid? TenantId { get; set; }
private readonly ICurrentTenant _currentTenant;
public MyAsyncJob(ICurrentTenant currentTenant)
{
_currentTenant = currentTenant;
}
public override Task ExecuteAsync(MyAsyncJobArgs args)
{
ExecutedValues.Add(args.Value);
TenantId = _currentTenant.Id;
return Task.CompletedTask;
}
}

12
framework/test/Volo.Abp.BackgroundJobs.Tests/Volo/Abp/BackgroundJobs/MyAsyncJobArgs.cs

@ -1,16 +1,22 @@
namespace Volo.Abp.BackgroundJobs;
using System;
using Volo.Abp.MultiTenancy;
public class MyAsyncJobArgs
namespace Volo.Abp.BackgroundJobs;
public class MyAsyncJobArgs: IMultiTenant
{
public string Value { get; set; }
public Guid? TenantId { get; }
public MyAsyncJobArgs()
{
}
public MyAsyncJobArgs(string value)
public MyAsyncJobArgs(string value, Guid? tenantId = null)
{
Value = value;
TenantId = tenantId;
}
}

14
framework/test/Volo.Abp.BackgroundJobs.Tests/Volo/Abp/BackgroundJobs/MyJob.cs

@ -1,14 +1,26 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using Volo.Abp.DependencyInjection;
using Volo.Abp.MultiTenancy;
namespace Volo.Abp.BackgroundJobs;
public class MyJob : BackgroundJob<MyJobArgs>, ISingletonDependency
{
public List<string> ExecutedValues { get; } = new List<string>();
public Guid? TenantId { get; set; }
private readonly ICurrentTenant _currentTenant;
public MyJob(ICurrentTenant currentTenant)
{
_currentTenant = currentTenant;
}
public override void Execute(MyJobArgs args)
{
ExecutedValues.Add(args.Value);
TenantId = _currentTenant.Id;
}
}

13
framework/test/Volo.Abp.BackgroundJobs.Tests/Volo/Abp/BackgroundJobs/MyJobArgs.cs

@ -1,6 +1,9 @@
namespace Volo.Abp.BackgroundJobs;
using System;
using Volo.Abp.MultiTenancy;
public class MyJobArgs
namespace Volo.Abp.BackgroundJobs;
public class MyJobArgs : IMultiTenant
{
public string Value { get; set; }
@ -8,9 +11,13 @@ public class MyJobArgs
{
}
public MyJobArgs(string value)
public MyJobArgs(string value, Guid? tenantId = null)
{
Value = value;
TenantId = tenantId;
}
public Guid? TenantId { get; }
}

51
framework/test/Volo.Abp.Core.Tests/Volo/Abp/AbpApplication_Initialize_Tests.cs

@ -1,10 +1,16 @@
using System.Threading.Tasks;
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Threading.Tasks;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using NSubstitute;
using Shouldly;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Modularity;
using Volo.Abp.Modularity.PlugIns;
using Xunit;
using IConfiguration = Castle.Core.Configuration.IConfiguration;
namespace Volo.Abp;
@ -147,8 +153,8 @@ public class AbpApplication_Initialize_Tests
[Fact]
public void Should_Set_And_Get_ApplicationName()
{
const string applicationName = "MyApplication";
var applicationName = "MyApplication";
using (var application = AbpApplicationFactory.Create<IndependentEmptyModule>(options =>
{
options.ApplicationName = applicationName;
@ -156,16 +162,49 @@ public class AbpApplication_Initialize_Tests
{
application.ApplicationName.ShouldBe(applicationName);
application.Services.GetApplicationName().ShouldBe(applicationName);
application.Initialize();
application.ServiceProvider
.GetRequiredService<IApplicationNameAccessor>()
.ApplicationName
.ShouldBe(applicationName);
}
using (var application = AbpApplicationFactory.Create<IndependentEmptyModule>(options =>
{
options.Services.ReplaceConfiguration(new ConfigurationBuilder()
.AddInMemoryCollection(new Dictionary<string, string> {{"ApplicationName", applicationName}})
.Build());
}))
{
application.ApplicationName.ShouldBe(applicationName);
application.Services.GetApplicationName().ShouldBe(applicationName);
application.Initialize();
application.ServiceProvider
.GetRequiredService<IApplicationNameAccessor>()
.ApplicationName
.ShouldBe(applicationName);
}
applicationName = Assembly.GetEntryAssembly()?.GetName().Name;
using (var application = AbpApplicationFactory.Create<IndependentEmptyModule>())
{
application.ApplicationName.ShouldBe(applicationName);
application.Services.GetApplicationName().ShouldBe(applicationName);
application.Initialize();
application.ServiceProvider
.GetRequiredService<IApplicationNameAccessor>()
.ApplicationName
.ShouldBe(applicationName);
}
}
[Fact]
public async Task Should_Resolve_Root_Service_Provider()
{

2
modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/en.json

@ -34,6 +34,8 @@
"DisplayName:PhoneNumber": "Phone number",
"PersonalSettings": "Personal settings",
"PersonalSettingsSaved": "Personal settings saved",
"PersonalSettingsChangedConfirmationModalTitle": "Personal info changed",
"PersonalSettingsChangedConfirmationModalDescription": "If you want to apply these changes, you have to login. Do you want to log out?",
"PasswordChanged": "Password changed",
"NewPasswordConfirmFailed": "Please confirm the new password.",
"NewPasswordSameAsOld": "New password must be different from the old one.",

2
modules/account/src/Volo.Abp.Account.Application.Contracts/Volo/Abp/Account/Localization/Resources/tr.json

@ -34,6 +34,8 @@
"DisplayName:PhoneNumber": "Telefon numarası",
"PersonalSettings": "Kişisel ayarlar",
"PersonalSettingsSaved": "Kişisel ayarlar kaydedildi",
"PersonalSettingsChangedConfirmationModalTitle": "Personal info changed",
"PersonalSettingsChangedConfirmationModalDescription": "If you want to apply these changes, you have to login. Do you want to log out?",
"PasswordChanged": "Şifre değiştirildi",
"NewPasswordConfirmFailed": "Lütfen yeni şifreyi onaylayın.",
"NewPasswordSameAsOld": "Yeni şifre eski şifre ile aynı olamaz.",

2
modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp.HangFire/appsettings.json

@ -1,5 +1,5 @@
{
"ConnectionStrings": {
"Default": "Server=localhost;Database=BackgroundJobsDemoApp;Trusted_Connection=True"
"Default": "Server=localhost;Database=BackgroundJobsDemoApp;Trusted_Connection=True;TrustServerCertificate=True"
}
}

2
modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp/appsettings.json

@ -1,5 +1,5 @@
{
"ConnectionStrings": {
"Default": "Server=localhost;Database=BackgroundJobsDemoApp;Trusted_Connection=True"
"Default": "Server=localhost;Database=BackgroundJobsDemoApp;Trusted_Connection=True;TrustServerCertificate=True"
}
}

19
modules/basic-theme/src/Volo.Abp.AspNetCore.Components.Web.BasicTheme/Themes/Basic/RedirectToLogin.razor

@ -1,17 +1,10 @@
@inject NavigationManager Navigation
@inject IJSRuntime JSRuntime
@code {
@code {
protected override void OnInitialized()
{
bool isWebAssembly = JSRuntime is IJSInProcessRuntime;
if (isWebAssembly)
{
Navigation.NavigateTo($"authentication/login?returnUrl={Uri.EscapeDataString(Navigation.Uri)}");
}
else
{
Navigation.NavigateTo($"account/login?returnUrl={Uri.EscapeDataString(Navigation.Uri)}", true);
}
}
}
Navigation.NavigateTo($"account/login?returnUrl={Uri.EscapeDataString(Navigation.Uri)}", true);
}
}

13
modules/basic-theme/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/LoginDisplay.razor.cs

@ -18,9 +18,6 @@ public partial class LoginDisplay : IDisposable
[Inject]
public AuthenticationStateProvider AuthenticationStateProvider { get; set; }
[CanBeNull]
protected SignOutSessionStateManager SignOutManager;
protected ApplicationMenu Menu { get; set; }
protected override async Task OnInitializedAsync()
@ -29,8 +26,6 @@ public partial class LoginDisplay : IDisposable
Navigation.LocationChanged += OnLocationChanged;
LazyGetService(ref SignOutManager);
AuthenticationStateProvider.AuthenticationStateChanged +=
AuthenticationStateProviderOnAuthenticationStateChanged;
}
@ -65,12 +60,8 @@ public partial class LoginDisplay : IDisposable
}
}
private async Task BeginSignOut()
private void BeginSignOut()
{
if (SignOutManager != null)
{
await SignOutManager.SetSignOutState();
await NavigateToAsync("authentication/logout");
}
Navigation.NavigateToLogout("authentication/logout");
}
}

17
modules/basic-theme/src/Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme/Themes/Basic/WebAssemblyRedirectToLogin.razor

@ -0,0 +1,17 @@
@inject NavigationManager Navigation
@using Volo.Abp.DependencyInjection
@using Volo.Abp.AspNetCore.Components.Web.BasicTheme.Themes.Basic
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication
@inherits RedirectToLogin
@attribute [ExposeServices(typeof(RedirectToLogin))]
@attribute [Dependency(ReplaceServices = true)]
@code {
protected override void OnInitialized()
{
Navigation.NavigateToLogin("authentication/login");
}
}

2
modules/basic-theme/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Dockerfile

@ -1,4 +1,4 @@
FROM mcr.microsoft.com/dotnet/aspnet:6.0.0-bullseye-slim AS base
FROM mcr.microsoft.com/dotnet/aspnet:7.0-bullseye-slim AS base
WORKDIR /app
EXPOSE 80
COPY bin/Release/publish .

2
modules/blob-storing-database/host/BlobStoring.Database.Host.ConsoleApp/src/BlobStoring.Database.Host.ConsoleApp.ConsoleApp/appsettings.json

@ -1,5 +1,5 @@
{
"ConnectionStrings": {
"Default": "Server=localhost;Database=BlobStoring_Host;Trusted_Connection=True"
"Default": "Server=localhost;Database=BlobStoring_Host;Trusted_Connection=True;TrustServerCertificate=True"
}
}

2
modules/blogging/app/Volo.BloggingTestApp/appsettings.json

@ -1,6 +1,6 @@
{
"ConnectionStrings": {
"SqlServer": "Server=localhost;Database=BloggingTestApp;Trusted_Connection=True",
"SqlServer": "Server=localhost;Database=BloggingTestApp;Trusted_Connection=True;TrustServerCertificate=True",
"MongoDb": "mongodb://localhost:27017/BloggingTestApp"
}
}

2
modules/cms-kit/database/Dockerfile

@ -1,4 +1,4 @@
FROM mcr.microsoft.com/dotnet/core/sdk:3.0-buster AS build
FROM mcr.microsoft.com/dotnet/core/sdk:7.0 AS build
COPY . .
WORKDIR /templates/service/host/IdentityServerHost

4
modules/cms-kit/host/Volo.CmsKit.HttpApi.Host/Dockerfile

@ -1,8 +1,8 @@
FROM mcr.microsoft.com/dotnet/core/aspnet:3.0-buster-slim AS base
FROM mcr.microsoft.com/dotnet/core/aspnet:7.0-bullseye-slim AS base
WORKDIR /app
EXPOSE 80
FROM mcr.microsoft.com/dotnet/core/sdk:3.0-buster AS build
FROM mcr.microsoft.com/dotnet/core/sdk:7.0 AS build
WORKDIR /src
COPY . .
WORKDIR /src/templates/service/host/Volo.CmsKit.HttpApi.Host

4
modules/cms-kit/host/Volo.CmsKit.HttpApi.Host/appsettings.json

@ -3,8 +3,8 @@
"CorsOrigins": "https://*.CmsKit.com,http://localhost:4200"
},
"ConnectionStrings": {
"Default": "Server=localhost;Database=CmsKit_Main;Trusted_Connection=True",
"CmsKit": "Server=localhost;Database=CmsKit_Module;Trusted_Connection=True"
"Default": "Server=localhost;Database=CmsKit_Main;Trusted_Connection=True;TrustServerCertificate=True",
"CmsKit": "Server=localhost;Database=CmsKit_Module;Trusted_Connection=True;TrustServerCertificate=True"
},
"Redis": {
"Configuration": "127.0.0.1"

4
modules/cms-kit/host/Volo.CmsKit.IdentityServer/Dockerfile

@ -1,8 +1,8 @@
FROM mcr.microsoft.com/dotnet/core/aspnet:3.0-buster-slim AS base
FROM mcr.microsoft.com/dotnet/core/aspnet:7.0-bullseye-slim AS base
WORKDIR /app
EXPOSE 80
FROM mcr.microsoft.com/dotnet/core/sdk:3.0-buster AS build
FROM mcr.microsoft.com/dotnet/core/sdk:7.0 AS build
WORKDIR /src
COPY . .
WORKDIR /src/templates/service/host/Volo.CmsKit.IdentityServer

2
modules/cms-kit/host/Volo.CmsKit.IdentityServer/appsettings.json

@ -5,7 +5,7 @@
},
"AppSelfUrl": "https://localhost:44318/",
"ConnectionStrings": {
"Default": "Server=localhost;Database=CmsKit_Main;Trusted_Connection=True"
"Default": "Server=localhost;Database=CmsKit_Main;Trusted_Connection=True;TrustServerCertificate=True"
},
"Redis": {
"Configuration": "127.0.0.1"

2
modules/cms-kit/host/Volo.CmsKit.Web.Unified/appsettings.json

@ -1,5 +1,5 @@
{
"ConnectionStrings": {
"Default": "Server=(localdb)\\MSSQLLocalDB;Database=CmsKit_Unified;Trusted_Connection=True"
"Default": "Server=(localdb)\\MSSQLLocalDB;Database=CmsKit_Unified;Trusted_Connection=True;TrustServerCertificate=True"
}
}

4
modules/docs/app/VoloDocs.Migrator/Dockerfile

@ -1,8 +1,8 @@
FROM mcr.microsoft.com/dotnet/core/aspnet:3.0-buster-slim AS base
FROM mcr.microsoft.com/dotnet/core/aspnet:7.0-bullseye-slim AS base
WORKDIR /app
EXPOSE 80
FROM mcr.microsoft.com/dotnet/core/sdk:3.0-buster AS build
FROM mcr.microsoft.com/dotnet/core/sdk:7.0 AS build
WORKDIR /src
COPY . .
WORKDIR "/src/modules/docs/app/VoloDocs.Migrator"

2
modules/docs/app/VoloDocs.Migrator/appsettings.json

@ -1,3 +1,3 @@
{
"ConnectionString": "Server=localhost;Database=VoloDocs;Trusted_Connection=True"
"ConnectionString": "Server=localhost;Database=VoloDocs;Trusted_Connection=True;TrustServerCertificate=True"
}

4
modules/docs/app/VoloDocs.Web/Dockerfile

@ -1,8 +1,8 @@
FROM mcr.microsoft.com/dotnet/core/aspnet:3.0-buster-slim AS base
FROM mcr.microsoft.com/dotnet/core/aspnet:7.0-bullseye-slim AS base
WORKDIR /app
EXPOSE 80
FROM mcr.microsoft.com/dotnet/core/sdk:3.0-buster AS build
FROM mcr.microsoft.com/dotnet/core/sdk:7.0 AS build
WORKDIR /src
COPY . .
WORKDIR "/src/modules/docs/app/VoloDocs.Web"

2
modules/docs/app/VoloDocs.Web/appsettings.json

@ -1,5 +1,5 @@
{
"ConnectionString": "Server=localhost;Database=VoloDocs;Trusted_Connection=True",
"ConnectionString": "Server=localhost;Database=VoloDocs;Trusted_Connection=True;TrustServerCertificate=True",
"ElasticSearch": {
"Url": "http://localhost:9200"
},

47
modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AspNetIdentity/AbpUserClaimsFactory.cs

@ -7,6 +7,7 @@ using IdentityModel;
using Microsoft.AspNetCore.Identity;
using Microsoft.IdentityModel.JsonWebTokens;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Security.Claims;
using IdentityUser = Volo.Abp.Identity.IdentityUser;
namespace Volo.Abp.IdentityServer.AspNetIdentity;
@ -14,30 +15,37 @@ namespace Volo.Abp.IdentityServer.AspNetIdentity;
public class AbpUserClaimsFactory<TUser> : IUserClaimsPrincipalFactory<TUser>
where TUser : class
{
private readonly IObjectAccessor<IUserClaimsPrincipalFactory<TUser>> _inner;
private readonly UserManager<TUser> _userManager;
protected IObjectAccessor<IUserClaimsPrincipalFactory<TUser>> Inner { get; }
protected UserManager<TUser> UserManager { get; }
protected ICurrentPrincipalAccessor CurrentPrincipalAccessor { get; }
protected IAbpClaimsPrincipalFactory AbpClaimsPrincipalFactory { get; }
public AbpUserClaimsFactory(IObjectAccessor<IUserClaimsPrincipalFactory<TUser>> inner,
UserManager<TUser> userManager)
public AbpUserClaimsFactory(
IObjectAccessor<IUserClaimsPrincipalFactory<TUser>> inner,
UserManager<TUser> userManager,
ICurrentPrincipalAccessor currentPrincipalAccessor,
IAbpClaimsPrincipalFactory abpClaimsPrincipalFactory)
{
_inner = inner;
_userManager = userManager;
Inner = inner;
UserManager = userManager;
CurrentPrincipalAccessor = currentPrincipalAccessor;
AbpClaimsPrincipalFactory = abpClaimsPrincipalFactory;
}
public async Task<ClaimsPrincipal> CreateAsync(TUser user)
public virtual async Task<ClaimsPrincipal> CreateAsync(TUser user)
{
var principal = await _inner.Value.CreateAsync(user);
var principal = await Inner.Value.CreateAsync(user);
var identity = principal.Identities.First();
if (!identity.HasClaim(x => x.Type == JwtClaimTypes.Subject))
{
var sub = await _userManager.GetUserIdAsync(user);
var sub = await UserManager.GetUserIdAsync(user);
identity.AddIfNotContains(new Claim(JwtClaimTypes.Subject, sub));
}
var username = await _userManager.GetUserNameAsync(user);
var username = await UserManager.GetUserNameAsync(user);
var usernameClaim = identity.FindFirst(claim =>
claim.Type == _userManager.Options.ClaimsIdentity.UserNameClaimType && claim.Value == username);
claim.Type == UserManager.Options.ClaimsIdentity.UserNameClaimType && claim.Value == username);
if (usernameClaim != null)
{
identity.RemoveClaim(usernameClaim);
@ -53,25 +61,25 @@ public class AbpUserClaimsFactory<TUser> : IUserClaimsPrincipalFactory<TUser>
identity.AddIfNotContains(new Claim(JwtClaimTypes.Name, username));
}
if (_userManager.SupportsUserEmail)
if (UserManager.SupportsUserEmail)
{
var email = await _userManager.GetEmailAsync(user);
var email = await UserManager.GetEmailAsync(user);
if (!string.IsNullOrWhiteSpace(email))
{
identity.AddIfNotContains(new Claim(JwtClaimTypes.Email, email));
identity.AddIfNotContains(new Claim(JwtClaimTypes.EmailVerified,
await _userManager.IsEmailConfirmedAsync(user) ? "true" : "false", ClaimValueTypes.Boolean));
await UserManager.IsEmailConfirmedAsync(user) ? "true" : "false", ClaimValueTypes.Boolean));
}
}
if (_userManager.SupportsUserPhoneNumber)
if (UserManager.SupportsUserPhoneNumber)
{
var phoneNumber = await _userManager.GetPhoneNumberAsync(user);
var phoneNumber = await UserManager.GetPhoneNumberAsync(user);
if (!string.IsNullOrWhiteSpace(phoneNumber))
{
identity.AddIfNotContains(new Claim(JwtClaimTypes.PhoneNumber, phoneNumber));
identity.AddIfNotContains(new Claim(JwtClaimTypes.PhoneNumberVerified,
await _userManager.IsPhoneNumberConfirmedAsync(user) ? "true" : "false",
await UserManager.IsPhoneNumberConfirmedAsync(user) ? "true" : "false",
ClaimValueTypes.Boolean));
}
}
@ -89,6 +97,11 @@ public class AbpUserClaimsFactory<TUser> : IUserClaimsPrincipalFactory<TUser>
}
}
using (CurrentPrincipalAccessor.Change(identity))
{
await AbpClaimsPrincipalFactory.CreateAsync(principal);
}
return principal;
}
}

2
modules/openiddict/app/OpenIddict.Demo.Server/appsettings.json

@ -1,6 +1,6 @@
{
"ConnectionStrings": {
"Default": "Server=(LocalDb)\\MSSQLLocalDB;Database=OpenIddict-Demo-Server;Trusted_Connection=True"
"Default": "Server=(LocalDb)\\MSSQLLocalDB;Database=OpenIddict-Demo-Server;Trusted_Connection=True;TrustServerCertificate=True"
},
"Logging": {
"LogLevel": {

2
modules/setting-management/app/Volo.Abp.SettingManagement.DemoApp/appsettings.json

@ -1,5 +1,5 @@
{
"ConnectionStrings": {
"Default": "Server=(LocalDb)\\MSSQLLocalDB;Database=SettingManagementDemoApp;Trusted_Connection=True"
"Default": "Server=(LocalDb)\\MSSQLLocalDB;Database=SettingManagementDemoApp;Trusted_Connection=True;TrustServerCertificate=True"
}
}

5
npm/ng-packs/packages/account/src/lib/account.module.ts

@ -15,6 +15,7 @@ import { accountConfigOptionsFactory } from './utils/factory-utils';
import { AuthenticationFlowGuard } from './guards/authentication-flow.guard';
import { ForgotPasswordComponent } from './components/forgot-password/forgot-password.component';
import { ResetPasswordComponent } from './components/reset-password/reset-password.component';
import { RE_LOGIN_CONFIRMATION_TOKEN } from './tokens';
import { UiExtensionsModule } from '@abp/ng.theme.shared/extensions';
import { ACCOUNT_EDIT_FORM_PROP_CONTRIBUTORS } from './tokens/extensions.token';
import { AccountExtensionsGuard } from './guards/extensions.guard';
@ -55,6 +56,10 @@ export class AccountModule {
useFactory: accountConfigOptionsFactory,
deps: [ACCOUNT_CONFIG_OPTIONS],
},
{
provide: RE_LOGIN_CONFIRMATION_TOKEN,
useValue: options.isPersonalSettingsChangedConfirmationActive ?? true,
},
{
provide: ACCOUNT_EDIT_FORM_PROP_CONTRIBUTORS,
useValue: options.editFormPropContributors,

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

@ -1,10 +1,12 @@
import { ProfileDto, ProfileService } from '@abp/ng.account.core/proxy';
import { ToasterService } from '@abp/ng.theme.shared';
import { Component, Injector, OnInit, ViewEncapsulation } from '@angular/core';
import { Confirmation, ConfirmationService, ToasterService } from '@abp/ng.theme.shared';
import { Component, Inject, Injector, OnInit, ViewEncapsulation } from '@angular/core';
import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
import { finalize } from 'rxjs/operators';
import { finalize, filter } from 'rxjs/operators';
import { Account } from '../../models/account';
import { ManageProfileStateService } from '../../services/manage-profile.state.service';
import { AuthService } from '@abp/ng.core';
import { RE_LOGIN_CONFIRMATION_TOKEN } from '../../tokens';
import {
EXTENSIONS_IDENTIFIER,
FormPropData,
@ -34,12 +36,17 @@ export class PersonalSettingsComponent
form: UntypedFormGroup;
inProgress: boolean;
private profile: ProfileDto;
constructor(
private fb: UntypedFormBuilder,
private toasterService: ToasterService,
private profileService: ProfileService,
private manageProfileState: ManageProfileStateService,
private readonly authService: AuthService,
private confirmationService: ConfirmationService,
@Inject(RE_LOGIN_CONFIRMATION_TOKEN)
private isPersonalSettingsChangedConfirmationActive: boolean,
protected injector: Injector,
) {}
@ -58,6 +65,7 @@ export class PersonalSettingsComponent
submit() {
if (this.form.invalid) return;
const isLogOutConfirmMessageVisible = this.isLogoutConfirmMessageActive();
this.inProgress = true;
this.profileService
.update(this.form.value)
@ -65,6 +73,39 @@ export class PersonalSettingsComponent
.subscribe(profile => {
this.manageProfileState.setProfile(profile);
this.toasterService.success('AbpAccount::PersonalSettingsSaved', 'Success', { life: 5000 });
if (isLogOutConfirmMessageVisible) {
this.showLogoutConfirmMessage();
}
});
}
isDataSame(oldValue, newValue) {
return Object.entries(oldValue).some(([key, value]) => {
if (key in newValue) {
return value !== newValue[key];
}
return false;
});
}
logoutConfirmation = () => {
this.authService.logout().subscribe();
};
private isLogoutConfirmMessageActive() {
if (!this.isPersonalSettingsChangedConfirmationActive) {
return false;
}
return this.isDataSame(this.profile, this.form.value);
}
private showLogoutConfirmMessage() {
this.confirmationService
.info(
'AbpAccount::PersonalSettingsChangedConfirmationModalDescription',
'AbpAccount::PersonalSettingsChangedConfirmationModalTitle',
)
.pipe(filter(status => status === Confirmation.Status.confirm))
.subscribe(this.logoutConfirmation);
}
}

1
npm/ng-packs/packages/account/src/lib/models/config-options.ts

@ -4,6 +4,7 @@ import { UpdateProfileDto } from '@abp/ng.account.core/proxy';
export interface AccountConfigOptions {
redirectUrl?: string;
isPersonalSettingsChangedConfirmationActive?: boolean;
editFormPropContributors?: AccountEditFormPropContributors;
}
export type AccountEditFormPropContributors = Partial<{

1
npm/ng-packs/packages/account/src/lib/tokens/index.ts

@ -1,2 +1,3 @@
export * from './config-options.token';
export * from './re-login-confirmation.token';
export * from './extensions.token';

5
npm/ng-packs/packages/account/src/lib/tokens/re-login-confirmation.token.ts

@ -0,0 +1,5 @@
import { InjectionToken } from '@angular/core';
export const RE_LOGIN_CONFIRMATION_TOKEN = new InjectionToken<boolean>(
'RE_LOGIN_CONFIRMATION_TOKEN',
);

1
npm/ng-packs/packages/components/tree/src/lib/components/tree.component.html

@ -16,7 +16,6 @@
></nz-tree>
<ng-template #treeTemplate let-node>
<div
class="node-wrapper"
[class.selected]="isNodeSelected(node)"
[title]="node.title"
(click)="onSelectedNodeChange(node)"

19
npm/ng-packs/packages/components/tree/src/lib/components/tree.component.ts

@ -3,6 +3,7 @@ import {
ContentChild,
EventEmitter,
Input,
OnChanges,
Output,
TemplateRef,
ViewEncapsulation,
@ -24,7 +25,7 @@ export type DropEvent = NzFormatEmitEvent & { pos: number };
],
encapsulation: ViewEncapsulation.None,
})
export class TreeComponent {
export class TreeComponent implements OnChanges {
dropPosition: number;
dropdowns = {} as { [key: string]: NgbDropdown };
@ -44,19 +45,31 @@ export class TreeComponent {
@Input() nodes = [];
@Input() expandedKeys: string[] = [];
@Input() selectedNode: any;
@Input() changeCheckboxWithNode: boolean;
@Input() changedNodeValues = [];
@Input() isNodeSelected = node => this.selectedNode?.id === node.key;
@Input() beforeDrop = (event: NzFormatBeforeDropEvent) => {
this.dropPosition = event.pos;
return of(false);
};
ngOnChanges() {
this.checkedKeys = [...this.changedNodeValues];
}
onSelectedNodeChange(node) {
this.selectedNode = node.origin.entity;
this.selectedNodeChange.emit(node.origin.entity);
if (this.changeCheckboxWithNode) {
this.selectedNodeChange.emit(node);
this.checkedKeys = [...this.changedNodeValues];
this.checkedKeysChange.emit(this.changedNodeValues);
} else {
this.selectedNodeChange.emit(node.origin.entity);
}
}
onCheckboxChange(event) {
this.checkedKeys = [...event.keys];
this.checkedKeys = this.changedNodeValues = [...event.keys];
this.checkedKeysChange.emit(event.keys);
}

62
templates/app-nolayers/angular/src/app/home/home.component.spec.ts

@ -0,0 +1,62 @@
import { CoreTestingModule } from '@abp/ng.core/testing';
import { ThemeBasicTestingModule } from '@abp/ng.theme.basic/testing';
import { ThemeSharedTestingModule } from '@abp/ng.theme.shared/testing';
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { NgxValidateCoreModule } from '@ngx-validate/core';
import { HomeComponent } from './home.component';
import { OAuthService } from 'angular-oauth2-oidc';
import { AuthService } from '@abp/ng.core';
describe('HomeComponent', () => {
let fixture: ComponentFixture<HomeComponent>;
const mockOAuthService = jasmine.createSpyObj('OAuthService', ['hasValidAccessToken']);
const mockAuthService = jasmine.createSpyObj('AuthService', ['navigateToLogin']);
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [HomeComponent],
imports: [
CoreTestingModule.withConfig(),
ThemeSharedTestingModule.withConfig(),
ThemeBasicTestingModule.withConfig(),
NgxValidateCoreModule,
],
providers: [
/* mock providers here */
{
provide: OAuthService,
useValue: mockOAuthService,
},
{
provide: AuthService,
useValue: mockAuthService,
},
],
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(HomeComponent);
fixture.detectChanges();
});
it('should be initiated', () => {
expect(fixture.componentInstance).toBeTruthy();
});
describe('when login state is true', () => {
beforeAll(() => {
mockOAuthService.hasValidAccessToken.and.returnValue(true);
});
it('hasLoggedIn should be true', () => {
expect(fixture.componentInstance.hasLoggedIn).toBeTrue();
expect(mockOAuthService.hasValidAccessToken).toHaveBeenCalled();
});
it('button should not be exists', () => {
const element = fixture.nativeElement;
const cardTitle = element.querySelector('.card-title');
expect(cardTitle).toBeTruthy();
});
});
});

3
templates/app-nolayers/angular/src/test.ts

@ -1,11 +1,10 @@
// This file is required by karma.conf.js and loads recursively all the .spec and framework files
import 'zone.js/testing';
import { getTestBed } from '@angular/core/testing';
import {
BrowserDynamicTestingModule,
platformBrowserDynamicTesting,
} from '@angular/platform-browser-dynamic/testing';
import 'zone.js/testing';
declare const require: {
context(

8
templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server.Mongo/MyCompanyName.MyProjectName.Blazor.Server.Mongo.csproj

@ -7,8 +7,8 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Blazorise.Bootstrap5" Version="1.0.6" />
<PackageReference Include="Blazorise.Icons.FontAwesome" Version="1.0.6" />
<PackageReference Include="Blazorise.Bootstrap5" Version="1.1.2" />
<PackageReference Include="Blazorise.Icons.FontAwesome" Version="1.1.2" />
<PackageReference Include="Serilog.AspNetCore" Version="5.0.0" />
<PackageReference Include="Serilog.Sinks.Async" Version="1.5.0" />
</ItemGroup>
@ -96,4 +96,8 @@
<None Remove="Logs\**" />
</ItemGroup>
<ItemGroup>
<Content Remove="$(UserProfile)\.nuget\packages\*\*\contentFiles\any\*\*.abppkg*.json" />
</ItemGroup>
</Project>

8
templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/MyCompanyName.MyProjectName.Blazor.Server.csproj

@ -7,8 +7,8 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Blazorise.Bootstrap5" Version="1.0.6" />
<PackageReference Include="Blazorise.Icons.FontAwesome" Version="1.0.6" />
<PackageReference Include="Blazorise.Bootstrap5" Version="1.1.2" />
<PackageReference Include="Blazorise.Icons.FontAwesome" Version="1.1.2" />
<PackageReference Include="Serilog.AspNetCore" Version="5.0.0" />
<PackageReference Include="Serilog.Sinks.Async" Version="1.5.0" />
</ItemGroup>
@ -104,4 +104,8 @@
<None Remove="Logs\**" />
</ItemGroup>
<ItemGroup>
<Content Remove="$(UserProfile)\.nuget\packages\*\*\contentFiles\any\*\*.abppkg*.json" />
</ItemGroup>
</Project>

2
templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/appsettings.json

@ -4,7 +4,7 @@
"RedirectAllowedUrls": "https://localhost:44300"
},
"ConnectionStrings": {
"Default": "Server=(LocalDb)\\MSSQLLocalDB;Database=MyProjectName;Trusted_Connection=True"
"Default": "Server=(LocalDb)\\MSSQLLocalDB;Database=MyProjectName;Trusted_Connection=True;TrustServerCertificate=True"
},
"StringEncryption": {
"DefaultPassPhrase": "gsKnGZ041HLL4IM8"

4
templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host.Mongo/MyCompanyName.MyProjectName.Host.Mongo.csproj

@ -88,4 +88,8 @@
<None Remove="Logs\**" />
</ItemGroup>
<ItemGroup>
<Content Remove="$(UserProfile)\.nuget\packages\*\*\contentFiles\any\*\*.abppkg*.json" />
</ItemGroup>
</Project>

4
templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/MyCompanyName.MyProjectName.Host.csproj

@ -96,4 +96,8 @@
<None Remove="Logs\**" />
</ItemGroup>
<ItemGroup>
<Content Remove="$(UserProfile)\.nuget\packages\*\*\contentFiles\any\*\*.abppkg*.json" />
</ItemGroup>
</Project>

2
templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/appsettings.json

@ -6,7 +6,7 @@
"RedirectAllowedUrls": "http://localhost:4200"
},
"ConnectionStrings": {
"Default": "Server=(LocalDb)\\MSSQLLocalDB;Database=MyProjectName;Trusted_Connection=True"
"Default": "Server=(LocalDb)\\MSSQLLocalDB;Database=MyProjectName;Trusted_Connection=True;TrustServerCertificate=True"
},
"AuthServer": {
"Authority": "https://localhost:44300",

4
templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc.Mongo/MyCompanyName.MyProjectName.Mvc.Mongo.csproj

@ -100,4 +100,8 @@
</None>
</ItemGroup>
<ItemGroup>
<Content Remove="$(UserProfile)\.nuget\packages\*\*\contentFiles\any\*\*.abppkg*.json" />
</ItemGroup>
</Project>

4
templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/MyCompanyName.MyProjectName.Mvc.csproj

@ -108,4 +108,8 @@
</None>
</ItemGroup>
<ItemGroup>
<Content Remove="$(UserProfile)\.nuget\packages\*\*\contentFiles\any\*\*.abppkg*.json" />
</ItemGroup>
</Project>

2
templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/appsettings.json

@ -3,7 +3,7 @@
"SelfUrl": "https://localhost:44300"
},
"ConnectionStrings": {
"Default": "Server=(LocalDb)\\MSSQLLocalDB;Database=MyProjectName;Trusted_Connection=True"
"Default": "Server=(LocalDb)\\MSSQLLocalDB;Database=MyProjectName;Trusted_Connection=True;TrustServerCertificate=True"
},
"StringEncryption": {
"DefaultPassPhrase": "gsKnGZ041HLL4IM8"

100
templates/app/angular/src/app/home/home.component.spec.ts

@ -0,0 +1,100 @@
import { CoreTestingModule } from "@abp/ng.core/testing";
import { ThemeBasicTestingModule } from "@abp/ng.theme.basic/testing";
import { ThemeSharedTestingModule } from "@abp/ng.theme.shared/testing";
import { ComponentFixture, TestBed, waitForAsync } from "@angular/core/testing";
import { NgxValidateCoreModule } from "@ngx-validate/core";
import { HomeComponent } from "./home.component";
import { OAuthService } from 'angular-oauth2-oidc';
import { AuthService } from '@abp/ng.core';
describe("HomeComponent", () => {
let fixture: ComponentFixture<HomeComponent>;
const mockOAuthService = jasmine.createSpyObj('OAuthService', ['hasValidAccessToken'])
const mockAuthService = jasmine.createSpyObj('AuthService', ['navigateToLogin'])
beforeEach(
waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [HomeComponent],
imports: [
CoreTestingModule.withConfig(),
ThemeSharedTestingModule.withConfig(),
ThemeBasicTestingModule.withConfig(),
NgxValidateCoreModule,
],
providers: [
/* mock providers here */
{
provide: OAuthService,
useValue: mockOAuthService
},
{
provide: AuthService,
useValue: mockAuthService
}
],
}).compileComponents();
})
);
beforeEach(() => {
fixture = TestBed.createComponent(HomeComponent);
fixture.detectChanges();
});
it("should be initiated", () => {
expect(fixture.componentInstance).toBeTruthy();
});
describe('when login state is true', () => {
beforeAll(() => {
mockOAuthService.hasValidAccessToken.and.returnValue(true)
});
it("hasLoggedIn should be true", () => {
expect(fixture.componentInstance.hasLoggedIn).toBeTrue();
expect(mockOAuthService.hasValidAccessToken).toHaveBeenCalled()
})
it("button should not be exists", () => {
const element = fixture.nativeElement
const button = element.querySelector('[role="button"]')
expect(button).toBeNull()
})
})
describe('when login state is false', () => {
beforeAll(() => {
mockOAuthService.hasValidAccessToken.and.returnValue(false)
});
it("hasLoggedIn should be false", () => {
expect(fixture.componentInstance.hasLoggedIn).toBeFalse();
expect(mockOAuthService.hasValidAccessToken).toHaveBeenCalled()
})
it("button should be exists", () => {
const element = fixture.nativeElement
const button = element.querySelector('[role="button"]')
expect(button).toBeDefined()
})
describe('when button clicked', () => {
beforeEach(() => {
const element = fixture.nativeElement
const button = element.querySelector('[role="button"]')
button.click()
});
it("navigateToLogin have been called", () => {
expect(mockAuthService.navigateToLogin).toHaveBeenCalled()
})
})
})
});

4
templates/app/angular/src/test.ts

@ -1,11 +1,11 @@
// This file is required by karma.conf.js and loads recursively all the .spec and framework files
import 'zone.js/testing';
import { getTestBed } from '@angular/core/testing';
import {
BrowserDynamicTestingModule,
platformBrowserDynamicTesting,
} from '@angular/platform-browser-dynamic/testing';
import 'zone.js/testing';
declare const require: {
context(

4
templates/app/aspnet-core/common.props

@ -12,4 +12,8 @@
</PropertyGroup>
</Target>
<ItemGroup>
<Content Remove="$(UserProfile)\.nuget\packages\*\*\contentFiles\any\*\*.abppkg*.json" />
</ItemGroup>
</Project>

2
templates/app/aspnet-core/src/MyCompanyName.MyProjectName.AuthServer/MyCompanyName.MyProjectName.AuthServer.csproj

@ -33,7 +33,7 @@
<ItemGroup>
<PackageReference Include="Serilog.AspNetCore" Version="5.0.0" />
<PackageReference Include="Serilog.Sinks.Async" Version="1.5.0" />
<PackageReference Include="Microsoft.AspNetCore.DataProtection.StackExchangeRedis" Version="6.0.5" />
<PackageReference Include="Microsoft.AspNetCore.DataProtection.StackExchangeRedis" Version="7.0.0-rc.2.*" />
<PackageReference Include="DistributedLock.Redis" Version="1.0.2" />
</ItemGroup>

2
templates/app/aspnet-core/src/MyCompanyName.MyProjectName.AuthServer/appsettings.json

@ -6,7 +6,7 @@
"RedirectAllowedUrls": "http://localhost:4200,https://localhost:44302,https://localhost:44307,https://localhost:44309"
},
"ConnectionStrings": {
"Default": "Server=(LocalDb)\\MSSQLLocalDB;Database=MyProjectName;Trusted_Connection=True"
"Default": "Server=(LocalDb)\\MSSQLLocalDB;Database=MyProjectName;Trusted_Connection=True;TrustServerCertificate=True"
},
"Redis": {
"Configuration": "127.0.0.1"

6
templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server.Tiered/MyCompanyName.MyProjectName.Blazor.Server.Tiered.csproj

@ -13,11 +13,11 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Blazorise.Bootstrap5" Version="1.0.6" />
<PackageReference Include="Blazorise.Icons.FontAwesome" Version="1.0.6" />
<PackageReference Include="Blazorise.Bootstrap5" Version="1.1.2" />
<PackageReference Include="Blazorise.Icons.FontAwesome" Version="1.1.2" />
<PackageReference Include="Serilog.AspNetCore" Version="5.0.0" />
<PackageReference Include="Serilog.Sinks.Async" Version="1.5.0" />
<PackageReference Include="Microsoft.AspNetCore.DataProtection.StackExchangeRedis" Version="6.0.5" />
<PackageReference Include="Microsoft.AspNetCore.DataProtection.StackExchangeRedis" Version="7.0.0-rc.2.*" />
<PackageReference Include="DistributedLock.Redis" Version="1.0.2" />
</ItemGroup>

4
templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server/MyCompanyName.MyProjectName.Blazor.Server.csproj

@ -13,8 +13,8 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Blazorise.Bootstrap5" Version="1.0.6" />
<PackageReference Include="Blazorise.Icons.FontAwesome" Version="1.0.6" />
<PackageReference Include="Blazorise.Bootstrap5" Version="1.1.2" />
<PackageReference Include="Blazorise.Icons.FontAwesome" Version="1.1.2" />
<PackageReference Include="Serilog.AspNetCore" Version="5.0.0" />
<PackageReference Include="Serilog.Sinks.Async" Version="1.5.0" />
</ItemGroup>

2
templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server/appsettings.json

@ -4,7 +4,7 @@
"RedirectAllowedUrls": "https://localhost:44308"
},
"ConnectionStrings": {
"Default": "Server=(LocalDb)\\MSSQLLocalDB;Database=MyProjectName;Trusted_Connection=True"
"Default": "Server=(LocalDb)\\MSSQLLocalDB;Database=MyProjectName;Trusted_Connection=True;TrustServerCertificate=True"
},
"AuthServer": {
"Authority": "https://localhost:44308",

4
templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/MyCompanyName.MyProjectName.Blazor.csproj

@ -11,8 +11,8 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Blazorise.Bootstrap5" Version="1.0.6" />
<PackageReference Include="Blazorise.Icons.FontAwesome" Version="1.0.6" />
<PackageReference Include="Blazorise.Bootstrap5" Version="1.1.2" />
<PackageReference Include="Blazorise.Icons.FontAwesome" Version="1.1.2" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="7.0.0-rc.2.*" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="7.0.0-rc.2.*" />
</ItemGroup>

139
templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/wwwroot/global.css

File diff suppressed because one or more lines are too long

4
templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/wwwroot/global.js

File diff suppressed because one or more lines are too long

4
templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor/wwwroot/index.html

@ -8,7 +8,7 @@
<base href="/" />
<!--ABP:Styles-->
<link href="global.css?_v=637992656644309659" rel="stylesheet"/>
<link href="global.css?_v=638019471644954402" rel="stylesheet"/>
<link href="main.css" rel="stylesheet"/>
<!--/ABP:Styles-->
<link href="MyCompanyName.MyProjectName.Blazor.styles.css" rel="stylesheet"/>
@ -29,7 +29,7 @@
</div>
<!--ABP:Scripts-->
<script src="global.js?_v=637992656647465320"></script>
<script src="global.js?_v=638019471646687054"></script>
<!--/ABP:Scripts-->
<!-- <TEMPLATE-REMOVE IF-NOT='PWA'> -->

2
templates/app/aspnet-core/src/MyCompanyName.MyProjectName.DbMigrator/appsettings.json

@ -1,6 +1,6 @@
{
"ConnectionStrings": {
"Default": "Server=(LocalDb)\\MSSQLLocalDB;Database=MyProjectName;Trusted_Connection=True"
"Default": "Server=(LocalDb)\\MSSQLLocalDB;Database=MyProjectName;Trusted_Connection=True;TrustServerCertificate=True"
},
"OpenIddict": {
"Applications": {

2
templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.Host/appsettings.json

@ -3,7 +3,7 @@
"CorsOrigins": "https://*.MyProjectName.com,http://localhost:4200,https://localhost:44307"
},
"ConnectionStrings": {
"Default": "Server=(LocalDb)\\MSSQLLocalDB;Database=MyProjectName;Trusted_Connection=True"
"Default": "Server=(LocalDb)\\MSSQLLocalDB;Database=MyProjectName;Trusted_Connection=True;TrustServerCertificate=True"
},
"Redis": {
"Configuration": "127.0.0.1"

2
templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.HostWithIds/appsettings.json

@ -6,7 +6,7 @@
"RedirectAllowedUrls": "http://localhost:4200,https://localhost:44307"
},
"ConnectionStrings": {
"Default": "Server=(LocalDb)\\MSSQLLocalDB;Database=MyProjectName;Trusted_Connection=True"
"Default": "Server=(LocalDb)\\MSSQLLocalDB;Database=MyProjectName;Trusted_Connection=True;TrustServerCertificate=True"
},
"AuthServer": {
"Authority": "https://localhost:44305",

2
templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Web/appsettings.json

@ -3,7 +3,7 @@
"SelfUrl": "https://localhost:44303"
},
"ConnectionStrings": {
"Default": "Server=(LocalDb)\\MSSQLLocalDB;Database=MyProjectName;Trusted_Connection=True"
"Default": "Server=(LocalDb)\\MSSQLLocalDB;Database=MyProjectName;Trusted_Connection=True;TrustServerCertificate=True"
},
"StringEncryption": {
"DefaultPassPhrase": "gsKnGZ041HLL4IM8"

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

Loading…
Cancel
Save