diff --git a/docs/en/Migration-Guides/Abp-7_0.md b/docs/en/Migration-Guides/Abp-7_0.md index da8d9c863a..05dc276e3d 100644 --- a/docs/en/Migration-Guides/Abp-7_0.md +++ b/docs/en/Migration-Guides/Abp-7_0.md @@ -115,4 +115,74 @@ See https://github.com/abpframework/abp/pull/13845 for more info. The `Devart.Data.Oracle.EFCore` package do not yet support EF Core 7.0, If you use `AbpEntityFrameworkCoreOracleDevartModule(Volo.Abp.EntityFrameworkCore.Oracle.Devart)` may not work as expected, We will release new packages as soon as they are updated. See https://github.com/abpframework/abp/issues/14412 for more info. +# Changes on Angular Apps +## Added a new package `@abp/ng.oauth` +OAuth Functionality moved to a seperate package named `@abp/ng.oauth`, so ABP users should add the `@abp/ng.oauth` packages on app.module.ts. +Add the new npm package to your app. +``` +yarn add @abp/ng.oauth +// or npm i ---save @abp/ng.oauth +``` + +```typescript +// app.module.ts +import { AbpOAuthModule } from "@abp/ng.oauth"; +// ... +@NgModule({ + // ... + imports: [ + AbpOAuthModule.forRoot(), // <-- Add This + // ... + ], + // ... +}) +export class AppModule {} + +``` +## Lepton X Google-Font +If you are using LeptonX that has google fonts, the fonts were built-in the Lepton file. It's been moved to a seperate file. So the ABP user should add font-bundle in angular.json. ( under the 'yourProjectName' > 'architect' > 'build' > 'options' >'styles' ) + +// for LeptonX Lite +```json + { + input: 'node_modules/@volo/ngx-lepton-x.lite/assets/css/font-bundle.rtl.css', + inject: false, + bundleName: 'font-bundle.rtl', + }, + { + input: 'node_modules/@volo/ngx-lepton-x.lite/assets/css/font-bundle.css', + inject: false, + bundleName: 'font-bundle', + }, +``` + +// for LeptonX +```json + { + input: 'node_modules/@volosoft/ngx-lepton-x/assets/css/font-bundle.css', + inject: false, + bundleName: 'font-bundle', + }, + { + input: 'node_modules/@volosoft/ngx-lepton-x/assets/css/font-bundle.rtl.css', + inject: false, + bundleName: 'font-bundle.rtl', + }, +``` + +## Updated Side Menu Layout + +In side menu layout, eThemeLeptonXComponents.Navbar has been changed to eThemeLeptonXComponents.Toolbar, and +eThemeLeptonXComponents.Sidebar to eThemeLeptonXComponents.Navbar. + +And also added new replaceable component like Logo Component, Language Component etc. + +If you are using replaceable component system you can check [documentation](https://docs.abp.io/en/commercial/latest/themes/lepton-x/angular#customization). + + +## ng-zorro-antd-tree.css + +ng-zorro-antd-tree.css file should be in angular.json if the user uses AbpTree component or Abp-commercial. The ABP User should add this style definition on angular.json. ( under the 'yourProjectName' > 'architect' > 'build' > 'options' >'styles' ) + +{ "input": "node_modules/ng-zorro-antd/tree/style/index.min.css", "inject": false, "bundleName": "ng-zorro-antd-tree" }, diff --git a/framework/src/Volo.Abp.Data/Volo/Abp/Data/AbpConnectionStringCheckResult.cs b/framework/src/Volo.Abp.Data/Volo/Abp/Data/AbpConnectionStringCheckResult.cs new file mode 100644 index 0000000000..64d955a760 --- /dev/null +++ b/framework/src/Volo.Abp.Data/Volo/Abp/Data/AbpConnectionStringCheckResult.cs @@ -0,0 +1,8 @@ +namespace Volo.Abp.Data; + +public class AbpConnectionStringCheckResult +{ + public bool Connected { get; set; } + + public bool DatabaseExists { get; set; } +} diff --git a/framework/src/Volo.Abp.Data/Volo/Abp/Data/DefaultConnectionStringChecker.cs b/framework/src/Volo.Abp.Data/Volo/Abp/Data/DefaultConnectionStringChecker.cs new file mode 100644 index 0000000000..9ce04a71b9 --- /dev/null +++ b/framework/src/Volo.Abp.Data/Volo/Abp/Data/DefaultConnectionStringChecker.cs @@ -0,0 +1,16 @@ +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.Data; + +public class DefaultConnectionStringChecker : IConnectionStringChecker, ITransientDependency +{ + public Task CheckAsync(string connectionString) + { + return Task.FromResult(new AbpConnectionStringCheckResult + { + Connected = false, + DatabaseExists = false + }); + } +} diff --git a/framework/src/Volo.Abp.Data/Volo/Abp/Data/IConnectionStringChecker.cs b/framework/src/Volo.Abp.Data/Volo/Abp/Data/IConnectionStringChecker.cs new file mode 100644 index 0000000000..159a52acc3 --- /dev/null +++ b/framework/src/Volo.Abp.Data/Volo/Abp/Data/IConnectionStringChecker.cs @@ -0,0 +1,8 @@ +using System.Threading.Tasks; + +namespace Volo.Abp.Data; + +public interface IConnectionStringChecker +{ + Task CheckAsync(string connectionString); +} diff --git a/framework/src/Volo.Abp.EntityFrameworkCore.MySQL/Volo/Abp/EntityFrameworkCore/ConnectionStrings/MySqlConnectionStringChecker.cs b/framework/src/Volo.Abp.EntityFrameworkCore.MySQL/Volo/Abp/EntityFrameworkCore/ConnectionStrings/MySqlConnectionStringChecker.cs new file mode 100644 index 0000000000..a77821b9df --- /dev/null +++ b/framework/src/Volo.Abp.EntityFrameworkCore.MySQL/Volo/Abp/EntityFrameworkCore/ConnectionStrings/MySqlConnectionStringChecker.cs @@ -0,0 +1,40 @@ +using System; +using System.Threading.Tasks; +using MySqlConnector; +using Volo.Abp.Data; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.EntityFrameworkCore.ConnectionStrings; + +[Dependency(ReplaceServices = true)] +public class MySqlConnectionStringChecker : IConnectionStringChecker, ITransientDependency +{ + public virtual async Task CheckAsync(string connectionString) + { + var result = new AbpConnectionStringCheckResult(); + var connString = new MySqlConnectionStringBuilder(connectionString) + { + ConnectionLifeTime = 1 + }; + + var oldDatabaseName = connString.Database; + connString.Database = "mysql"; + + try + { + await using var conn = new MySqlConnection(connString.ConnectionString); + await conn.OpenAsync(); + result.Connected = true; + await conn.ChangeDatabaseAsync(oldDatabaseName); + result.DatabaseExists = true; + + await conn.CloseAsync(); + + return result; + } + catch (Exception e) + { + return result; + } + } +} diff --git a/framework/src/Volo.Abp.EntityFrameworkCore.Oracle.Devart/Volo/Abp/EntityFrameworkCore/ConnectionStrings/OracleDevartConnectionStringChecker.cs b/framework/src/Volo.Abp.EntityFrameworkCore.Oracle.Devart/Volo/Abp/EntityFrameworkCore/ConnectionStrings/OracleDevartConnectionStringChecker.cs new file mode 100644 index 0000000000..1bbc300ec8 --- /dev/null +++ b/framework/src/Volo.Abp.EntityFrameworkCore.Oracle.Devart/Volo/Abp/EntityFrameworkCore/ConnectionStrings/OracleDevartConnectionStringChecker.cs @@ -0,0 +1,36 @@ +using System; +using System.Threading.Tasks; +using Devart.Data.Oracle; +using Volo.Abp.Data; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.EntityFrameworkCore.ConnectionStrings; + +[Dependency(ReplaceServices = true)] +public class OracleDevartConnectionStringChecker : IConnectionStringChecker, ITransientDependency +{ + public virtual async Task CheckAsync(string connectionString) + { + var result = new AbpConnectionStringCheckResult(); + var connString = new OracleConnectionStringBuilder(connectionString) + { + ConnectionTimeout = 1 + }; + + try + { + await using var conn = new OracleConnection(connString.ConnectionString); + await conn.OpenAsync(); + result.Connected = true; + result.DatabaseExists = true; + + await conn.CloseAsync(); + + return result; + } + catch (Exception e) + { + return result; + } + } +} diff --git a/framework/src/Volo.Abp.EntityFrameworkCore.Oracle/Volo/Abp/EntityFrameworkCore/ConnectionStrings/OracleConnectionStringChecker.cs b/framework/src/Volo.Abp.EntityFrameworkCore.Oracle/Volo/Abp/EntityFrameworkCore/ConnectionStrings/OracleConnectionStringChecker.cs new file mode 100644 index 0000000000..1176a9ce64 --- /dev/null +++ b/framework/src/Volo.Abp.EntityFrameworkCore.Oracle/Volo/Abp/EntityFrameworkCore/ConnectionStrings/OracleConnectionStringChecker.cs @@ -0,0 +1,36 @@ +using System; +using System.Threading.Tasks; +using Oracle.ManagedDataAccess.Client; +using Volo.Abp.Data; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.EntityFrameworkCore.ConnectionStrings; + +[Dependency(ReplaceServices = true)] +public class OracleConnectionStringChecker : IConnectionStringChecker, ITransientDependency +{ + public virtual async Task CheckAsync(string connectionString) + { + var result = new AbpConnectionStringCheckResult(); + var connString = new OracleConnectionStringBuilder(connectionString) + { + ConnectionTimeout = 1 + }; + + try + { + await using var conn = new OracleConnection(connString.ConnectionString); + await conn.OpenAsync(); + result.Connected = true; + result.DatabaseExists = true; + + await conn.CloseAsync(); + + return result; + } + catch (Exception e) + { + return result; + } + } +} diff --git a/framework/src/Volo.Abp.EntityFrameworkCore.PostgreSql/Volo/Abp/EntityFrameworkCore/ConnectionStrings/NpgsqlConnectionStringChecker.cs b/framework/src/Volo.Abp.EntityFrameworkCore.PostgreSql/Volo/Abp/EntityFrameworkCore/ConnectionStrings/NpgsqlConnectionStringChecker.cs new file mode 100644 index 0000000000..f3ab83eb55 --- /dev/null +++ b/framework/src/Volo.Abp.EntityFrameworkCore.PostgreSql/Volo/Abp/EntityFrameworkCore/ConnectionStrings/NpgsqlConnectionStringChecker.cs @@ -0,0 +1,40 @@ +using System; +using System.Threading.Tasks; +using Npgsql; +using Volo.Abp.Data; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.EntityFrameworkCore.ConnectionStrings; + +[Dependency(ReplaceServices = true)] +public class NpgsqlConnectionStringChecker : IConnectionStringChecker, ITransientDependency +{ + public virtual async Task CheckAsync(string connectionString) + { + var result = new AbpConnectionStringCheckResult(); + var connString = new NpgsqlConnectionStringBuilder(connectionString) + { + Timeout = 1 + }; + + var oldDatabaseName = connString.Database; + connString.Database = "postgres"; + + try + { + await using var conn = new NpgsqlConnection(connString.ConnectionString); + await conn.OpenAsync(); + result.Connected = true; + await conn.ChangeDatabaseAsync(oldDatabaseName); + result.DatabaseExists = true; + + await conn.CloseAsync(); + + return result; + } + catch (Exception e) + { + return result; + } + } +} diff --git a/framework/src/Volo.Abp.EntityFrameworkCore.SqlServer/Volo/Abp/EntityFrameworkCore/ConnectionStrings/SqlServerConnectionStringChecker.cs b/framework/src/Volo.Abp.EntityFrameworkCore.SqlServer/Volo/Abp/EntityFrameworkCore/ConnectionStrings/SqlServerConnectionStringChecker.cs new file mode 100644 index 0000000000..668aec3d96 --- /dev/null +++ b/framework/src/Volo.Abp.EntityFrameworkCore.SqlServer/Volo/Abp/EntityFrameworkCore/ConnectionStrings/SqlServerConnectionStringChecker.cs @@ -0,0 +1,40 @@ +using System; +using System.Threading.Tasks; +using Microsoft.Data.SqlClient; +using Volo.Abp.Data; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.EntityFrameworkCore.ConnectionStrings; + +[Dependency(ReplaceServices = true)] +public class SqlServerConnectionStringChecker : IConnectionStringChecker, ITransientDependency +{ + public virtual async Task CheckAsync(string connectionString) + { + var result = new AbpConnectionStringCheckResult(); + var connString = new SqlConnectionStringBuilder(connectionString) + { + ConnectTimeout = 1 + }; + + var oldDatabaseName = connString.InitialCatalog; + connString.InitialCatalog = "master"; + + try + { + await using var conn = new SqlConnection(connString.ConnectionString); + await conn.OpenAsync(); + result.Connected = true; + await conn.ChangeDatabaseAsync(oldDatabaseName); + result.DatabaseExists = true; + + await conn.CloseAsync(); + + return result; + } + catch (Exception e) + { + return result; + } + } +} diff --git a/framework/src/Volo.Abp.EntityFrameworkCore.Sqlite/Volo/Abp/EntityFrameworkCore/ConnectionStrings/SqliteConnectionStringChecker.cs b/framework/src/Volo.Abp.EntityFrameworkCore.Sqlite/Volo/Abp/EntityFrameworkCore/ConnectionStrings/SqliteConnectionStringChecker.cs new file mode 100644 index 0000000000..48b428ce8f --- /dev/null +++ b/framework/src/Volo.Abp.EntityFrameworkCore.Sqlite/Volo/Abp/EntityFrameworkCore/ConnectionStrings/SqliteConnectionStringChecker.cs @@ -0,0 +1,32 @@ +using System; +using System.Threading.Tasks; +using Microsoft.Data.Sqlite; +using Volo.Abp.Data; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.EntityFrameworkCore.ConnectionStrings; + +[Dependency(ReplaceServices = true)] +public class SqliteConnectionStringChecker : IConnectionStringChecker, ITransientDependency +{ + public virtual async Task CheckAsync(string connectionString) + { + var result = new AbpConnectionStringCheckResult(); + + try + { + await using var conn = new SqliteConnection(connectionString); + await conn.OpenAsync(); + result.Connected = true; + result.DatabaseExists = true; + + await conn.CloseAsync(); + + return result; + } + catch (Exception e) + { + return result; + } + } +} diff --git a/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/ConnectionStrings/MongoDBConnectionStringChecker.cs b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/ConnectionStrings/MongoDBConnectionStringChecker.cs new file mode 100644 index 0000000000..f77335f285 --- /dev/null +++ b/framework/src/Volo.Abp.MongoDB/Volo/Abp/MongoDB/ConnectionStrings/MongoDBConnectionStringChecker.cs @@ -0,0 +1,30 @@ +using System; +using System.Threading.Tasks; +using MongoDB.Driver; +using Volo.Abp.Data; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.MongoDB.ConnectionStrings; + +[Dependency(ReplaceServices = true)] +public class MongoDBConnectionStringChecker : IConnectionStringChecker, ITransientDependency +{ + public virtual Task CheckAsync(string connectionString) + { + try + { + var mongoUrl = MongoUrl.Create(connectionString); + var client = new MongoClient(mongoUrl); + client.GetDatabase(mongoUrl.DatabaseName); + return Task.FromResult(new AbpConnectionStringCheckResult() + { + Connected = true, + DatabaseExists = true + }); + } + catch (Exception e) + { + return Task.FromResult(new AbpConnectionStringCheckResult()); + } + } +} diff --git a/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/AlwaysDisableTransactionsUnitOfWorkManager.cs b/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/AlwaysDisableTransactionsUnitOfWorkManager.cs new file mode 100644 index 0000000000..a02f63c3e1 --- /dev/null +++ b/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/AlwaysDisableTransactionsUnitOfWorkManager.cs @@ -0,0 +1,39 @@ +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.Uow; + +[DisableConventionalRegistration] +public class AlwaysDisableTransactionsUnitOfWorkManager : IUnitOfWorkManager +{ + private readonly UnitOfWorkManager _unitOfWorkManager; + + public AlwaysDisableTransactionsUnitOfWorkManager(UnitOfWorkManager unitOfWorkManager) + { + _unitOfWorkManager = unitOfWorkManager; + } + + public IUnitOfWork Current => _unitOfWorkManager.Current; + + public IUnitOfWork Begin(AbpUnitOfWorkOptions options, bool requiresNew = false) + { + options.IsTransactional = false; + return _unitOfWorkManager.Begin(options, requiresNew); + } + + public IUnitOfWork Reserve(string reservationName, bool requiresNew = false) + { + return _unitOfWorkManager.Reserve(reservationName, requiresNew); + } + + public void BeginReserved(string reservationName, AbpUnitOfWorkOptions options) + { + options.IsTransactional = false; + _unitOfWorkManager.BeginReserved(reservationName, options); + } + + public bool TryBeginReserved(string reservationName, AbpUnitOfWorkOptions options) + { + options.IsTransactional = false; + return _unitOfWorkManager.TryBeginReserved(reservationName, options); + } +} diff --git a/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/UnitOfWorkCollectionExtensions.cs b/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/UnitOfWorkCollectionExtensions.cs new file mode 100644 index 0000000000..fb47ccc83c --- /dev/null +++ b/framework/src/Volo.Abp.Uow/Volo/Abp/Uow/UnitOfWorkCollectionExtensions.cs @@ -0,0 +1,12 @@ +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace Volo.Abp.Uow; + +public static class UnitOfWorkCollectionExtensions +{ + public static IServiceCollection AddAlwaysDisableUnitOfWorkTransaction(this IServiceCollection services) + { + return services.Replace(ServiceDescriptor.Singleton()); + } +} diff --git a/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/ConnectionStrings/AbpConnectionStringChecker_Tests.cs b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/ConnectionStrings/AbpConnectionStringChecker_Tests.cs new file mode 100644 index 0000000000..8889fb8bcd --- /dev/null +++ b/framework/test/Volo.Abp.EntityFrameworkCore.Tests/Volo/Abp/EntityFrameworkCore/ConnectionStrings/AbpConnectionStringChecker_Tests.cs @@ -0,0 +1,18 @@ +using System.Threading.Tasks; +using Shouldly; +using Volo.Abp.Data; +using Xunit; + +namespace Volo.Abp.EntityFrameworkCore.ConnectionStrings; + +public class AbpConnectionStringChecker_Tests : EntityFrameworkCoreTestBase +{ + [Fact] + public async Task IsValidAsync() + { + var connectionStringChecker = GetRequiredService(); + var result = await connectionStringChecker.CheckAsync(@"Data Source=:memory:"); + result.Connected.ShouldBeTrue(); + result.DatabaseExists.ShouldBeTrue(); + } +} diff --git a/framework/test/Volo.Abp.Uow.Tests/Volo/Abp/Uow/AlwaysDisableUnitOfWorkTransaction_Tests.cs b/framework/test/Volo.Abp.Uow.Tests/Volo/Abp/Uow/AlwaysDisableUnitOfWorkTransaction_Tests.cs new file mode 100644 index 0000000000..56c2ea89e3 --- /dev/null +++ b/framework/test/Volo.Abp.Uow.Tests/Volo/Abp/Uow/AlwaysDisableUnitOfWorkTransaction_Tests.cs @@ -0,0 +1,28 @@ +using Microsoft.Extensions.DependencyInjection; +using Shouldly; +using Volo.Abp.Testing; +using Xunit; + +namespace Volo.Abp.Uow; + +public class AlwaysDisableUnitOfWorkTransaction_Tests: AbpIntegratedTest +{ + protected override void AfterAddApplication(IServiceCollection services) + { + services.AddAlwaysDisableUnitOfWorkTransaction(); + } + + [Fact] + public void AlwaysDisableUnitOfWorkTransaction_Test() + { + GetService().ShouldNotBeNull(); + + var unitOfWorkManager = ServiceProvider.GetRequiredService(); + unitOfWorkManager.GetType().ShouldBe(typeof(AlwaysDisableTransactionsUnitOfWorkManager)); + + using (var uow = unitOfWorkManager.Begin(isTransactional: true)) + { + uow.Options.IsTransactional.ShouldBeFalse(); + } + } +}