Compare commits

...

58 commits
1.1.01 ... main

Author SHA1 Message Date
Sedat Öztürk
233c9b7502 Kullanıcı Detayları ve Avatar 2026-06-07 23:45:39 +03:00
Sedat Öztürk
12f046f262 Workflow ve WizardSeeder düzenlemeleri yapıldı. 2026-06-07 22:42:02 +03:00
Sedat Öztürk
d0cccde53f Workflow için IsFilterUserName özelliği eklendi. 2026-06-07 19:26:19 +03:00
Sedat Öztürk
1d15c44a3d Seçilenleri ve Tümünü Sil butonları 2026-06-07 14:07:48 +03:00
Sedat Öztürk
bade0bab98 Workflow düzeltmeleri 2026-06-07 10:52:28 +03:00
Sedat Öztürk
c204eef755 Workflow Listlerinin Note Özelliği eklendi 2026-06-07 01:22:35 +03:00
Sedat Öztürk
27e65f05f0 Wizard kısmında sütunların Popupformda görünüp görünmeyeceğini belirlenmesi 2026-06-06 22:52:56 +03:00
Sedat Öztürk
64084679e8 Workflow problemleri 2026-06-06 21:31:03 +03:00
Sedat Öztürk
2f1b9d4e77 Wizard problemleri giderildi. 2026-06-06 18:22:14 +03:00
Sedat Öztürk
1c472a7d9a AuditLog
SubForms kısmında ListFormCode dahil edildi
2026-06-05 22:05:57 +03:00
Sedat ÖZTÜRK
119c3650f0 Netdata dashboard kurulumu ve sunucu performansı 2026-06-05 17:22:02 +03:00
Sedat ÖZTÜRK
ebab6ea114 Wizard üzerindeki problemler giderildi. 2026-06-05 12:30:40 +03:00
Sedat ÖZTÜRK
975bc8dd6c intranet kaydırılma işlemi 2026-06-05 08:44:01 +03:00
Sedat Öztürk
97a2a4b38d Wizard üzerinden Entity eklenebiliyor 2026-06-04 23:25:19 +03:00
Sedat ÖZTÜRK
20e7fae481 Public tasarımları 2026-06-04 17:13:55 +03:00
Sedat ÖZTÜRK
6a5881960f Backend takılma problemi giderildi. 2026-06-04 15:08:52 +03:00
Sedat ÖZTÜRK
37d3065ed7 Genel düzenlemeler 2026-06-04 13:11:31 +03:00
Sedat ÖZTÜRK
648a63d618 Setting tanımlama 2026-06-04 11:26:07 +03:00
Sedat Öztürk
197c4e0741 Scriban Problemi ve User Details 2026-06-04 00:38:21 +03:00
Sedat ÖZTÜRK
921c3c6d35 AbpSetting kısmı ayarların uygulanması 2026-06-03 17:43:41 +03:00
Sedat ÖZTÜRK
f56eccee55 MailKit ve MimeKit Deploy problemi 2026-06-03 13:45:30 +03:00
Sedat Öztürk
fd5364ff97 Extend Login Request 2026-06-03 00:24:33 +03:00
Sedat Öztürk
a9e1a15183 Identity NomalizeName 2026-06-02 23:24:06 +03:00
Sedat Öztürk
d161e0f4b9 Tenantlı uygulama için ForgotPassword, ResetPassword 2026-06-02 23:04:25 +03:00
Sedat ÖZTÜRK
f9c5910813 Tenantlı uygulama için Login düzenlemesi 2026-06-02 21:47:01 +03:00
Sedat ÖZTÜRK
67286232da Dark Mode Devexpress uygun hale getirildi. 2026-06-02 12:17:31 +03:00
Sedat ÖZTÜRK
9875ba3041 Route -> Component Type sütunu eklendi.
Dynamic component type
2026-06-02 10:14:33 +03:00
Sedat Öztürk
daf0d51960 FormDevexpress, Grid ve Tree setReadOnly 2026-06-01 23:51:59 +03:00
Sedat ÖZTÜRK
5e6d2f518b FormDevexpress Default Value değerleri düzenlendi 2026-06-01 17:19:49 +03:00
Sedat ÖZTÜRK
2df3e359c4 setReadOnly metodu eklendi. 2026-06-01 16:47:38 +03:00
Sedat ÖZTÜRK
57dbb0d308 Home sayfası için Seeder 2026-06-01 13:26:04 +03:00
Sedat Öztürk
5806ff5f9f Editor Options Builder 2026-05-31 21:16:41 +03:00
Sedat Öztürk
e1c808310d Helper Codes güncellemeleri ve EditorScript düzenlemesi 2026-05-31 12:36:51 +03:00
Sedat Öztürk
96f7091d46 Stil Güncellemeleri 2026-05-30 20:14:08 +03:00
Sedat Öztürk
300bc5ae88 EditForm içerisine Script ve Options komponentleri 2026-05-30 01:22:39 +03:00
Sedat Öztürk
f5b32d5a6b Sql Query Manager .sql dosyasının Preview özelliği 2026-05-29 11:26:10 +03:00
Sedat Öztürk
a3e66081e9 Profile ve UserDetail komponentleri düzenlendi 2026-05-28 01:30:13 +03:00
Sedat Öztürk
231860e85a ListFormWizard SubForms, Wizard, Workflow 2026-05-27 22:09:05 +03:00
Sedat Öztürk
96cd6dfd80 ListForm SubFormDialog güncellemeleri 2026-05-27 19:32:23 +03:00
Sedat Öztürk
84b9f65107 Sql Query Manager -> Move to Host Data 2026-05-27 15:36:46 +03:00
Sedat Öztürk
0f30c4ad7c Tenant yapısına uygunluğu kontrol edildi.
Hatalar giderildi.
2026-05-26 23:01:49 +03:00
Sedat Öztürk
7d006e0d74 HostData ayrımı yapıldı. 2026-05-26 19:49:46 +03:00
Sedat Öztürk
b38aabb5bd Public sayfalarını dark mod eklendi 2026-05-26 19:09:26 +03:00
Sedat Öztürk
ef201fda13 FileManager Seeder 2026-05-26 14:30:04 +03:00
Sedat Öztürk
bea5aabffa Seeder güncellemeleri
LogWarning, LogError, LogError
2026-05-26 12:29:46 +03:00
Sedat Öztürk
df575706fb DbMigrator uyarları kaldırıldı 2026-05-26 12:03:11 +03:00
Sedat Öztürk
0e95c7df7b About güncellemesi 2026-05-26 11:56:05 +03:00
Sedat Öztürk
277dbd907f Intranet stil düzenlemeleri 2026-05-25 23:00:57 +03:00
Sedat Öztürk
8e61351ac0 İşe yaramayan Permission Gruplar kaldırıldı 2026-05-25 21:48:19 +03:00
Sedat Öztürk
d50c62cd1c AuditLogDetail kısmı çalışmıyordu düzeltildi. 2026-05-25 21:30:08 +03:00
Sedat Öztürk
0f5d44ceb0 MicrosoftSql üzerinde çalışması için çalışma 2026-05-25 18:17:47 +03:00
Sedat Öztürk
01e19ef26f PostgreSql üzerinde çalışması için çalışma 2026-05-25 17:31:54 +03:00
Sedat Öztürk
0b5eb3d978 User Details ve Genel düzenlemeler 2026-05-25 12:14:42 +03:00
Sedat Öztürk
e50a02bddc net10 ve Abp10 geçişleri 2026-05-25 01:23:52 +03:00
Sedat Öztürk
9da0b89b8a Setup/Application-Status ve formix required() 2026-05-24 18:48:55 +03:00
Sedat Öztürk
f02a0f8830 Dark mod düzenlemesi 2026-05-24 01:11:54 +03:00
Sedat Öztürk
312f784e3e ListFormWorkflow daki Information düğümü çalıştırıldı 2026-05-24 00:54:36 +03:00
Sedat Öztürk
6ed1c2dabc Darkmod ayarları düzenlendi. 2026-05-24 00:53:56 +03:00
342 changed files with 19515 additions and 6721 deletions

View file

@ -3,7 +3,7 @@
"isRoot": true, "isRoot": true,
"tools": { "tools": {
"volo.abp.cli": { "volo.abp.cli": {
"version": "9.0.2", "version": "10.0.0",
"commands": [ "commands": [
"abp" "abp"
] ]

View file

@ -0,0 +1,5 @@
<Project>
<PropertyGroup>
<NoWarn>$(NoWarn);CS0162;CS8321;CS8618;CS8632</NoWarn>
</PropertyGroup>
</Project>

View file

@ -1,7 +1,13 @@
FROM mcr.microsoft.com/dotnet/sdk:9.0-alpine AS build FROM mcr.microsoft.com/dotnet/sdk:10.0-alpine AS build
ENV DOTNET_NUGET_SIGNATURE_VERIFICATION=false ENV DOTNET_NUGET_SIGNATURE_VERIFICATION=false
WORKDIR /app WORKDIR /app
COPY global.json ./
COPY common.props ./
COPY "modules/Sozsoft.Languages/common.props" "modules/Sozsoft.Languages/"
COPY "modules/Sozsoft.Notifications/common.props" "modules/Sozsoft.Notifications/"
COPY "modules/Sozsoft.Settings/common.props" "modules/Sozsoft.Settings/"
COPY "modules/Sozsoft.SqlQueryManager/common.props" "modules/Sozsoft.SqlQueryManager/"
COPY "modules/Sozsoft.Languages/Sozsoft.Languages.Application.Contracts/Sozsoft.Languages.Application.Contracts.csproj" "modules/Sozsoft.Languages/Sozsoft.Languages.Application.Contracts/" COPY "modules/Sozsoft.Languages/Sozsoft.Languages.Application.Contracts/Sozsoft.Languages.Application.Contracts.csproj" "modules/Sozsoft.Languages/Sozsoft.Languages.Application.Contracts/"
COPY "modules/Sozsoft.Languages/Sozsoft.Languages.Domain/Sozsoft.Languages.Domain.csproj" "modules/Sozsoft.Languages/Sozsoft.Languages.Domain/" COPY "modules/Sozsoft.Languages/Sozsoft.Languages.Domain/Sozsoft.Languages.Domain.csproj" "modules/Sozsoft.Languages/Sozsoft.Languages.Domain/"
COPY "modules/Sozsoft.Languages/Sozsoft.Languages.Domain.Shared/Sozsoft.Languages.Domain.Shared.csproj" "modules/Sozsoft.Languages/Sozsoft.Languages.Domain.Shared/" COPY "modules/Sozsoft.Languages/Sozsoft.Languages.Domain.Shared/Sozsoft.Languages.Domain.Shared.csproj" "modules/Sozsoft.Languages/Sozsoft.Languages.Domain.Shared/"
@ -30,7 +36,7 @@ RUN dotnet restore "src/Sozsoft.Platform.DbMigrator/Sozsoft.Platform.DbMigrator.
COPY . . COPY . .
RUN dotnet publish "src/Sozsoft.Platform.DbMigrator/Sozsoft.Platform.DbMigrator.csproj" -c Release -o /app/publish --no-restore RUN dotnet publish "src/Sozsoft.Platform.DbMigrator/Sozsoft.Platform.DbMigrator.csproj" -c Release -o /app/publish --no-restore
FROM mcr.microsoft.com/dotnet/aspnet:9.0-alpine AS final FROM mcr.microsoft.com/dotnet/aspnet:10.0-alpine AS final
# DevExpress License Key - runtime'da da gerekli # DevExpress License Key - runtime'da da gerekli
ARG DevExpress_License ARG DevExpress_License

View file

@ -1,9 +1,15 @@
FROM mcr.microsoft.com/dotnet/sdk:9.0-alpine AS build FROM mcr.microsoft.com/dotnet/sdk:10.0-alpine AS build
ENV DOTNET_NUGET_SIGNATURE_VERIFICATION=false ENV DOTNET_NUGET_SIGNATURE_VERIFICATION=false
WORKDIR /app WORKDIR /app
RUN apk update && apk upgrade RUN apk update && apk upgrade
RUN apk add nodejs~=24 npm~=11 RUN apk add nodejs~=24 npm~=11
COPY global.json ./
COPY common.props ./
COPY "modules/Sozsoft.Languages/common.props" "modules/Sozsoft.Languages/"
COPY "modules/Sozsoft.Notifications/common.props" "modules/Sozsoft.Notifications/"
COPY "modules/Sozsoft.Settings/common.props" "modules/Sozsoft.Settings/"
COPY "modules/Sozsoft.SqlQueryManager/common.props" "modules/Sozsoft.SqlQueryManager/"
COPY .config/dotnet-tools.json .config/dotnet-tools.json COPY .config/dotnet-tools.json .config/dotnet-tools.json
RUN dotnet tool restore RUN dotnet tool restore
ENV PATH="/root/.dotnet/tools:/app/.config/dotnet/tools:${PATH}" ENV PATH="/root/.dotnet/tools:/app/.config/dotnet/tools:${PATH}"
@ -54,7 +60,7 @@ RUN mkdir -p publish
RUN dotnet publish "src/Sozsoft.Platform.HttpApi.Host/Sozsoft.Platform.HttpApi.Host.csproj" -c Release -o /app/publish --no-restore RUN dotnet publish "src/Sozsoft.Platform.HttpApi.Host/Sozsoft.Platform.HttpApi.Host.csproj" -c Release -o /app/publish --no-restore
RUN dotnet publish "src/Sozsoft.Platform.DbMigrator/Sozsoft.Platform.DbMigrator.csproj" -c Release -o /app/migrator RUN dotnet publish "src/Sozsoft.Platform.DbMigrator/Sozsoft.Platform.DbMigrator.csproj" -c Release -o /app/migrator
FROM mcr.microsoft.com/dotnet/aspnet:9.0-alpine AS final FROM mcr.microsoft.com/dotnet/aspnet:10.0-alpine AS final
# DevExpress License Key - runtime'da da gerekli # DevExpress License Key - runtime'da da gerekli
ARG DevExpress_License ARG DevExpress_License

View file

@ -16,4 +16,10 @@
<Content Remove="$(UserProfile)\.nuget\packages\*\*\contentFiles\any\*\*.abppkg*.json" /> <Content Remove="$(UserProfile)\.nuget\packages\*\*\contentFiles\any\*\*.abppkg*.json" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<PackageReference Include="MailKit" Version="4.16.0" />
<PackageReference Include="MimeKit" Version="4.16.0" />
<PackageReference Include="Scriban" Version="7.2.3" />
</ItemGroup>
</Project> </Project>

View file

@ -1,6 +1,6 @@
{ {
"sdk": { "sdk": {
"version": "9.0.101", "version": "10.0.300",
"rollForward": "latestMajor" "rollForward": "latestMajor"
} }
} }

View file

@ -1,6 +1,4 @@
using Sozsoft.Languages.Localization;
using Volo.Abp.Authorization.Permissions; using Volo.Abp.Authorization.Permissions;
using Volo.Abp.Localization;
namespace Sozsoft.Languages.Permissions; namespace Sozsoft.Languages.Permissions;
@ -8,12 +6,5 @@ public class LanguagesPermissionDefinitionProvider : PermissionDefinitionProvide
{ {
public override void Define(IPermissionDefinitionContext context) public override void Define(IPermissionDefinitionContext context)
{ {
var myGroup = context.AddGroup(LanguagesPermissions.GroupName, L("Permission:Languages"));
}
private static LocalizableString L(string name)
{
return LocalizableString.Create<LanguagesResource>(name);
} }
} }

View file

@ -3,13 +3,13 @@
<Import Project="..\common.props" /> <Import Project="..\common.props" />
<PropertyGroup> <PropertyGroup>
<TargetFramework>net9.0</TargetFramework> <TargetFramework>net10.0</TargetFramework>
<RootNamespace>Sozsoft.Languages</RootNamespace> <RootNamespace>Sozsoft.Languages</RootNamespace>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Volo.Abp.Ddd.Application.Contracts" Version="9.0.2" /> <PackageReference Include="Volo.Abp.Ddd.Application.Contracts" Version="10.0.0" />
<PackageReference Include="Volo.Abp.Authorization" Version="9.0.2" /> <PackageReference Include="Volo.Abp.Authorization" Version="10.0.0" />
<ProjectReference Include="..\Sozsoft.Languages.Domain.Shared\Sozsoft.Languages.Domain.Shared.csproj" /> <ProjectReference Include="..\Sozsoft.Languages.Domain.Shared\Sozsoft.Languages.Domain.Shared.csproj" />
</ItemGroup> </ItemGroup>

View file

@ -1,29 +0,0 @@
using AutoMapper;
using Sozsoft.Languages.Entities;
using Volo.Abp.AutoMapper;
using Volo.Abp.Localization;
namespace Sozsoft.Languages;
public class LanguagesApplicationAutoMapperProfile : Profile
{
public LanguagesApplicationAutoMapperProfile()
{
CreateMap<Language, LanguageInfo>();
CreateMap<Language, LanguageDto>();
CreateMap<LanguageKey, LanguageKeyDto>();
CreateMap<LanguageText, LanguageTextDto>();
CreateMap<LanguageText, LanguageTextEto>();
CreateMap<LanguageTextCreateUpdateDto, LanguageText>()
.IgnoreAllPropertiesWithAnInaccessibleSetter()
.ForMember(dest => dest.LanguageKey, opt => opt.Ignore());
CreateMap<LanguageKey, LanguageTextTranslatedDto>()
.ForMember(d => d.Key, o => o.MapFrom(s => s.Key))
.ForMember(d => d.ResourceName, o => o.MapFrom(s => s.ResourceName))
.ForAllMembers(o => o.Ignore());
}
}

View file

@ -0,0 +1,122 @@
using Sozsoft.Languages.Entities;
using Volo.Abp.Localization;
using Riok.Mapperly.Abstractions;
using Volo.Abp.Mapperly;
namespace Sozsoft.Languages;
[Mapper(RequiredMappingStrategy = RequiredMappingStrategy.Target)]
public partial class LanguageToLanguageInfoMapper : MapperBase<Language, LanguageInfo>
{
public override partial LanguageInfo Map(Language source);
public override partial void Map(Language source, LanguageInfo destination);
public override void BeforeMap(Language source)
{
}
public override void AfterMap(Language source, LanguageInfo destination)
{
}
}
[Mapper(RequiredMappingStrategy = RequiredMappingStrategy.Target)]
public partial class LanguageToLanguageDtoMapper : MapperBase<Language, LanguageDto>
{
public override partial LanguageDto Map(Language source);
public override partial void Map(Language source, LanguageDto destination);
public override void BeforeMap(Language source)
{
}
public override void AfterMap(Language source, LanguageDto destination)
{
}
}
[Mapper(RequiredMappingStrategy = RequiredMappingStrategy.Target)]
public partial class LanguageKeyToLanguageKeyDtoMapper : MapperBase<LanguageKey, LanguageKeyDto>
{
public override partial LanguageKeyDto Map(LanguageKey source);
public override partial void Map(LanguageKey source, LanguageKeyDto destination);
public override void BeforeMap(LanguageKey source)
{
}
public override void AfterMap(LanguageKey source, LanguageKeyDto destination)
{
}
}
[Mapper(RequiredMappingStrategy = RequiredMappingStrategy.Target)]
public partial class LanguageTextToLanguageTextDtoMapper : MapperBase<LanguageText, LanguageTextDto>
{
public override partial LanguageTextDto Map(LanguageText source);
public override partial void Map(LanguageText source, LanguageTextDto destination);
public override void BeforeMap(LanguageText source)
{
}
public override void AfterMap(LanguageText source, LanguageTextDto destination)
{
}
}
[Mapper(RequiredMappingStrategy = RequiredMappingStrategy.Target)]
public partial class LanguageTextToLanguageTextEtoMapper : MapperBase<LanguageText, LanguageTextEto>
{
public override partial LanguageTextEto Map(LanguageText source);
public override partial void Map(LanguageText source, LanguageTextEto destination);
public override void BeforeMap(LanguageText source)
{
}
public override void AfterMap(LanguageText source, LanguageTextEto destination)
{
}
}
[Mapper(RequiredMappingStrategy = RequiredMappingStrategy.Target)]
public partial class LanguageTextCreateUpdateDtoToLanguageTextMapper : MapperBase<LanguageTextCreateUpdateDto, LanguageText>
{
[MapperIgnoreTarget(nameof(LanguageText.LanguageKey))]
public override partial LanguageText Map(LanguageTextCreateUpdateDto source);
[MapperIgnoreTarget(nameof(LanguageText.LanguageKey))]
public override partial void Map(LanguageTextCreateUpdateDto source, LanguageText destination);
public override void BeforeMap(LanguageTextCreateUpdateDto source)
{
}
public override void AfterMap(LanguageTextCreateUpdateDto source, LanguageText destination)
{
}
}
[Mapper(RequiredMappingStrategy = RequiredMappingStrategy.Target)]
public partial class LanguageKeyToLanguageTextTranslatedDtoMapper : MapperBase<LanguageKey, LanguageTextTranslatedDto>
{
[MapperIgnoreTarget(nameof(LanguageTextTranslatedDto.Id))]
public override partial LanguageTextTranslatedDto Map(LanguageKey source);
[MapperIgnoreTarget(nameof(LanguageTextTranslatedDto.Id))]
public override partial void Map(LanguageKey source, LanguageTextTranslatedDto destination);
public override void BeforeMap(LanguageKey source)
{
}
public override void AfterMap(LanguageKey source, LanguageTextTranslatedDto destination)
{
}
}

View file

@ -1,6 +1,6 @@
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Application; using Volo.Abp.Application;
using Volo.Abp.AutoMapper; using Volo.Abp.Mapperly;
using Volo.Abp.Modularity; using Volo.Abp.Modularity;
namespace Sozsoft.Languages; namespace Sozsoft.Languages;
@ -9,18 +9,13 @@ namespace Sozsoft.Languages;
typeof(LanguagesDomainModule), typeof(LanguagesDomainModule),
typeof(LanguagesApplicationContractsModule), typeof(LanguagesApplicationContractsModule),
typeof(AbpDddApplicationModule), typeof(AbpDddApplicationModule),
typeof(AbpAutoMapperModule) typeof(AbpMapperlyModule)
)] )]
public class LanguagesApplicationModule : AbpModule public class LanguagesApplicationModule : AbpModule
{ {
public override void ConfigureServices(ServiceConfigurationContext context) public override void ConfigureServices(ServiceConfigurationContext context)
{ {
context.Services.AddAutoMapperObjectMapper<LanguagesApplicationModule>(); context.Services.AddMapperlyObjectMapper<LanguagesApplicationModule>();
Configure<AbpAutoMapperOptions>(options =>
{
options.AddMaps<LanguagesApplicationModule>(validate: true);
});
} }
} }

View file

@ -3,14 +3,14 @@
<Import Project="..\common.props" /> <Import Project="..\common.props" />
<PropertyGroup> <PropertyGroup>
<TargetFramework>net9.0</TargetFramework> <TargetFramework>net10.0</TargetFramework>
<RootNamespace>Sozsoft.Languages</RootNamespace> <RootNamespace>Sozsoft.Languages</RootNamespace>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Volo.Abp.AutoMapper" Version="9.0.2" /> <PackageReference Include="Volo.Abp.Mapperly" Version="10.0.0" />
<PackageReference Include="Volo.Abp.Ddd.Application" Version="9.0.2" /> <PackageReference Include="Volo.Abp.Ddd.Application" Version="10.0.0" />
<PackageReference Include="Volo.Abp.EntityFrameworkCore" Version="9.0.2" /> <PackageReference Include="Volo.Abp.EntityFrameworkCore" Version="10.0.0" />
<ProjectReference Include="..\Sozsoft.Languages.Application.Contracts\Sozsoft.Languages.Application.Contracts.csproj" /> <ProjectReference Include="..\Sozsoft.Languages.Application.Contracts\Sozsoft.Languages.Application.Contracts.csproj" />
<ProjectReference Include="..\Sozsoft.Languages.Domain\Sozsoft.Languages.Domain.csproj" /> <ProjectReference Include="..\Sozsoft.Languages.Domain\Sozsoft.Languages.Domain.csproj" />
</ItemGroup> </ItemGroup>

View file

@ -1,19 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\common.props" /> <Import Project="..\common.props" />
<PropertyGroup> <PropertyGroup>
<TargetFramework>net9.0</TargetFramework> <TargetFramework>net10.0</TargetFramework>
<GenerateEmbeddedFilesManifest>true</GenerateEmbeddedFilesManifest> <GenerateEmbeddedFilesManifest>false</GenerateEmbeddedFilesManifest>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Volo.Abp.Ddd.Domain.Shared" Version="9.0.2" /> <PackageReference Include="Volo.Abp.Ddd.Domain.Shared" Version="10.0.0" />
<PackageReference Include="Volo.Abp.Validation" Version="9.0.2" /> <PackageReference Include="Volo.Abp.Validation" Version="10.0.0" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="9.0.0" /> <PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="10.0.0" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View file

@ -3,13 +3,13 @@
<Import Project="..\common.props" /> <Import Project="..\common.props" />
<PropertyGroup> <PropertyGroup>
<TargetFramework>net9.0</TargetFramework> <TargetFramework>net10.0</TargetFramework>
<RootNamespace>Sozsoft.Languages</RootNamespace> <RootNamespace>Sozsoft.Languages</RootNamespace>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Volo.Abp.Caching.StackExchangeRedis" Version="9.0.2" /> <PackageReference Include="Volo.Abp.Caching.StackExchangeRedis" Version="10.0.0" />
<PackageReference Include="Volo.Abp.Ddd.Domain" Version="9.0.2" /> <PackageReference Include="Volo.Abp.Ddd.Domain" Version="10.0.0" />
<ProjectReference Include="..\Sozsoft.Languages.Domain.Shared\Sozsoft.Languages.Domain.Shared.csproj" /> <ProjectReference Include="..\Sozsoft.Languages.Domain.Shared\Sozsoft.Languages.Domain.Shared.csproj" />
</ItemGroup> </ItemGroup>

View file

@ -3,12 +3,12 @@
<Import Project="..\common.props" /> <Import Project="..\common.props" />
<PropertyGroup> <PropertyGroup>
<TargetFramework>net9.0</TargetFramework> <TargetFramework>net10.0</TargetFramework>
<RootNamespace>Sozsoft.Languages</RootNamespace> <RootNamespace>Sozsoft.Languages</RootNamespace>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Volo.Abp.EntityFrameworkCore" Version="9.0.2" /> <PackageReference Include="Volo.Abp.EntityFrameworkCore" Version="10.0.0" />
<ProjectReference Include="..\Sozsoft.Languages.Domain\Sozsoft.Languages.Domain.csproj" /> <ProjectReference Include="..\Sozsoft.Languages.Domain\Sozsoft.Languages.Domain.csproj" />
</ItemGroup> </ItemGroup>

View file

@ -7,11 +7,14 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="ConfigureAwait.Fody" Version="3.3.1" PrivateAssets="All" /> <PackageReference Include="ConfigureAwait.Fody" Version="3.4.0" PrivateAssets="All" />
<PackageReference Include="Fody" Version="6.5.3"> <PackageReference Include="Fody" Version="6.9.3">
<PrivateAssets>All</PrivateAssets> <PrivateAssets>All</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference> </PackageReference>
<PackageReference Include="MailKit" Version="4.16.0" />
<PackageReference Include="MimeKit" Version="4.16.0" />
<PackageReference Include="Scriban" Version="7.2.3" />
</ItemGroup> </ItemGroup>

View file

@ -1,13 +0,0 @@
using AutoMapper;
namespace Sozsoft.MailQueue.Application;
public class MailQueueAutoMapperProfile : Profile
{
public MailQueueAutoMapperProfile()
{
}
}

View file

@ -0,0 +1 @@
namespace Sozsoft.MailQueue.Application;

View file

@ -31,6 +31,8 @@ public class MailTrackingManager : DomainService
/// <returns></returns> /// <returns></returns>
public async Task StartAsync() public async Task StartAsync()
{ {
// https://us-east-1.console.aws.amazon.com/iam/home?region=eu-central-1#/users
// https://eu-central-1.console.aws.amazon.com/ses/home?region=eu-central-1#/identities/system%40sozsoft.com?tabId=authentication
var accessKey = configuration.GetValue<string>(AmazonSesEmailSettingNames.AccessKey); var accessKey = configuration.GetValue<string>(AmazonSesEmailSettingNames.AccessKey);
var accessKeyId = configuration.GetValue<string>(AmazonSesEmailSettingNames.AccessKeyId); var accessKeyId = configuration.GetValue<string>(AmazonSesEmailSettingNames.AccessKeyId);
var region = configuration.GetValue<string>(AmazonSesEmailSettingNames.Region); var region = configuration.GetValue<string>(AmazonSesEmailSettingNames.Region);

View file

@ -1,10 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net9.0</TargetFramework> <TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<GenerateEmbeddedFilesManifest>true</GenerateEmbeddedFilesManifest> <GenerateEmbeddedFilesManifest>true</GenerateEmbeddedFilesManifest>
<NoWarn>$(NoWarn);CS8632</NoWarn>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
@ -19,22 +18,25 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Volo.Abp.BackgroundJobs" Version="9.0.2" /> <PackageReference Include="Volo.Abp.BackgroundJobs" Version="10.0.0" />
<PackageReference Include="Volo.Abp.EntityFrameworkCore" Version="9.0.2" /> <PackageReference Include="Volo.Abp.EntityFrameworkCore" Version="10.0.0" />
<PackageReference Include="Volo.Abp.Validation" Version="9.0.2" /> <PackageReference Include="Volo.Abp.Validation" Version="10.0.0" />
<PackageReference Include="Volo.Abp.Caching.StackExchangeRedis" Version="9.0.2" /> <PackageReference Include="Volo.Abp.Caching.StackExchangeRedis" Version="10.0.0" />
<PackageReference Include="Volo.Abp.Authorization" Version="9.0.2" /> <PackageReference Include="Volo.Abp.Authorization" Version="10.0.0" />
<PackageReference Include="Volo.Abp.AutoMapper" Version="9.0.2" /> <PackageReference Include="Volo.Abp.Mapperly" Version="10.0.0" />
<PackageReference Include="Volo.Abp.Ddd.Domain" Version="9.0.2" /> <PackageReference Include="Volo.Abp.Ddd.Domain" Version="10.0.0" />
<PackageReference Include="Volo.Abp.Ddd.Application" Version="9.0.2" /> <PackageReference Include="Volo.Abp.Ddd.Application" Version="10.0.0" />
<PackageReference Include="Volo.Abp.Ddd.Application.Contracts" Version="9.0.2" /> <PackageReference Include="Volo.Abp.Ddd.Application.Contracts" Version="10.0.0" />
<PackageReference Include="Volo.Abp.TextTemplating.Razor" Version="9.0.2" /> <PackageReference Include="Volo.Abp.TextTemplating.Razor" Version="10.0.0" />
<PackageReference Include="MailKit" Version="4.16.0" />
<PackageReference Include="MimeKit" Version="4.16.0" />
<PackageReference Include="Scriban" Version="7.2.3" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="AWSSDK.SQS" Version="3.7.400" /> <PackageReference Include="AWSSDK.SQS" Version="3.7.400" />
<PackageReference Include="ClosedXML" Version="0.104.2" /> <PackageReference Include="ClosedXML" Version="0.104.2" />
<PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="9.0.0" /> <PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="10.0.0" />
<PackageReference Include="Wkhtmltopdf.NetCore" Version="3.0.2" /> <PackageReference Include="Wkhtmltopdf.NetCore" Version="3.0.2" />
</ItemGroup> </ItemGroup>

View file

@ -6,7 +6,7 @@ using Microsoft.CodeAnalysis;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Application; using Volo.Abp.Application;
using Volo.Abp.Authorization; using Volo.Abp.Authorization;
using Volo.Abp.AutoMapper; using Volo.Abp.Mapperly;
using Volo.Abp.Domain; using Volo.Abp.Domain;
using Volo.Abp.EntityFrameworkCore; using Volo.Abp.EntityFrameworkCore;
using Volo.Abp.Localization; using Volo.Abp.Localization;
@ -22,7 +22,7 @@ namespace Sozsoft.MailQueue;
typeof(AbpDddDomainModule), typeof(AbpDddDomainModule),
typeof(AbpDddApplicationModule), typeof(AbpDddApplicationModule),
typeof(AbpDddApplicationContractsModule), typeof(AbpDddApplicationContractsModule),
typeof(AbpAutoMapperModule), typeof(AbpMapperlyModule),
typeof(AbpAuthorizationModule), typeof(AbpAuthorizationModule),
typeof(AbpEntityFrameworkCoreModule), typeof(AbpEntityFrameworkCoreModule),
typeof(AbpTextTemplatingRazorModule), typeof(AbpTextTemplatingRazorModule),
@ -32,11 +32,7 @@ public class ErpMailQueueModule : AbpModule
{ {
public override void ConfigureServices(ServiceConfigurationContext context) public override void ConfigureServices(ServiceConfigurationContext context)
{ {
context.Services.AddAutoMapperObjectMapper<ErpMailQueueModule>(); context.Services.AddMapperlyObjectMapper<ErpMailQueueModule>();
Configure<AbpAutoMapperOptions>(options =>
{
options.AddMaps<ErpMailQueueModule>(validate: true);
});
Configure<AbpLocalizationOptions>(options => Configure<AbpLocalizationOptions>(options =>
{ {

View file

@ -1,6 +1,4 @@
using Sozsoft.Notifications.Localization;
using Volo.Abp.Authorization.Permissions; using Volo.Abp.Authorization.Permissions;
using Volo.Abp.Localization;
namespace Sozsoft.Notifications.Permissions; namespace Sozsoft.Notifications.Permissions;
@ -8,12 +6,5 @@ public class NotificationPermissionDefinitionProvider : PermissionDefinitionProv
{ {
public override void Define(IPermissionDefinitionContext context) public override void Define(IPermissionDefinitionContext context)
{ {
var myGroup = context.AddGroup(NotificationPermissions.GroupName, L("Permission:Notifications"));
}
private static LocalizableString L(string name)
{
return LocalizableString.Create<NotificationResource>(name);
} }
} }

View file

@ -3,14 +3,14 @@
<Import Project="..\common.props" /> <Import Project="..\common.props" />
<PropertyGroup> <PropertyGroup>
<TargetFramework>net9.0</TargetFramework> <TargetFramework>net10.0</TargetFramework>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<RootNamespace>Sozsoft.Notifications</RootNamespace> <RootNamespace>Sozsoft.Notifications</RootNamespace>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Volo.Abp.Ddd.Application.Contracts" Version="9.0.2" /> <PackageReference Include="Volo.Abp.Ddd.Application.Contracts" Version="10.0.0" />
<PackageReference Include="Volo.Abp.Authorization" Version="9.0.2" /> <PackageReference Include="Volo.Abp.Authorization" Version="10.0.0" />
<ProjectReference Include="..\Sozsoft.Notifications.Domain.Shared\Sozsoft.Notifications.Domain.Shared.csproj" /> <ProjectReference Include="..\Sozsoft.Notifications.Domain.Shared\Sozsoft.Notifications.Domain.Shared.csproj" />
</ItemGroup> </ItemGroup>

View file

@ -1,19 +0,0 @@
using AutoMapper;
using Sozsoft.Notifications.Entities;
using Sozsoft.Notifications.NotificationRules;
namespace Sozsoft.Notifications.Application;
public class NotificationApplicationAutoMapperProfile : Profile
{
public NotificationApplicationAutoMapperProfile()
{
CreateMap<NotificationType, NotificationTypeDto>();
CreateMap<NotificationRule, NotificationRuleDto>();
CreateMap<Notification, NotificationDto>()
.ForMember(d => d.CreatorFullname, o => o.Ignore())
.ForMember(d => d.TenantId, o => o.Ignore());
CreateMap<CreateUpdateNotificationRuleDto, NotificationRule>(MemberList.Source);
}
}

View file

@ -0,0 +1,90 @@
using Sozsoft.Notifications.Entities;
using Sozsoft.Notifications.Domain;
using Sozsoft.Notifications.NotificationRules;
using Riok.Mapperly.Abstractions;
using Volo.Abp.Mapperly;
namespace Sozsoft.Notifications.Application;
[Mapper(RequiredMappingStrategy = RequiredMappingStrategy.Target)]
public partial class NotificationTypeToNotificationTypeDtoMapper : MapperBase<NotificationType, NotificationTypeDto>
{
public override partial NotificationTypeDto Map(NotificationType source);
public override partial void Map(NotificationType source, NotificationTypeDto destination);
public override void BeforeMap(NotificationType source)
{
}
public override void AfterMap(NotificationType source, NotificationTypeDto destination)
{
}
}
[Mapper(RequiredMappingStrategy = RequiredMappingStrategy.Target)]
public partial class NotificationRuleToNotificationRuleDtoMapper : MapperBase<NotificationRule, NotificationRuleDto>
{
public override partial NotificationRuleDto Map(NotificationRule source);
public override partial void Map(NotificationRule source, NotificationRuleDto destination);
public override void BeforeMap(NotificationRule source)
{
}
public override void AfterMap(NotificationRule source, NotificationRuleDto destination)
{
}
}
[Mapper(RequiredMappingStrategy = RequiredMappingStrategy.Target)]
public partial class NotificationToNotificationDtoMapper : MapperBase<Notification, NotificationDto>
{
[MapperIgnoreTarget(nameof(NotificationDto.CreatorFullname))]
[MapperIgnoreTarget(nameof(NotificationDto.TenantId))]
public override partial NotificationDto Map(Notification source);
[MapperIgnoreTarget(nameof(NotificationDto.CreatorFullname))]
[MapperIgnoreTarget(nameof(NotificationDto.TenantId))]
public override partial void Map(Notification source, NotificationDto destination);
public override void BeforeMap(Notification source)
{
}
public override void AfterMap(Notification source, NotificationDto destination)
{
}
}
[Mapper(RequiredMappingStrategy = RequiredMappingStrategy.Target)]
public partial class CreateUpdateNotificationRuleDtoToNotificationRuleMapper : MapperBase<CreateUpdateNotificationRuleDto, NotificationRule>
{
[MapperIgnoreTarget(nameof(NotificationRule.RecipientType))]
public override NotificationRule Map(CreateUpdateNotificationRuleDto source)
{
var destination = new NotificationRule
{
RecipientType = NotificationRecipientTypes.All,
Channel = source.Channel,
NotificationTypeId = source.NotificationTypeId,
IsActive = source.IsActive
};
AfterMap(source, destination);
return destination;
}
[MapperIgnoreTarget(nameof(NotificationRule.RecipientType))]
public override partial void Map(CreateUpdateNotificationRuleDto source, NotificationRule destination);
public override void BeforeMap(CreateUpdateNotificationRuleDto source)
{
}
public override void AfterMap(CreateUpdateNotificationRuleDto source, NotificationRule destination)
{
}
}

View file

@ -1,7 +1,7 @@
using Sozsoft.Notifications.Domain; using Sozsoft.Notifications.Domain;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Application; using Volo.Abp.Application;
using Volo.Abp.AutoMapper; using Volo.Abp.Mapperly;
using Volo.Abp.Modularity; using Volo.Abp.Modularity;
namespace Sozsoft.Notifications.Application; namespace Sozsoft.Notifications.Application;
@ -10,17 +10,13 @@ namespace Sozsoft.Notifications.Application;
typeof(NotificationDomainModule), typeof(NotificationDomainModule),
typeof(NotificationApplicationContractsModule), typeof(NotificationApplicationContractsModule),
typeof(AbpDddApplicationModule), typeof(AbpDddApplicationModule),
typeof(AbpAutoMapperModule) typeof(AbpMapperlyModule)
)] )]
public class NotificationApplicationModule : AbpModule public class NotificationApplicationModule : AbpModule
{ {
public override void ConfigureServices(ServiceConfigurationContext context) public override void ConfigureServices(ServiceConfigurationContext context)
{ {
context.Services.AddAutoMapperObjectMapper<NotificationApplicationModule>(); context.Services.AddMapperlyObjectMapper<NotificationApplicationModule>();
Configure<AbpAutoMapperOptions>(options =>
{
options.AddMaps<NotificationApplicationModule>(validate: true);
});
} }
} }

View file

@ -3,14 +3,14 @@
<Import Project="..\common.props" /> <Import Project="..\common.props" />
<PropertyGroup> <PropertyGroup>
<TargetFramework>net9.0</TargetFramework> <TargetFramework>net10.0</TargetFramework>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<RootNamespace>Sozsoft.Notifications</RootNamespace> <RootNamespace>Sozsoft.Notifications</RootNamespace>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Volo.Abp.AutoMapper" Version="9.0.2" /> <PackageReference Include="Volo.Abp.Mapperly" Version="10.0.0" />
<PackageReference Include="Volo.Abp.Ddd.Application" Version="9.0.2" /> <PackageReference Include="Volo.Abp.Ddd.Application" Version="10.0.0" />
<ProjectReference Include="..\Sozsoft.Notifications.Application.Contracts\Sozsoft.Notifications.Application.Contracts.csproj" /> <ProjectReference Include="..\Sozsoft.Notifications.Application.Contracts\Sozsoft.Notifications.Application.Contracts.csproj" />
<ProjectReference Include="..\Sozsoft.Notifications.Domain\Sozsoft.Notifications.Domain.csproj" /> <ProjectReference Include="..\Sozsoft.Notifications.Domain\Sozsoft.Notifications.Domain.csproj" />
</ItemGroup> </ItemGroup>

View file

@ -3,19 +3,19 @@
<Import Project="..\common.props" /> <Import Project="..\common.props" />
<PropertyGroup> <PropertyGroup>
<TargetFramework>net9.0</TargetFramework> <TargetFramework>net10.0</TargetFramework>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<RootNamespace>Sozsoft.Notifications</RootNamespace> <RootNamespace>Sozsoft.Notifications</RootNamespace>
<GenerateEmbeddedFilesManifest>true</GenerateEmbeddedFilesManifest> <GenerateEmbeddedFilesManifest>false</GenerateEmbeddedFilesManifest>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Volo.Abp.Ddd.Domain.Shared" Version="9.0.2" /> <PackageReference Include="Volo.Abp.Ddd.Domain.Shared" Version="10.0.0" />
<PackageReference Include="Volo.Abp.Validation" Version="9.0.2" /> <PackageReference Include="Volo.Abp.Validation" Version="10.0.0" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="9.0.0" /> <PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="10.0.0" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View file

@ -3,16 +3,15 @@
<Import Project="..\common.props" /> <Import Project="..\common.props" />
<PropertyGroup> <PropertyGroup>
<TargetFramework>net9.0</TargetFramework> <TargetFramework>net10.0</TargetFramework>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<RootNamespace>Sozsoft.Notifications</RootNamespace> <RootNamespace>Sozsoft.Notifications</RootNamespace>
<NoWarn>$(NoWarn);CS8632</NoWarn>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Volo.Abp.Ddd.Domain" Version="9.0.2" /> <PackageReference Include="Volo.Abp.Ddd.Domain" Version="10.0.0" />
<PackageReference Include="Volo.Abp.Identity.Domain" Version="9.0.2" /> <PackageReference Include="Volo.Abp.Identity.Domain" Version="10.0.0" />
<PackageReference Include="Volo.Abp.EntityFrameworkCore" Version="9.0.2" /> <PackageReference Include="Volo.Abp.EntityFrameworkCore" Version="10.0.0" />
<ProjectReference Include="..\Sozsoft.Notifications.Domain.Shared\Sozsoft.Notifications.Domain.Shared.csproj" /> <ProjectReference Include="..\Sozsoft.Notifications.Domain.Shared\Sozsoft.Notifications.Domain.Shared.csproj" />
</ItemGroup> </ItemGroup>

View file

@ -3,13 +3,13 @@
<Import Project="..\common.props" /> <Import Project="..\common.props" />
<PropertyGroup> <PropertyGroup>
<TargetFramework>net9.0</TargetFramework> <TargetFramework>net10.0</TargetFramework>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<RootNamespace>Sozsoft.Notifications</RootNamespace> <RootNamespace>Sozsoft.Notifications</RootNamespace>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Volo.Abp.EntityFrameworkCore" Version="9.0.2" /> <PackageReference Include="Volo.Abp.EntityFrameworkCore" Version="10.0.0" />
<ProjectReference Include="..\Sozsoft.Notifications.Domain\Sozsoft.Notifications.Domain.csproj" /> <ProjectReference Include="..\Sozsoft.Notifications.Domain\Sozsoft.Notifications.Domain.csproj" />
</ItemGroup> </ItemGroup>

View file

@ -7,11 +7,14 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="ConfigureAwait.Fody" Version="3.3.1" PrivateAssets="All" /> <PackageReference Include="ConfigureAwait.Fody" Version="3.4.0" PrivateAssets="All" />
<PackageReference Include="Fody" Version="6.5.3"> <PackageReference Include="Fody" Version="6.9.3">
<PrivateAssets>All</PrivateAssets> <PrivateAssets>All</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference> </PackageReference>
<PackageReference Include="MailKit" Version="4.16.0" />
<PackageReference Include="MimeKit" Version="4.16.0" />
<PackageReference Include="Scriban" Version="7.2.3" />
</ItemGroup> </ItemGroup>

View file

@ -65,6 +65,7 @@ public class AmazonSesEmailSender : EmailSenderBase, ISozsoftEmailSender, ITrans
await BackgroundJobManager.EnqueueAsync( await BackgroundJobManager.EnqueueAsync(
new ErpBackgroundEmailSendingJobArgs new ErpBackgroundEmailSendingJobArgs
{ {
TenantId = CurrentTenant.Id,
To = to, To = to,
Sender = sender, Sender = sender,
Params = @params, Params = @params,

View file

@ -1,5 +1,6 @@
using Volo.Abp.BackgroundJobs; using Volo.Abp.BackgroundJobs;
using Volo.Abp.DependencyInjection; using Volo.Abp.DependencyInjection;
using Volo.Abp.MultiTenancy;
namespace Sozsoft.Sender.Mail; namespace Sozsoft.Sender.Mail;
@ -7,13 +8,19 @@ public class ErpBackgroundEmailSendingJob :
AsyncBackgroundJob<ErpBackgroundEmailSendingJobArgs>, ITransientDependency AsyncBackgroundJob<ErpBackgroundEmailSendingJobArgs>, ITransientDependency
{ {
protected ISozsoftEmailSender EmailSender { get; } protected ISozsoftEmailSender EmailSender { get; }
protected ICurrentTenant CurrentTenant { get; }
public ErpBackgroundEmailSendingJob(ISozsoftEmailSender emailSender) public ErpBackgroundEmailSendingJob(
ISozsoftEmailSender emailSender,
ICurrentTenant currentTenant)
{ {
EmailSender = emailSender; EmailSender = emailSender;
CurrentTenant = currentTenant;
} }
public override async Task ExecuteAsync(ErpBackgroundEmailSendingJobArgs args) public override async Task ExecuteAsync(ErpBackgroundEmailSendingJobArgs args)
{
using (CurrentTenant.Change(args.TenantId))
{ {
//await EmailSender.SendEmailAsync(args.Template, args.To, args.Params, args.Subject); //await EmailSender.SendEmailAsync(args.Template, args.To, args.Params, args.Subject);
await EmailSender.SendEmailAsync( await EmailSender.SendEmailAsync(
@ -24,5 +31,5 @@ public class ErpBackgroundEmailSendingJob :
args.Subject, args.Subject,
args.Attachments); args.Attachments);
} }
}
} }

View file

@ -1,8 +1,12 @@
namespace Sozsoft.Sender.Mail; using Volo.Abp.MultiTenancy;
namespace Sozsoft.Sender.Mail;
[Serializable] [Serializable]
public class ErpBackgroundEmailSendingJobArgs public class ErpBackgroundEmailSendingJobArgs : IMultiTenant
{ {
public Guid? TenantId { get; set; }
public string[] To { get; set; } public string[] To { get; set; }
public KeyValuePair<string, string>? Sender { get; set; } public KeyValuePair<string, string>? Sender { get; set; }
@ -14,6 +18,4 @@ public class ErpBackgroundEmailSendingJobArgs
public Dictionary<string, string>? Attachments { get; set; } public Dictionary<string, string>? Attachments { get; set; }
public string? TextContent { get; set; } public string? TextContent { get; set; }
} }

View file

@ -17,15 +17,15 @@ public class RocketSender : ISozsoftRocketSender
public async Task<RocketSendResult> SendAsync(string Username, string Message) public async Task<RocketSendResult> SendAsync(string Username, string Message)
{ {
logger.LogInformation("Rocket gönderiliyor. {Username}, {Message}", Username, Message); logger.LogInformation("Sending Rocket message. {Username}, {Message}", Username, Message);
var result = await httpClient.SendMessageAsync(Username, Message); var result = await httpClient.SendMessageAsync(Username, Message);
if (result.Success) if (result.Success)
{ {
logger.LogInformation("Rocket gönderildi. {Username}, {Message}", Username, Message); logger.LogInformation("Rocket sent successfully. {Username}, {Message}", Username, Message);
} }
else else
{ {
logger.LogWarning("Rocket gönderilemedi. {Username}, {Message}", Username, Message); logger.LogWarning("Failed to send Rocket message. {Username}, {Message}", Username, Message);
} }
return new RocketSendResult return new RocketSendResult

View file

@ -25,15 +25,15 @@ public class PostaGuverciniSmsSender : ISozsoftSmsSender
Message = Check.NotNullOrWhiteSpace(Message, nameof(Message)); Message = Check.NotNullOrWhiteSpace(Message, nameof(Message));
PhoneNumber = PhoneNumber.StartsWith('0') ? PhoneNumber[1..] : PhoneNumber; PhoneNumber = PhoneNumber.StartsWith('0') ? PhoneNumber[1..] : PhoneNumber;
logger.LogInformation("Sms gönderiliyor. {PhoneNumber}, {Message}", PhoneNumber, Message); logger.LogInformation("Sending SMS message. {PhoneNumber}, {Message}", PhoneNumber, Message);
var result = await httpClient.SendSmsAsync(PhoneNumber, Message); var result = await httpClient.SendSmsAsync(PhoneNumber, Message);
if (result.IsSuccess) if (result.IsSuccess)
{ {
logger.LogInformation("Sms gönderildi. {PhoneNumber}, {Message}", PhoneNumber, Message); logger.LogInformation("SMS sent successfully. {PhoneNumber}, {Message}", PhoneNumber, Message);
} }
else else
{ {
logger.LogWarning("Sms gönderilemedi. {PhoneNumber}, {Message}, {Error}", PhoneNumber, Message, $"{result.ErrNo}:{result.ErrText}"); logger.LogWarning("Failed to send SMS message. {PhoneNumber}, {Message}, {Error}", PhoneNumber, Message, $"{result.ErrNo}:{result.ErrText}");
} }
return new SmsSendResult return new SmsSendResult

View file

@ -1,17 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net9.0</TargetFramework> <TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="AWSSDK.SimpleEmailV2" Version="3.7.406" /> <PackageReference Include="AWSSDK.SimpleEmailV2" Version="3.7.406" />
<PackageReference Include="Volo.Abp.BackgroundJobs" Version="9.0.2" /> <PackageReference Include="Volo.Abp.BackgroundJobs" Version="10.0.0" />
<PackageReference Include="Volo.Abp.Emailing" Version="9.0.2" /> <PackageReference Include="Volo.Abp.Emailing" Version="10.0.0" />
<PackageReference Include="Volo.Abp.MailKit" Version="9.0.2" /> <PackageReference Include="Volo.Abp.MailKit" Version="10.0.0" />
<PackageReference Include="Volo.Abp.Sms" Version="9.0.2" /> <PackageReference Include="Volo.Abp.Sms" Version="10.0.0" />
<PackageReference Include="Microsoft.Extensions.Http" Version="9.0.0" /> <PackageReference Include="Microsoft.Extensions.Http" Version="10.0.0" />
<PackageReference Include="MailKit" Version="4.16.0" />
<PackageReference Include="MimeKit" Version="4.16.0" />
<PackageReference Include="Scriban" Version="7.2.3" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View file

@ -23,16 +23,16 @@ public class SozsoftWhatsAppSender : ISozsoftWhatsAppSender
public async Task<WhatsAppSendResult> SendAsync(string To, string Message, string LanguageCode = "tr") public async Task<WhatsAppSendResult> SendAsync(string To, string Message, string LanguageCode = "tr")
{ {
logger.LogInformation("WhatsApp gönderiliyor. {To}, {LanguageCode}, {Message}", To, LanguageCode, Message); logger.LogInformation("Sending WhatsApp message. {To}, {LanguageCode}, {Message}", To, LanguageCode, Message);
var result = await httpClient.SendMessageAsync(To, Message, LanguageCode); var result = await httpClient.SendMessageAsync(To, Message, LanguageCode);
var success = !result.messages.IsNullOrEmpty() && result.messages.FirstOrDefault()?.message_status == "accepted"; var success = !result.messages.IsNullOrEmpty() && result.messages.FirstOrDefault()?.message_status == "accepted";
if (success) if (success)
{ {
logger.LogInformation("WhatsApp gönderildi. {To}, {LanguageCode}, {Message}", To, LanguageCode, Message); logger.LogInformation("WhatsApp sent successfully. {To}, {LanguageCode}, {Message}", To, LanguageCode, Message);
} }
else else
{ {
logger.LogWarning("WhatsApp gönderilemedi. {To}, {LanguageCode}, {Message}", To, LanguageCode, Message); logger.LogWarning("Failed to send WhatsApp message. {To}, {LanguageCode}, {Message}", To, LanguageCode, Message);
} }
return new WhatsAppSendResult return new WhatsAppSendResult

View file

@ -1,6 +1,4 @@
using Sozsoft.Settings.Localization;
using Volo.Abp.Authorization.Permissions; using Volo.Abp.Authorization.Permissions;
using Volo.Abp.Localization;
namespace Sozsoft.Settings.Permissions; namespace Sozsoft.Settings.Permissions;
@ -8,12 +6,5 @@ public class SettingsPermissionDefinitionProvider : PermissionDefinitionProvider
{ {
public override void Define(IPermissionDefinitionContext context) public override void Define(IPermissionDefinitionContext context)
{ {
var myGroup = context.AddGroup(SettingsPermissions.GroupName, L("Permission:Settings"));
}
private static LocalizableString L(string name)
{
return LocalizableString.Create<SettingsResource>(name);
} }
} }

View file

@ -3,14 +3,14 @@
<Import Project="..\common.props" /> <Import Project="..\common.props" />
<PropertyGroup> <PropertyGroup>
<TargetFramework>net9.0</TargetFramework> <TargetFramework>net10.0</TargetFramework>
<RootNamespace>Sozsoft.Settings</RootNamespace> <RootNamespace>Sozsoft.Settings</RootNamespace>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Volo.Abp.Ddd.Application.Contracts" Version="9.0.2" /> <PackageReference Include="Volo.Abp.Ddd.Application.Contracts" Version="10.0.0" />
<PackageReference Include="Volo.Abp.Authorization" Version="9.0.2" /> <PackageReference Include="Volo.Abp.Authorization" Version="10.0.0" />
<PackageReference Include="Volo.Abp.SettingManagement.Application.Contracts" Version="9.0.2" /> <PackageReference Include="Volo.Abp.SettingManagement.Application.Contracts" Version="10.0.0" />
<ProjectReference Include="..\Sozsoft.Settings.Domain.Shared\Sozsoft.Settings.Domain.Shared.csproj" /> <ProjectReference Include="..\Sozsoft.Settings.Domain.Shared\Sozsoft.Settings.Domain.Shared.csproj" />
</ItemGroup> </ItemGroup>

View file

@ -5,10 +5,9 @@ using System.Threading.Tasks;
using Sozsoft.Languages; using Sozsoft.Languages;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Volo.Abp.Application.Services; using Volo.Abp.Application.Services;
using Volo.Abp.Domain.Repositories; using Volo.Abp.MultiTenancy;
using Volo.Abp.SettingManagement; using Volo.Abp.SettingManagement;
using Volo.Abp.Settings; using Volo.Abp.Settings;
using SettingDefinition = Sozsoft.Settings.Entities.SettingDefinition;
namespace Sozsoft.Settings; namespace Sozsoft.Settings;
@ -20,17 +19,20 @@ public class SettingUiAppService : ApplicationService, ISettingUiAppService
private readonly ISettingDefinitionManager settingDefinitionManager; private readonly ISettingDefinitionManager settingDefinitionManager;
private readonly ISettingManager settingManager; private readonly ISettingManager settingManager;
private readonly ErpSettingDefinitionManager ErpSettingDefinitionManager; private readonly ErpSettingDefinitionManager ErpSettingDefinitionManager;
private readonly ICurrentTenant currentTenant;
public SettingUiAppService( public SettingUiAppService(
ILanguageKeyIntegrationService languageKeyIntegrationService, ILanguageKeyIntegrationService languageKeyIntegrationService,
ISettingDefinitionManager settingDefinitionManager, ISettingDefinitionManager settingDefinitionManager,
ISettingManager settingManager, ISettingManager settingManager,
ErpSettingDefinitionManager ErpSettingDefinitionManager) ErpSettingDefinitionManager ErpSettingDefinitionManager,
ICurrentTenant currentTenant)
{ {
this.languageKeyIntegrationService = languageKeyIntegrationService; this.languageKeyIntegrationService = languageKeyIntegrationService;
this.settingDefinitionManager = settingDefinitionManager; this.settingDefinitionManager = settingDefinitionManager;
this.settingManager = settingManager; this.settingManager = settingManager;
this.ErpSettingDefinitionManager = ErpSettingDefinitionManager; this.ErpSettingDefinitionManager = ErpSettingDefinitionManager;
this.currentTenant = currentTenant;
} }
public virtual async Task<List<MainGroupedSettingDto>> GetListAsync() public virtual async Task<List<MainGroupedSettingDto>> GetListAsync()
@ -95,15 +97,18 @@ public class SettingUiAppService : ApplicationService, ISettingUiAppService
{ {
if (setting.Providers.IsNullOrEmpty()) if (setting.Providers.IsNullOrEmpty())
{ {
await settingManager.SetForCurrentUserAsync(setting.Name, value); if (currentTenant.Id.HasValue)
{
await settingManager.SetForCurrentTenantAsync(setting.Name, value);
} }
else else
{ {
if (setting.Providers.Any(p => p == UserSettingValueProvider.ProviderName)) await settingManager.SetGlobalAsync(setting.Name, value);
{
await settingManager.SetForCurrentUserAsync(setting.Name, value);
} }
else if (setting.Providers.Any(p => p == TenantSettingValueProvider.ProviderName)) }
else
{
if (setting.Providers.Any(p => p == TenantSettingValueProvider.ProviderName) && currentTenant.Id.HasValue)
{ {
await settingManager.SetForCurrentTenantAsync(setting.Name, value); await settingManager.SetForCurrentTenantAsync(setting.Name, value);
} }
@ -111,6 +116,10 @@ public class SettingUiAppService : ApplicationService, ISettingUiAppService
{ {
await settingManager.SetGlobalAsync(setting.Name, value); await settingManager.SetGlobalAsync(setting.Name, value);
} }
else if (setting.Providers.Any(p => p == UserSettingValueProvider.ProviderName))
{
await settingManager.SetForCurrentUserAsync(setting.Name, value);
}
} }
} }

View file

@ -1,6 +1,6 @@
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Application; using Volo.Abp.Application;
using Volo.Abp.AutoMapper; using Volo.Abp.Mapperly;
using Volo.Abp.Modularity; using Volo.Abp.Modularity;
using Volo.Abp.SettingManagement; using Volo.Abp.SettingManagement;
@ -10,18 +10,14 @@ namespace Sozsoft.Settings;
typeof(SettingsDomainModule), typeof(SettingsDomainModule),
typeof(SettingsApplicationContractsModule), typeof(SettingsApplicationContractsModule),
typeof(AbpDddApplicationModule), typeof(AbpDddApplicationModule),
typeof(AbpAutoMapperModule), typeof(AbpMapperlyModule),
typeof(AbpSettingManagementApplicationModule) typeof(AbpSettingManagementApplicationModule)
)] )]
public class SettingsApplicationModule : AbpModule public class SettingsApplicationModule : AbpModule
{ {
public override void ConfigureServices(ServiceConfigurationContext context) public override void ConfigureServices(ServiceConfigurationContext context)
{ {
context.Services.AddAutoMapperObjectMapper<SettingsApplicationModule>(); context.Services.AddMapperlyObjectMapper<SettingsApplicationModule>();
Configure<AbpAutoMapperOptions>(options =>
{
options.AddMaps<SettingsApplicationModule>(validate: true);
});
} }
} }

View file

@ -1,13 +0,0 @@
using AutoMapper;
using Sozsoft.Settings.Entities;
namespace Sozsoft.Settings;
public class SettingsAutoMapperProfile : Profile
{
public SettingsAutoMapperProfile()
{
CreateMap<SettingDefinition, SettingDefinitionDto>().ReverseMap();
}
}

View file

@ -0,0 +1,33 @@
using Sozsoft.Settings.Entities;
using Riok.Mapperly.Abstractions;
using Volo.Abp.Mapperly;
namespace Sozsoft.Settings;
[Mapper(RequiredMappingStrategy = RequiredMappingStrategy.Target)]
public partial class SettingDefinitionToSettingDefinitionDtoMapper : TwoWayMapperBase<SettingDefinition, SettingDefinitionDto>
{
public override partial SettingDefinitionDto Map(SettingDefinition source);
public override partial void Map(SettingDefinition source, SettingDefinitionDto destination);
public override void BeforeMap(SettingDefinition source)
{
}
public override void AfterMap(SettingDefinition source, SettingDefinitionDto destination)
{
}
public override partial SettingDefinition ReverseMap(SettingDefinitionDto destination);
public override partial void ReverseMap(SettingDefinitionDto destination, SettingDefinition source);
public override void BeforeReverseMap(SettingDefinitionDto destination)
{
}
public override void AfterReverseMap(SettingDefinitionDto destination, SettingDefinition source)
{
}
}

View file

@ -3,14 +3,14 @@
<Import Project="..\common.props" /> <Import Project="..\common.props" />
<PropertyGroup> <PropertyGroup>
<TargetFramework>net9.0</TargetFramework> <TargetFramework>net10.0</TargetFramework>
<RootNamespace>Sozsoft.Settings</RootNamespace> <RootNamespace>Sozsoft.Settings</RootNamespace>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Volo.Abp.AutoMapper" Version="9.0.2" /> <PackageReference Include="Volo.Abp.Mapperly" Version="10.0.0" />
<PackageReference Include="Volo.Abp.EntityFrameworkCore" Version="9.0.2" /> <PackageReference Include="Volo.Abp.EntityFrameworkCore" Version="10.0.0" />
<PackageReference Include="Volo.Abp.SettingManagement.Application" Version="9.0.2" /> <PackageReference Include="Volo.Abp.SettingManagement.Application" Version="10.0.0" />
<ProjectReference Include="..\..\Sozsoft.Languages\Sozsoft.Languages.Application.Contracts\Sozsoft.Languages.Application.Contracts.csproj" /> <ProjectReference Include="..\..\Sozsoft.Languages\Sozsoft.Languages.Application.Contracts\Sozsoft.Languages.Application.Contracts.csproj" />
<ProjectReference Include="..\Sozsoft.Settings.Application.Contracts\Sozsoft.Settings.Application.Contracts.csproj" /> <ProjectReference Include="..\Sozsoft.Settings.Application.Contracts\Sozsoft.Settings.Application.Contracts.csproj" />
<ProjectReference Include="..\Sozsoft.Settings.Domain\Sozsoft.Settings.Domain.csproj" /> <ProjectReference Include="..\Sozsoft.Settings.Domain\Sozsoft.Settings.Domain.csproj" />

View file

@ -3,19 +3,19 @@
<Import Project="..\common.props" /> <Import Project="..\common.props" />
<PropertyGroup> <PropertyGroup>
<TargetFramework>net9.0</TargetFramework> <TargetFramework>net10.0</TargetFramework>
<RootNamespace>Sozsoft.Settings</RootNamespace> <RootNamespace>Sozsoft.Settings</RootNamespace>
<GenerateEmbeddedFilesManifest>true</GenerateEmbeddedFilesManifest> <GenerateEmbeddedFilesManifest>false</GenerateEmbeddedFilesManifest>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Volo.Abp.SettingManagement.Domain.Shared" Version="9.0.2" /> <PackageReference Include="Volo.Abp.SettingManagement.Domain.Shared" Version="10.0.0" />
<PackageReference Include="Volo.Abp.Validation" Version="9.0.2" /> <PackageReference Include="Volo.Abp.Validation" Version="10.0.0" />
<PackageReference Include="Volo.Abp.Ddd.Domain.Shared" Version="9.0.2" /> <PackageReference Include="Volo.Abp.Ddd.Domain.Shared" Version="10.0.0" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="9.0.0" /> <PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="10.0.0" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View file

@ -28,22 +28,38 @@ public class SettingsDefinitionProvider : SettingDefinitionProvider
foreach (var item in settingDefinitions.OrderBy(a => a.Order)) foreach (var item in settingDefinitions.OrderBy(a => a.Order))
{ {
var iDescription = item.DescriptionKey.IsNullOrEmpty() ? null : L(item.DescriptionKey); var iDescription = item.DescriptionKey.IsNullOrEmpty() ? null : L(item.DescriptionKey);
var providers = item.Providers.IsNullOrEmpty()
? []
: item.Providers.Split(MultiValueDelimiter, StringSplitOptions.RemoveEmptyEntries);
var def = new Volo.Abp.Settings.SettingDefinition( var def = context.GetOrNull(item.Code);
if (def == null)
{
def = new Volo.Abp.Settings.SettingDefinition(
item.Code, item.DefaultValue, L(item.NameKey), iDescription, item.Code, item.DefaultValue, L(item.NameKey), iDescription,
item.IsVisibleToClients, item.IsInherited, item.IsEncrypted) item.IsVisibleToClients, item.IsInherited, item.IsEncrypted);
.WithProperty(SettingsConsts.MainGroup, item.MainGroupKey)
context.Add(def);
}
else
{
def.DefaultValue = item.DefaultValue;
def.DisplayName = L(item.NameKey);
def.Description = iDescription;
def.IsVisibleToClients = item.IsVisibleToClients;
def.IsInherited = item.IsInherited;
def.IsEncrypted = item.IsEncrypted;
def.Properties.Clear();
def.Providers.Clear();
}
def.Providers.AddRange(providers);
def.WithProperty(SettingsConsts.MainGroup, item.MainGroupKey)
.WithProperty(SettingsConsts.SubGroup, item.SubGroupKey) .WithProperty(SettingsConsts.SubGroup, item.SubGroupKey)
.WithProperty(SettingsConsts.DataType, item.DataType) .WithProperty(SettingsConsts.DataType, item.DataType)
.WithProperty(SettingsConsts.RequiredPermission, item.RequiredPermissionName) .WithProperty(SettingsConsts.RequiredPermission, item.RequiredPermissionName)
.WithProperty(SettingsConsts.SelectOptions, item.SelectOptions?.ToDictionary(x => x.Key, x => L(x.Value))); .WithProperty(SettingsConsts.SelectOptions, item.SelectOptions?.ToDictionary(x => x.Key, x => L(x.Value)));
if (!item.Providers.IsNullOrEmpty())
{
def.Providers.AddRange(item.Providers.Split(MultiValueDelimiter));
}
context.Add(def);
} }
} }

View file

@ -1,5 +1,6 @@
using Volo.Abp.Modularity; using Volo.Abp.Modularity;
using Volo.Abp.SettingManagement; using Volo.Abp.SettingManagement;
using Volo.Abp.Settings;
namespace Sozsoft.Settings; namespace Sozsoft.Settings;
@ -11,7 +12,10 @@ public class SettingsDomainModule : AbpModule
{ {
public override void ConfigureServices(ServiceConfigurationContext context) public override void ConfigureServices(ServiceConfigurationContext context)
{ {
Configure<AbpSettingOptions>(options =>
{
options.DefinitionProviders.Remove<SettingsDefinitionProvider>();
options.DefinitionProviders.Add<SettingsDefinitionProvider>();
});
} }
} }

View file

@ -3,13 +3,13 @@
<Import Project="..\common.props" /> <Import Project="..\common.props" />
<PropertyGroup> <PropertyGroup>
<TargetFramework>net9.0</TargetFramework> <TargetFramework>net10.0</TargetFramework>
<RootNamespace>Sozsoft.Settings</RootNamespace> <RootNamespace>Sozsoft.Settings</RootNamespace>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Volo.Abp.Authorization" Version="9.0.2" /> <PackageReference Include="Volo.Abp.Authorization" Version="10.0.0" />
<PackageReference Include="Volo.Abp.SettingManagement.Domain" Version="9.0.2" /> <PackageReference Include="Volo.Abp.SettingManagement.Domain" Version="10.0.0" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View file

@ -3,12 +3,12 @@
<Import Project="..\common.props" /> <Import Project="..\common.props" />
<PropertyGroup> <PropertyGroup>
<TargetFramework>net9.0</TargetFramework> <TargetFramework>net10.0</TargetFramework>
<RootNamespace>Sozsoft.Settings</RootNamespace> <RootNamespace>Sozsoft.Settings</RootNamespace>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Volo.Abp.SettingManagement.EntityFrameworkCore" Version="9.0.2" /> <PackageReference Include="Volo.Abp.SettingManagement.EntityFrameworkCore" Version="10.0.0" />
<ProjectReference Include="..\Sozsoft.Settings.Domain\Sozsoft.Settings.Domain.csproj" /> <ProjectReference Include="..\Sozsoft.Settings.Domain\Sozsoft.Settings.Domain.csproj" />
</ItemGroup> </ItemGroup>

View file

@ -7,11 +7,14 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="ConfigureAwait.Fody" Version="3.3.1" PrivateAssets="All" /> <PackageReference Include="ConfigureAwait.Fody" Version="3.4.0" PrivateAssets="All" />
<PackageReference Include="Fody" Version="6.5.3"> <PackageReference Include="Fody" Version="6.9.3">
<PrivateAssets>All</PrivateAssets> <PrivateAssets>All</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference> </PackageReference>
<PackageReference Include="MailKit" Version="4.16.0" />
<PackageReference Include="MimeKit" Version="4.16.0" />
<PackageReference Include="Scriban" Version="7.2.3" />
</ItemGroup> </ItemGroup>

View file

@ -4,7 +4,10 @@ public class DatabaseTableDto
{ {
public string SchemaName { get; set; } public string SchemaName { get; set; }
public string TableName { get; set; } public string TableName { get; set; }
public string FullName => $"{SchemaName}.{TableName}"; public string DataSourceType { get; set; }
public string FullName => DataSourceType == "Postgresql"
? $"\"{SchemaName}\".\"{TableName}\""
: $"[{SchemaName}].[{TableName}]";
} }
public class DatabaseColumnDto public class DatabaseColumnDto

View file

@ -22,6 +22,7 @@ public interface ISqlObjectManagerAppService : IApplicationService
// Database Metadata Operations // Database Metadata Operations
Task<List<DatabaseColumnDto>> GetTableColumnsAsync(string dataSourceCode, string schemaName, string tableName); Task<List<DatabaseColumnDto>> GetTableColumnsAsync(string dataSourceCode, string schemaName, string tableName);
Task<string> GetTableCreateScriptAsync(string dataSourceCode, string schemaName, string tableName);
/// <summary> /// <summary>
/// Gets the SQL definition/body of a native SQL Server object (Stored Procedure, View, or Function) /// Gets the SQL definition/body of a native SQL Server object (Stored Procedure, View, or Function)
@ -43,5 +44,15 @@ public interface ISqlObjectManagerAppService : IApplicationService
/// <summary> /// <summary>
/// Lists .sql files currently available under DbMigrator Seeds/SqlData. /// Lists .sql files currently available under DbMigrator Seeds/SqlData.
/// </summary> /// </summary>
Task<List<SqlDataFileDto>> GetSqlDataFilesAsync(); Task<List<SqlDataFileDto>> GetSqlDataFilesAsync(string dataDirectoryName = "SqlData", string relativePath = "");
/// <summary>
/// Reads a .sql seed file content from the selected data directory.
/// </summary>
Task<string> GetSqlDataFileContentAsync(string dataDirectoryName = "SqlData", string relativePath = "");
/// <summary>
/// Moves a SQL seed file between the selected data directory root and HostData.
/// </summary>
Task MoveSqlDataFileAsync(MoveSqlDataFileDto input);
} }

View file

@ -1,15 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\common.props" /> <Import Project="..\common.props" />
<PropertyGroup> <PropertyGroup>
<TargetFramework>net9.0</TargetFramework> <TargetFramework>net10.0</TargetFramework>
<RootNamespace>Sozsoft.SqlQueryManager</RootNamespace> <RootNamespace>Sozsoft.SqlQueryManager</RootNamespace>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Volo.Abp.Ddd.Application.Contracts" Version="9.0.2" /> <PackageReference Include="Volo.Abp.Ddd.Application.Contracts" Version="10.0.0" />
<PackageReference Include="Volo.Abp.Authorization" Version="9.0.2" /> <PackageReference Include="Volo.Abp.Authorization" Version="10.0.0" />
<ProjectReference Include="..\Sozsoft.SqlQueryManager.Domain.Shared\Sozsoft.SqlQueryManager.Domain.Shared.csproj" /> <ProjectReference Include="..\Sozsoft.SqlQueryManager.Domain.Shared\Sozsoft.SqlQueryManager.Domain.Shared.csproj" />
</ItemGroup> </ItemGroup>

View file

@ -5,5 +5,8 @@ namespace Sozsoft.SqlQueryManager.Application.Contracts;
public class SqlDataFileDto public class SqlDataFileDto
{ {
public string FileName { get; set; } = string.Empty; public string FileName { get; set; } = string.Empty;
public string Name { get; set; } = string.Empty;
public string RelativePath { get; set; } = string.Empty;
public bool IsDirectory { get; set; }
public DateTime CreatedAt { get; set; } public DateTime CreatedAt { get; set; }
} }

View file

@ -46,3 +46,10 @@ public class DeleteSqlDataFilesDto
/// </summary> /// </summary>
public List<string> FileNames { get; set; } = new(); public List<string> FileNames { get; set; } = new();
} }
public class MoveSqlDataFileDto
{
public string DataDirectoryName { get; set; } = string.Empty;
public string SourceRelativePath { get; set; } = string.Empty;
public string TargetRelativePath { get; set; } = string.Empty;
}

View file

@ -9,7 +9,10 @@ public class SqlNativeObjectDto
{ {
public string SchemaName { get; set; } = "dbo"; public string SchemaName { get; set; } = "dbo";
public string ObjectName { get; set; } = ""; public string ObjectName { get; set; } = "";
public string FullName => $"[{SchemaName}].[{ObjectName}]"; public string DataSourceType { get; set; } = "";
public string FullName => DataSourceType == "Postgresql"
? $"\"{SchemaName}\".\"{ObjectName}\""
: $"[{SchemaName}].[{ObjectName}]";
} }
/// <summary> /// <summary>

View file

@ -1,16 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\common.props" /> <Import Project="..\common.props" />
<PropertyGroup> <PropertyGroup>
<TargetFramework>net9.0</TargetFramework> <TargetFramework>net10.0</TargetFramework>
<RootNamespace>Sozsoft.SqlQueryManager</RootNamespace> <RootNamespace>Sozsoft.SqlQueryManager</RootNamespace>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Volo.Abp.AutoMapper" Version="9.0.2" /> <PackageReference Include="Volo.Abp.Mapperly" Version="10.0.0" />
<PackageReference Include="Volo.Abp.Ddd.Application" Version="9.0.2" /> <PackageReference Include="Volo.Abp.Ddd.Application" Version="10.0.0" />
<PackageReference Include="Volo.Abp.AspNetCore.Mvc" Version="9.0.2" /> <PackageReference Include="Volo.Abp.AspNetCore.Mvc" Version="10.0.0" />
<ProjectReference Include="..\Sozsoft.SqlQueryManager.Application.Contracts\Sozsoft.SqlQueryManager.Application.Contracts.csproj" /> <ProjectReference Include="..\Sozsoft.SqlQueryManager.Application.Contracts\Sozsoft.SqlQueryManager.Application.Contracts.csproj" />
<ProjectReference Include="..\Sozsoft.SqlQueryManager.Domain\Sozsoft.SqlQueryManager.Domain.csproj" /> <ProjectReference Include="..\Sozsoft.SqlQueryManager.Domain\Sozsoft.SqlQueryManager.Domain.csproj" />
</ItemGroup> </ItemGroup>

View file

@ -13,6 +13,8 @@ using Microsoft.Extensions.Logging;
using Volo.Abp.Application.Services; using Volo.Abp.Application.Services;
using Volo.Abp.MultiTenancy; using Volo.Abp.MultiTenancy;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using Sozsoft.Platform.Enums;
using Sozsoft.Platform.Queries;
namespace Sozsoft.SqlQueryManager.Application; namespace Sozsoft.SqlQueryManager.Application;
@ -43,6 +45,7 @@ public class SqlObjectManagerAppService : ApplicationService, ISqlObjectManagerA
private readonly ISqlExecutorService _sqlExecutorService; private readonly ISqlExecutorService _sqlExecutorService;
private readonly ISqlTemplateProvider _templateProvider; private readonly ISqlTemplateProvider _templateProvider;
private readonly IDataSourceManager _dataSourceManager;
private readonly ICurrentTenant _currentTenant; private readonly ICurrentTenant _currentTenant;
private readonly IHttpContextAccessor _httpContextAccessor; private readonly IHttpContextAccessor _httpContextAccessor;
private readonly IHostEnvironment _hostEnvironment; private readonly IHostEnvironment _hostEnvironment;
@ -51,6 +54,7 @@ public class SqlObjectManagerAppService : ApplicationService, ISqlObjectManagerA
public SqlObjectManagerAppService( public SqlObjectManagerAppService(
ISqlExecutorService sqlExecutorService, ISqlExecutorService sqlExecutorService,
ISqlTemplateProvider templateProvider, ISqlTemplateProvider templateProvider,
IDataSourceManager dataSourceManager,
ICurrentTenant currentTenant, ICurrentTenant currentTenant,
IHttpContextAccessor httpContextAccessor, IHttpContextAccessor httpContextAccessor,
IHostEnvironment hostEnvironment, IHostEnvironment hostEnvironment,
@ -58,6 +62,7 @@ public class SqlObjectManagerAppService : ApplicationService, ISqlObjectManagerA
{ {
_sqlExecutorService = sqlExecutorService; _sqlExecutorService = sqlExecutorService;
_templateProvider = templateProvider; _templateProvider = templateProvider;
_dataSourceManager = dataSourceManager;
_currentTenant = currentTenant; _currentTenant = currentTenant;
_httpContextAccessor = httpContextAccessor; _httpContextAccessor = httpContextAccessor;
_hostEnvironment = hostEnvironment; _hostEnvironment = hostEnvironment;
@ -90,11 +95,12 @@ public class SqlObjectManagerAppService : ApplicationService, ISqlObjectManagerA
{ {
ValidateTenantAccess(); ValidateTenantAccess();
var result = new SqlObjectExplorerDto(); var result = new SqlObjectExplorerDto();
var dataSourceType = await GetDataSourceTypeAsync(dataSourceCode);
result.Tables = await GetTablesAsync(dataSourceCode); result.Tables = await GetTablesAsync(dataSourceCode, dataSourceType);
result.Views = await GetNativeObjectsAsync(dataSourceCode, "V"); result.Views = await GetNativeObjectsAsync(dataSourceCode, dataSourceType, "V");
result.StoredProcedures = await GetNativeObjectsAsync(dataSourceCode, "P"); result.StoredProcedures = await GetNativeObjectsAsync(dataSourceCode, dataSourceType, "P");
result.Functions = await GetNativeObjectsAsync(dataSourceCode, "FN", "IF", "TF"); result.Functions = await GetNativeObjectsAsync(dataSourceCode, dataSourceType, "FN", "IF", "TF");
result.Templates = _templateProvider.GetAvailableQueryTemplates() result.Templates = _templateProvider.GetAvailableQueryTemplates()
.Select(t => new SqlTemplateDto .Select(t => new SqlTemplateDto
@ -109,20 +115,25 @@ public class SqlObjectManagerAppService : ApplicationService, ISqlObjectManagerA
return result; return result;
} }
private async Task<List<SqlNativeObjectDto>> GetNativeObjectsAsync(string dataSourceCode, params string[] objectTypes) private async Task<DataSourceTypeEnum> GetDataSourceTypeAsync(string dataSourceCode)
{ {
var typeList = string.Join(",", objectTypes.Select(t => $"'{t}'")); var dataSource = await _dataSourceManager.GetDataSourceAsync(_currentTenant.IsAvailable, dataSourceCode);
var query = $@" if (dataSource == null)
SELECT {
SCHEMA_NAME(o.schema_id) AS SchemaName, throw new Volo.Abp.UserFriendlyException($"Data source '{dataSourceCode}' was not found.");
o.name AS ObjectName }
FROM
sys.objects o return dataSource.DataSourceType;
WHERE }
o.type IN ({typeList})
AND o.is_ms_shipped = 0 private async Task<List<SqlNativeObjectDto>> GetNativeObjectsAsync(
ORDER BY string dataSourceCode,
SCHEMA_NAME(o.schema_id), o.name"; DataSourceTypeEnum dataSourceType,
params string[] objectTypes)
{
var query = dataSourceType == DataSourceTypeEnum.Postgresql
? BuildPostgreSqlNativeObjectsQuery(objectTypes)
: BuildSqlServerNativeObjectsQuery(objectTypes);
var result = await _sqlExecutorService.ExecuteQueryAsync(query, dataSourceCode); var result = await _sqlExecutorService.ExecuteQueryAsync(query, dataSourceCode);
@ -136,8 +147,9 @@ public class SqlObjectManagerAppService : ApplicationService, ISqlObjectManagerA
{ {
objects.Add(new SqlNativeObjectDto objects.Add(new SqlNativeObjectDto
{ {
SchemaName = dict["SchemaName"]?.ToString() ?? "dbo", SchemaName = GetDictionaryValue(dict, "SchemaName")?.ToString() ?? GetDefaultSchemaName(dataSourceType),
ObjectName = dict["ObjectName"]?.ToString() ?? "" ObjectName = GetDictionaryValue(dict, "ObjectName")?.ToString() ?? "",
DataSourceType = dataSourceType.ToString()
}); });
} }
} }
@ -146,9 +158,73 @@ public class SqlObjectManagerAppService : ApplicationService, ISqlObjectManagerA
return objects; return objects;
} }
private async Task<List<DatabaseTableDto>> GetTablesAsync(string dataSourceCode) private static string BuildSqlServerNativeObjectsQuery(params string[] objectTypes)
{ {
var query = @" var typeList = string.Join(",", objectTypes.Select(t => $"'{t}'"));
return $@"
SELECT
SCHEMA_NAME(o.schema_id) AS SchemaName,
o.name AS ObjectName
FROM
sys.objects o
WHERE
o.type IN ({typeList})
AND o.is_ms_shipped = 0
ORDER BY
SCHEMA_NAME(o.schema_id), o.name";
}
private static string BuildPostgreSqlNativeObjectsQuery(params string[] objectTypes)
{
var wantsViews = objectTypes.Contains("V");
var wantsProcedures = objectTypes.Contains("P");
var wantsFunctions = objectTypes.Any(t => t is "FN" or "IF" or "TF");
if (wantsViews)
{
return @"
SELECT
table_schema AS ""SchemaName"",
table_name AS ""ObjectName""
FROM information_schema.views
WHERE table_schema NOT IN ('pg_catalog', 'information_schema')
ORDER BY table_schema, table_name";
}
var proKinds = new List<string>();
if (wantsProcedures)
{
proKinds.Add("'p'");
}
if (wantsFunctions)
{
proKinds.Add("'f'");
}
return $@"
SELECT
n.nspname AS ""SchemaName"",
p.proname AS ""ObjectName""
FROM pg_proc p
INNER JOIN pg_namespace n ON n.oid = p.pronamespace
WHERE n.nspname NOT IN ('pg_catalog', 'information_schema')
AND p.prokind IN ({string.Join(",", proKinds)})
ORDER BY n.nspname, p.proname";
}
private async Task<List<DatabaseTableDto>> GetTablesAsync(string dataSourceCode, DataSourceTypeEnum dataSourceType)
{
var query = dataSourceType == DataSourceTypeEnum.Postgresql
? @"
SELECT
table_schema AS ""SchemaName"",
table_name AS ""TableName""
FROM information_schema.tables
WHERE table_type = 'BASE TABLE'
AND table_schema NOT IN ('pg_catalog', 'information_schema')
ORDER BY table_schema, table_name"
: @"
SELECT SELECT
SCHEMA_NAME(t.schema_id) AS SchemaName, SCHEMA_NAME(t.schema_id) AS SchemaName,
t.name AS TableName t.name AS TableName
@ -171,8 +247,9 @@ public class SqlObjectManagerAppService : ApplicationService, ISqlObjectManagerA
{ {
tables.Add(new DatabaseTableDto tables.Add(new DatabaseTableDto
{ {
SchemaName = dict["SchemaName"]?.ToString() ?? "dbo", SchemaName = GetDictionaryValue(dict, "SchemaName")?.ToString() ?? GetDefaultSchemaName(dataSourceType),
TableName = dict["TableName"]?.ToString() ?? "" TableName = GetDictionaryValue(dict, "TableName")?.ToString() ?? "",
DataSourceType = dataSourceType.ToString()
}); });
} }
} }
@ -229,12 +306,9 @@ public class SqlObjectManagerAppService : ApplicationService, ISqlObjectManagerA
public async Task<string> GetNativeObjectDefinitionAsync(string dataSourceCode, string schemaName, string objectName) public async Task<string> GetNativeObjectDefinitionAsync(string dataSourceCode, string schemaName, string objectName)
{ {
ValidateTenantAccess(); ValidateTenantAccess();
var query = @" var dataSourceType = await GetDataSourceTypeAsync(dataSourceCode);
SELECT OBJECT_DEFINITION(OBJECT_ID(@ObjectName)) AS Definition";
var fullObjectName = $"[{schemaName}].[{objectName}]";
var result = await _sqlExecutorService.ExecuteQueryAsync( var result = await _sqlExecutorService.ExecuteQueryAsync(
query.Replace("@ObjectName", $"'{fullObjectName}'"), BuildNativeObjectDefinitionQuery(dataSourceType, schemaName, objectName),
dataSourceCode); dataSourceCode);
if (result.Success && result.Data != null) if (result.Success && result.Data != null)
@ -243,15 +317,18 @@ public class SqlObjectManagerAppService : ApplicationService, ISqlObjectManagerA
if (dataList.Count > 0) if (dataList.Count > 0)
{ {
var row = dataList[0] as IDictionary<string, object>; var row = dataList[0] as IDictionary<string, object>;
if (row != null && row.ContainsKey("Definition")) if (row != null)
{ {
var definition = row["Definition"]?.ToString() ?? string.Empty; var definition = GetDictionaryValue(row, "Definition")?.ToString() ?? string.Empty;
// Always open object script as CREATE OR ALTER in editor. // Always open object script as CREATE OR ALTER in editor.
if (dataSourceType == DataSourceTypeEnum.Mssql)
{
definition = Regex.Replace( definition = Regex.Replace(
definition, definition,
@"^\s*(?:CREATE|ALTER)\s+(?:OR\s+ALTER\s+)?", @"^\s*(?:CREATE|ALTER)\s+(?:OR\s+ALTER\s+)?",
"CREATE OR ALTER ", "CREATE OR ALTER ",
RegexOptions.IgnoreCase); RegexOptions.IgnoreCase);
}
return definition; return definition;
} }
} }
@ -260,10 +337,59 @@ public class SqlObjectManagerAppService : ApplicationService, ISqlObjectManagerA
return string.Empty; return string.Empty;
} }
private static string BuildNativeObjectDefinitionQuery(
DataSourceTypeEnum dataSourceType,
string schemaName,
string objectName)
{
if (dataSourceType == DataSourceTypeEnum.Postgresql)
{
var schema = ToSqlLiteral(schemaName);
var name = ToSqlLiteral(objectName);
return $@"
SELECT ""Definition""
FROM (
SELECT pg_get_viewdef(c.oid, true) AS ""Definition""
FROM pg_class c
INNER JOIN pg_namespace n ON n.oid = c.relnamespace
WHERE n.nspname = {schema}
AND c.relname = {name}
AND c.relkind IN ('v', 'm')
UNION ALL
SELECT pg_get_functiondef(p.oid) AS ""Definition""
FROM pg_proc p
INNER JOIN pg_namespace n ON n.oid = p.pronamespace
WHERE n.nspname = {schema}
AND p.proname = {name}
AND p.prokind IN ('f', 'p')
) d
LIMIT 1";
}
var fullObjectName = $"[{schemaName.Replace("]", "]]")}].[{objectName.Replace("]", "]]")}]";
return $@"
SELECT OBJECT_DEFINITION(OBJECT_ID({ToSqlLiteral(fullObjectName)})) AS Definition";
}
public async Task<List<DatabaseColumnDto>> GetTableColumnsAsync(string dataSourceCode, string schemaName, string tableName) public async Task<List<DatabaseColumnDto>> GetTableColumnsAsync(string dataSourceCode, string schemaName, string tableName)
{ {
ValidateTenantAccess(); ValidateTenantAccess();
var query = $@" var dataSourceType = await GetDataSourceTypeAsync(dataSourceCode);
var query = dataSourceType == DataSourceTypeEnum.Postgresql
? $@"
SELECT
column_name AS ""ColumnName"",
COALESCE(NULLIF(udt_name, ''), data_type) AS ""DataType"",
CASE WHEN is_nullable = 'YES' THEN TRUE ELSE FALSE END AS ""IsNullable"",
character_maximum_length AS ""MaxLength""
FROM information_schema.columns
WHERE table_schema = {ToSqlLiteral(schemaName)}
AND table_name = {ToSqlLiteral(tableName)}
ORDER BY ordinal_position"
: $@"
SELECT SELECT
c.name AS ColumnName, c.name AS ColumnName,
TYPE_NAME(c.user_type_id) AS DataType, TYPE_NAME(c.user_type_id) AS DataType,
@ -274,8 +400,8 @@ public class SqlObjectManagerAppService : ApplicationService, ISqlObjectManagerA
INNER JOIN sys.tables t ON c.object_id = t.object_id INNER JOIN sys.tables t ON c.object_id = t.object_id
INNER JOIN sys.schemas s ON t.schema_id = s.schema_id INNER JOIN sys.schemas s ON t.schema_id = s.schema_id
WHERE WHERE
s.name = '{schemaName}' s.name = {ToSqlLiteral(schemaName)}
AND t.name = '{tableName}' AND t.name = {ToSqlLiteral(tableName)}
ORDER BY ORDER BY
c.column_id"; c.column_id";
@ -291,10 +417,10 @@ public class SqlObjectManagerAppService : ApplicationService, ISqlObjectManagerA
{ {
columns.Add(new DatabaseColumnDto columns.Add(new DatabaseColumnDto
{ {
ColumnName = dict["ColumnName"]?.ToString() ?? "", ColumnName = GetDictionaryValue(dict, "ColumnName")?.ToString() ?? "",
DataType = dict["DataType"]?.ToString() ?? "", DataType = GetDictionaryValue(dict, "DataType")?.ToString() ?? "",
IsNullable = dict["IsNullable"] is bool b && b, IsNullable = ToBoolean(GetDictionaryValue(dict, "IsNullable")),
MaxLength = dict["MaxLength"] != null ? int.Parse(dict["MaxLength"].ToString()) : null MaxLength = ToNullableInt(GetDictionaryValue(dict, "MaxLength"))
}); });
} }
} }
@ -303,6 +429,218 @@ public class SqlObjectManagerAppService : ApplicationService, ISqlObjectManagerA
return columns; return columns;
} }
[HttpGet("api/app/sql-object-manager/table-create-script")]
public async Task<string> GetTableCreateScriptAsync(string dataSourceCode, string schemaName, string tableName)
{
ValidateTenantAccess();
var dataSourceType = await GetDataSourceTypeAsync(dataSourceCode);
var result = await _sqlExecutorService.ExecuteQueryAsync(
BuildTableCreateScriptQuery(dataSourceType, schemaName, tableName),
dataSourceCode);
if (!result.Success || result.Data == null)
{
return string.Empty;
}
var row = result.Data.FirstOrDefault() as IDictionary<string, object>;
return GetDictionaryValue(row, "Script")?.ToString() ?? string.Empty;
}
private static string BuildTableCreateScriptQuery(
DataSourceTypeEnum dataSourceType,
string schemaName,
string tableName)
{
if (dataSourceType == DataSourceTypeEnum.Postgresql)
{
return BuildPostgreSqlTableCreateScriptQuery(schemaName, tableName);
}
return BuildSqlServerTableCreateScriptQuery(schemaName, tableName);
}
private static string BuildSqlServerTableCreateScriptQuery(string schemaName, string tableName)
{
var fullName = $"[{schemaName.Replace("]", "]]")}].[{tableName.Replace("]", "]]")}]";
var escapedFullName = ToSqlLiteral(fullName);
return $@"
DECLARE @ObjectId INT = OBJECT_ID({escapedFullName});
IF @ObjectId IS NULL
BEGIN
SELECT CAST('' AS NVARCHAR(MAX)) AS Script;
RETURN;
END;
;WITH cols AS
(
SELECT
c.column_id,
' ' + QUOTENAME(c.name) + ' ' +
CASE
WHEN t.name IN ('varchar', 'char', 'varbinary', 'binary') THEN
t.name + '(' + CASE WHEN c.max_length = -1 THEN 'MAX' ELSE CAST(c.max_length AS VARCHAR(10)) END + ')'
WHEN t.name IN ('nvarchar', 'nchar') THEN
t.name + '(' + CASE WHEN c.max_length = -1 THEN 'MAX' ELSE CAST(c.max_length / 2 AS VARCHAR(10)) END + ')'
WHEN t.name IN ('decimal', 'numeric') THEN
t.name + '(' + CAST(c.precision AS VARCHAR(10)) + ',' + CAST(c.scale AS VARCHAR(10)) + ')'
WHEN t.name IN ('datetime2', 'datetimeoffset', 'time') THEN
t.name + '(' + CAST(c.scale AS VARCHAR(10)) + ')'
ELSE t.name
END +
CASE
WHEN ic.object_id IS NOT NULL
THEN ' IDENTITY(' + CAST(ic.seed_value AS VARCHAR(30)) + ',' + CAST(ic.increment_value AS VARCHAR(30)) + ')'
ELSE ''
END +
CASE WHEN c.is_nullable = 1 THEN ' NULL' ELSE ' NOT NULL' END +
ISNULL(' DEFAULT ' + dc.definition, '') AS line
FROM sys.columns c
INNER JOIN sys.types t ON c.user_type_id = t.user_type_id
LEFT JOIN sys.identity_columns ic ON c.object_id = ic.object_id AND c.column_id = ic.column_id
LEFT JOIN sys.default_constraints dc ON c.default_object_id = dc.object_id
WHERE c.object_id = @ObjectId
),
pk AS
(
SELECT
' CONSTRAINT ' + QUOTENAME(k.name) + ' PRIMARY KEY ' +
CASE WHEN i.type = 1 THEN 'CLUSTERED' ELSE 'NONCLUSTERED' END +
CHAR(13) + CHAR(10) + ' (' + CHAR(13) + CHAR(10) +
(
SELECT ' ' + QUOTENAME(c.name) + CASE WHEN ic.is_descending_key = 1 THEN ' DESC' ELSE ' ASC' END + CHAR(13) + CHAR(10)
FROM sys.index_columns ic
INNER JOIN sys.columns c ON ic.object_id = c.object_id AND ic.column_id = c.column_id
WHERE ic.object_id = i.object_id
AND ic.index_id = i.index_id
AND ic.is_included_column = 0
ORDER BY ic.key_ordinal
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)') +
' )' AS line
FROM sys.key_constraints k
INNER JOIN sys.indexes i ON k.parent_object_id = i.object_id AND k.unique_index_id = i.index_id
WHERE k.parent_object_id = @ObjectId
AND k.type = 'PK'
)
SELECT
'IF OBJECT_ID(N''{fullName.Replace("'", "''")}'', ''U'') IS NULL' + CHAR(13) + CHAR(10) +
'BEGIN' + CHAR(13) + CHAR(10) +
' CREATE TABLE {fullName}' + CHAR(13) + CHAR(10) +
' (' + CHAR(13) + CHAR(10) +
STUFF(
(
SELECT ',' + CHAR(13) + CHAR(10) + line
FROM cols
ORDER BY column_id
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,3,'') +
ISNULL(
(
SELECT ',' + CHAR(13) + CHAR(10) + line
FROM pk
),
''
) + CHAR(13) + CHAR(10) + ' )' + CHAR(13) + CHAR(10) + 'END' + CHAR(13) + CHAR(10) + 'GO' AS Script;";
}
private static string BuildPostgreSqlTableCreateScriptQuery(string schemaName, string tableName)
{
return $@"
WITH cols AS (
SELECT
c.ordinal_position,
' ' || quote_ident(c.column_name) || ' ' ||
CASE
WHEN c.data_type = 'character varying' THEN 'varchar(' || c.character_maximum_length || ')'
WHEN c.data_type = 'character' THEN 'char(' || c.character_maximum_length || ')'
WHEN c.data_type = 'numeric' AND c.numeric_precision IS NOT NULL THEN 'numeric(' || c.numeric_precision || ',' || c.numeric_scale || ')'
WHEN c.data_type = 'USER-DEFINED' THEN c.udt_name
ELSE c.data_type
END ||
CASE WHEN c.is_nullable = 'NO' THEN ' NOT NULL' ELSE '' END ||
COALESCE(' DEFAULT ' || c.column_default, '') AS line
FROM information_schema.columns c
WHERE c.table_schema = {ToSqlLiteral(schemaName)}
AND c.table_name = {ToSqlLiteral(tableName)}
),
pk AS (
SELECT
' CONSTRAINT ' || quote_ident(tc.constraint_name) || ' PRIMARY KEY (' ||
string_agg(quote_ident(kcu.column_name), ', ' ORDER BY kcu.ordinal_position) || ')' AS line
FROM information_schema.table_constraints tc
JOIN information_schema.key_column_usage kcu
ON tc.constraint_name = kcu.constraint_name
AND tc.table_schema = kcu.table_schema
AND tc.table_name = kcu.table_name
WHERE tc.constraint_type = 'PRIMARY KEY'
AND tc.table_schema = {ToSqlLiteral(schemaName)}
AND tc.table_name = {ToSqlLiteral(tableName)}
GROUP BY tc.constraint_name
)
SELECT
'CREATE TABLE IF NOT EXISTS ' || quote_ident({ToSqlLiteral(schemaName)}) || '.' || quote_ident({ToSqlLiteral(tableName)}) || E'\n(\n' ||
string_agg(line, E',\n' ORDER BY sort_order) ||
E'\n);' AS ""Script""
FROM (
SELECT ordinal_position AS sort_order, line FROM cols
UNION ALL
SELECT 100000 AS sort_order, line FROM pk
) s;";
}
private static object GetDictionaryValue(IDictionary<string, object> row, string key)
{
if (row == null)
{
return null;
}
if (row.TryGetValue(key, out var value))
{
return value;
}
var match = row.FirstOrDefault(x => string.Equals(x.Key, key, StringComparison.OrdinalIgnoreCase));
return string.IsNullOrEmpty(match.Key) ? null : match.Value;
}
private static string GetDefaultSchemaName(DataSourceTypeEnum dataSourceType)
{
return dataSourceType == DataSourceTypeEnum.Postgresql ? "public" : "dbo";
}
private static string ToSqlLiteral(string value)
{
return $"'{(value ?? string.Empty).Replace("'", "''")}'";
}
private static bool ToBoolean(object value)
{
return value switch
{
bool boolValue => boolValue,
short shortValue => shortValue != 0,
int intValue => intValue != 0,
long longValue => longValue != 0,
_ => bool.TryParse(value?.ToString(), out var parsed) && parsed
};
}
private static int? ToNullableInt(object value)
{
if (value == null)
{
return null;
}
return int.TryParse(value.ToString(), out var parsed) ? parsed : null;
}
private SqlQueryExecutionResultDto MapExecutionResult(SqlExecutionResult result, bool isDeployed = false) private SqlQueryExecutionResultDto MapExecutionResult(SqlExecutionResult result, bool isDeployed = false)
{ {
return new SqlQueryExecutionResultDto return new SqlQueryExecutionResultDto
@ -617,27 +955,48 @@ public class SqlObjectManagerAppService : ApplicationService, ISqlObjectManagerA
} }
[HttpGet("api/app/sql-object-manager/sql-data-files")] [HttpGet("api/app/sql-object-manager/sql-data-files")]
public Task<List<SqlDataFileDto>> GetSqlDataFilesAsync() public Task<List<SqlDataFileDto>> GetSqlDataFilesAsync(
[FromQuery] string dataDirectoryName = "SqlData",
[FromQuery] string relativePath = "")
{ {
ValidateTenantAccess(); ValidateTenantAccess();
try try
{ {
var outputPath = ResolveSqlDataOutputPath(); var rootPath = ResolveSqlDataOutputPath(dataDirectoryName);
var outputPath = ResolveSqlDataChildPath(rootPath, relativePath);
if (!Directory.Exists(outputPath)) if (!Directory.Exists(outputPath))
return Task.FromResult(new List<SqlDataFileDto>()); return Task.FromResult(new List<SqlDataFileDto>());
var directories = Directory.GetDirectories(outputPath, "*", SearchOption.TopDirectoryOnly)
.Where(d => string.Equals(Path.GetFileName(d), "HostData", StringComparison.OrdinalIgnoreCase))
.Select(d => new SqlDataFileDto
{
FileName = Path.GetFileName(d)!,
Name = Path.GetFileName(d)!,
RelativePath = BuildSqlDataRelativePath(relativePath, Path.GetFileName(d)!),
IsDirectory = true,
CreatedAt = Directory.GetCreationTime(d)
});
var files = Directory.GetFiles(outputPath, "*.sql", SearchOption.TopDirectoryOnly) var files = Directory.GetFiles(outputPath, "*.sql", SearchOption.TopDirectoryOnly)
.Select(f => new SqlDataFileDto .Select(f => new SqlDataFileDto
{ {
FileName = Path.GetFileName(f)!, FileName = Path.GetFileName(f)!,
Name = Path.GetFileName(f)!,
RelativePath = BuildSqlDataRelativePath(relativePath, Path.GetFileName(f)!),
IsDirectory = false,
CreatedAt = File.GetCreationTime(f) CreatedAt = File.GetCreationTime(f)
}) })
.Where(x => !string.IsNullOrWhiteSpace(x.FileName)) .Where(x => !string.IsNullOrWhiteSpace(x.Name));
.OrderBy(x => x.FileName, StringComparer.OrdinalIgnoreCase)
var entries = directories
.Concat(files)
.OrderByDescending(x => x.IsDirectory)
.ThenBy(x => x.Name, StringComparer.OrdinalIgnoreCase)
.ToList(); .ToList();
return Task.FromResult(files); return Task.FromResult(entries);
} }
catch (Exception ex) catch (Exception ex)
{ {
@ -646,24 +1005,140 @@ public class SqlObjectManagerAppService : ApplicationService, ISqlObjectManagerA
} }
} }
[HttpGet("api/app/sql-object-manager/sql-data-file-content")]
public async Task<string> GetSqlDataFileContentAsync(
[FromQuery] string dataDirectoryName = "SqlData",
[FromQuery] string relativePath = "")
{
ValidateTenantAccess();
var rootPath = ResolveSqlDataOutputPath(dataDirectoryName);
var filePath = ResolveSqlDataChildPath(rootPath, relativePath);
if (!File.Exists(filePath))
throw new Volo.Abp.UserFriendlyException("SQL seed file was not found.");
if (!string.Equals(Path.GetExtension(filePath), ".sql", StringComparison.OrdinalIgnoreCase))
throw new Volo.Abp.UserFriendlyException("Only .sql files can be previewed.");
return await File.ReadAllTextAsync(filePath);
}
[HttpPost("api/app/sql-object-manager/move-sql-data-file")]
public Task MoveSqlDataFileAsync(MoveSqlDataFileDto input)
{
ValidateTenantAccess();
if (input == null)
throw new Volo.Abp.UserFriendlyException("Invalid move request.");
var rootPath = ResolveSqlDataOutputPath(input.DataDirectoryName);
var sourcePath = ResolveSqlDataChildPath(rootPath, input.SourceRelativePath);
var targetPath = ResolveSqlDataChildPath(rootPath, input.TargetRelativePath);
if (!File.Exists(sourcePath))
throw new Volo.Abp.UserFriendlyException("Source file was not found.");
if (!string.Equals(Path.GetExtension(sourcePath), ".sql", StringComparison.OrdinalIgnoreCase) ||
!string.Equals(Path.GetExtension(targetPath), ".sql", StringComparison.OrdinalIgnoreCase))
{
throw new Volo.Abp.UserFriendlyException("Only .sql files can be moved.");
}
Directory.CreateDirectory(Path.GetDirectoryName(targetPath)!);
if (File.Exists(targetPath))
throw new Volo.Abp.UserFriendlyException("A file with the same name already exists in the target folder.");
File.Move(sourcePath, targetPath);
_logger.LogInformation("SQL seed file moved from {SourcePath} to {TargetPath}", sourcePath, targetPath);
return Task.CompletedTask;
}
private string ResolveSqlDataOutputPath() private string ResolveSqlDataOutputPath()
{
return ResolveSqlDataOutputPath("SqlData");
}
private string ResolveSqlDataOutputPath(string dataDirectoryName)
{ {
const string dbMigratorName = "Sozsoft.Platform.DbMigrator"; const string dbMigratorName = "Sozsoft.Platform.DbMigrator";
var safeDirectoryName = NormalizeSqlDataDirectoryName(dataDirectoryName);
var dir = new DirectoryInfo(_hostEnvironment.ContentRootPath); var dir = new DirectoryInfo(_hostEnvironment.ContentRootPath);
while (dir != null) while (dir != null)
{ {
var candidate = Path.Combine(dir.FullName, "src", dbMigratorName, "Seeds"); var candidate = Path.Combine(dir.FullName, "src", dbMigratorName, "Seeds");
if (Directory.Exists(candidate)) if (Directory.Exists(candidate))
return Path.Combine(candidate, "SqlData"); return Path.Combine(candidate, safeDirectoryName);
candidate = Path.Combine(dir.FullName, dbMigratorName, "Seeds"); candidate = Path.Combine(dir.FullName, dbMigratorName, "Seeds");
if (Directory.Exists(candidate)) if (Directory.Exists(candidate))
return Path.Combine(candidate, "SqlData"); return Path.Combine(candidate, safeDirectoryName);
dir = dir.Parent; dir = dir.Parent;
} }
return Path.Combine(_hostEnvironment.ContentRootPath, "Seeds", "SqlData"); return Path.Combine(_hostEnvironment.ContentRootPath, "Seeds", safeDirectoryName);
}
private static string NormalizeSqlDataDirectoryName(string dataDirectoryName)
{
return string.Equals(dataDirectoryName, "PostgresData", StringComparison.OrdinalIgnoreCase)
? "PostgresData"
: "SqlData";
}
private static string ResolveSqlDataChildPath(string rootPath, string relativePath)
{
var normalized = NormalizeSqlDataRelativePath(relativePath);
var fullPath = Path.GetFullPath(Path.Combine(rootPath, normalized));
var fullRoot = Path.GetFullPath(rootPath);
var fullRootWithSeparator = fullRoot.EndsWith(Path.DirectorySeparatorChar)
? fullRoot
: fullRoot + Path.DirectorySeparatorChar;
if (!string.Equals(fullPath, fullRoot, StringComparison.OrdinalIgnoreCase) &&
!fullPath.StartsWith(fullRootWithSeparator, StringComparison.OrdinalIgnoreCase))
{
throw new Volo.Abp.UserFriendlyException("Invalid path.");
}
return fullPath;
}
private static string NormalizeSqlDataRelativePath(string relativePath)
{
if (string.IsNullOrWhiteSpace(relativePath))
return string.Empty;
var normalized = relativePath.Replace('\\', '/').Trim('/');
var parts = normalized.Split('/', StringSplitOptions.RemoveEmptyEntries);
if (parts.Length == 0)
return string.Empty;
if (parts.Any(p => p == "." || p == ".." || p.IndexOfAny(Path.GetInvalidFileNameChars()) >= 0))
throw new Volo.Abp.UserFriendlyException("Invalid path.");
var isRootFile = parts.Length == 1 && parts[0].EndsWith(".sql", StringComparison.OrdinalIgnoreCase);
var isHostDataFolder = parts.Length == 1 && string.Equals(parts[0], "HostData", StringComparison.OrdinalIgnoreCase);
var isHostDataFile = parts.Length == 2 &&
string.Equals(parts[0], "HostData", StringComparison.OrdinalIgnoreCase) &&
parts[1].EndsWith(".sql", StringComparison.OrdinalIgnoreCase);
if (!isRootFile && !isHostDataFolder && !isHostDataFile)
throw new Volo.Abp.UserFriendlyException("Invalid path.");
return Path.Combine(parts);
}
private static string BuildSqlDataRelativePath(string parentRelativePath, string name)
{
if (string.IsNullOrWhiteSpace(parentRelativePath))
return name;
return $"{parentRelativePath.Trim('/', '\\')}/{name}";
} }
} }

View file

@ -1,6 +1,6 @@
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Application; using Volo.Abp.Application;
using Volo.Abp.AutoMapper; using Volo.Abp.Mapperly;
using Volo.Abp.Modularity; using Volo.Abp.Modularity;
namespace Sozsoft.SqlQueryManager; namespace Sozsoft.SqlQueryManager;
@ -9,17 +9,12 @@ namespace Sozsoft.SqlQueryManager;
typeof(SqlQueryManagerDomainModule), typeof(SqlQueryManagerDomainModule),
typeof(SqlQueryManagerApplicationContractsModule), typeof(SqlQueryManagerApplicationContractsModule),
typeof(AbpDddApplicationModule), typeof(AbpDddApplicationModule),
typeof(AbpAutoMapperModule) typeof(AbpMapperlyModule)
)] )]
public class SqlQueryManagerApplicationModule : AbpModule public class SqlQueryManagerApplicationModule : AbpModule
{ {
public override void ConfigureServices(ServiceConfigurationContext context) public override void ConfigureServices(ServiceConfigurationContext context)
{ {
context.Services.AddAutoMapperObjectMapper<SqlQueryManagerApplicationModule>(); context.Services.AddMapperlyObjectMapper<SqlQueryManagerApplicationModule>();
Configure<AbpAutoMapperOptions>(options =>
{
options.AddMaps<SqlQueryManagerApplicationModule>(validate: true);
});
} }
} }

View file

@ -1,12 +0,0 @@
using AutoMapper;
namespace Sozsoft.SqlQueryManager.Application;
// No entity-to-DTO mappings needed; SQL objects are no longer persisted in this module.
public class SqlQueryManagerAutoMapperProfile : Profile
{
public SqlQueryManagerAutoMapperProfile()
{
// intentionally empty
}
}

View file

@ -0,0 +1 @@
namespace Sozsoft.SqlQueryManager.Application;

View file

@ -1,20 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\common.props" /> <Import Project="..\common.props" />
<PropertyGroup> <PropertyGroup>
<TargetFramework>net9.0</TargetFramework> <TargetFramework>net10.0</TargetFramework>
<GenerateEmbeddedFilesManifest>true</GenerateEmbeddedFilesManifest> <GenerateEmbeddedFilesManifest>false</GenerateEmbeddedFilesManifest>
<RootNamespace>Sozsoft.SqlQueryManager</RootNamespace> <RootNamespace>Sozsoft.SqlQueryManager</RootNamespace>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Volo.Abp.Ddd.Domain.Shared" Version="9.0.2" /> <PackageReference Include="Volo.Abp.Ddd.Domain.Shared" Version="10.0.0" />
<PackageReference Include="Volo.Abp.Validation" Version="9.0.2" /> <PackageReference Include="Volo.Abp.Validation" Version="10.0.0" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="9.0.0" /> <PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="10.0.0" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View file

@ -5,6 +5,7 @@ using System.Linq;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Threading.Tasks; using System.Threading.Tasks;
using Sozsoft.Platform.DynamicData; using Sozsoft.Platform.DynamicData;
using Sozsoft.Platform.Enums;
using Sozsoft.Platform.Queries; using Sozsoft.Platform.Queries;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Volo.Abp; using Volo.Abp;
@ -38,14 +39,25 @@ public class SqlExecutorService : DomainService, ISqlExecutorService
.WithData("DataSourceCode", dataSourceCode); .WithData("DataSourceCode", dataSourceCode);
} }
// Get appropriate repository based on database type var repositoryKey = dataSource.DataSourceType switch
// For now, using MS SQL Server repository {
var repository = _serviceProvider.GetKeyedService<IDynamicDataRepository>("Ms"); DataSourceTypeEnum.Mssql => "Ms",
DataSourceTypeEnum.Postgresql => "Pg",
_ => null
};
if (repositoryKey == null)
{
throw new BusinessException("SqlQueryManager:DataSourceTypeNotSupported")
.WithData("DatabaseType", dataSource.DataSourceType);
}
var repository = _serviceProvider.GetKeyedService<IDynamicDataRepository>(repositoryKey);
if (repository == null) if (repository == null)
{ {
throw new BusinessException("SqlQueryManager:RepositoryNotFound") throw new BusinessException("SqlQueryManager:RepositoryNotFound")
.WithData("DatabaseType", "Ms"); .WithData("DatabaseType", repositoryKey);
} }
return repository; return repository;

View file

@ -1,14 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\common.props" /> <Import Project="..\common.props" />
<PropertyGroup> <PropertyGroup>
<TargetFramework>net9.0</TargetFramework> <TargetFramework>net10.0</TargetFramework>
<RootNamespace>Sozsoft.SqlQueryManager</RootNamespace> <RootNamespace>Sozsoft.SqlQueryManager</RootNamespace>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Volo.Abp.Ddd.Domain" Version="9.0.2" /> <PackageReference Include="Volo.Abp.Ddd.Domain" Version="10.0.0" />
<ProjectReference Include="..\Sozsoft.SqlQueryManager.Domain.Shared\Sozsoft.SqlQueryManager.Domain.Shared.csproj" /> <ProjectReference Include="..\Sozsoft.SqlQueryManager.Domain.Shared\Sozsoft.SqlQueryManager.Domain.Shared.csproj" />
<ProjectReference Include="..\..\..\src\Sozsoft.Platform.Domain\Sozsoft.Platform.Domain.csproj" /> <ProjectReference Include="..\..\..\src\Sozsoft.Platform.Domain\Sozsoft.Platform.Domain.csproj" />
</ItemGroup> </ItemGroup>

View file

@ -1,14 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\common.props" /> <Import Project="..\common.props" />
<PropertyGroup> <PropertyGroup>
<TargetFramework>net9.0</TargetFramework> <TargetFramework>net10.0</TargetFramework>
<RootNamespace>Sozsoft.SqlQueryManager</RootNamespace> <RootNamespace>Sozsoft.SqlQueryManager</RootNamespace>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Volo.Abp.EntityFrameworkCore" Version="9.0.2" /> <PackageReference Include="Volo.Abp.EntityFrameworkCore" Version="10.0.0" />
<ProjectReference Include="..\Sozsoft.SqlQueryManager.Domain\Sozsoft.SqlQueryManager.Domain.csproj" /> <ProjectReference Include="..\Sozsoft.SqlQueryManager.Domain\Sozsoft.SqlQueryManager.Domain.csproj" />
</ItemGroup> </ItemGroup>

View file

@ -7,11 +7,14 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="ConfigureAwait.Fody" Version="3.3.1" PrivateAssets="All" /> <PackageReference Include="ConfigureAwait.Fody" Version="3.4.0" PrivateAssets="All" />
<PackageReference Include="Fody" Version="6.5.3"> <PackageReference Include="Fody" Version="6.9.3">
<PrivateAssets>All</PrivateAssets> <PrivateAssets>All</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference> </PackageReference>
<PackageReference Include="MailKit" Version="4.16.0" />
<PackageReference Include="MimeKit" Version="4.16.0" />
<PackageReference Include="Scriban" Version="7.2.3" />
</ItemGroup> </ItemGroup>

View file

@ -5,11 +5,11 @@ namespace Sozsoft.Platform.AuditLogs;
public class AuditLogActionDto : EntityDto<Guid> public class AuditLogActionDto : EntityDto<Guid>
{ {
public virtual Guid AuditLogId { get; protected set; } public virtual Guid AuditLogId { get; set; }
public virtual string ServiceName { get; protected set; } public virtual string ServiceName { get; set; }
public virtual string MethodName { get; protected set; } public virtual string MethodName { get; set; }
public virtual string Parameters { get; protected set; } public virtual string Parameters { get; set; }
public virtual DateTime ExecutionTime { get; protected set; } public virtual DateTime ExecutionTime { get; set; }
public virtual int ExecutionDuration { get; protected set; } public virtual int ExecutionDuration { get; set; }
} }

View file

@ -13,24 +13,24 @@ public class AuditLogDto : EntityDto<Guid>
} }
public string ApplicationName { get; set; } public string ApplicationName { get; set; }
public Guid? UserId { get; protected set; } public Guid? UserId { get; set; }
public string UserName { get; protected set; } public string UserName { get; set; }
public Guid? TenantId { get; protected set; } public Guid? TenantId { get; set; }
public string TenantName { get; protected set; } public string TenantName { get; set; }
public DateTime ExecutionTime { get; protected set; } public DateTime ExecutionTime { get; set; }
public int ExecutionDuration { get; protected set; } public int ExecutionDuration { get; set; }
public string ClientIpAddress { get; protected set; } public string ClientIpAddress { get; set; }
public string ClientName { get; protected set; } public string ClientName { get; set; }
public string ClientId { get; set; } public string ClientId { get; set; }
public string CorrelationId { get; set; } public string CorrelationId { get; set; }
public string BrowserInfo { get; protected set; } public string BrowserInfo { get; set; }
public string HttpMethod { get; protected set; } public string HttpMethod { get; set; }
public string Url { get; protected set; } public string Url { get; set; }
public string Exceptions { get; protected set; } public string Exceptions { get; set; }
public string Comments { get; protected set; } public string Comments { get; set; }
public int? HttpStatusCode { get; set; } public int? HttpStatusCode { get; set; }
public ICollection<EntityChangeDto> EntityChanges { get; protected set; } public ICollection<EntityChangeDto> EntityChanges { get; set; }
public ICollection<AuditLogActionDto> Actions { get; protected set; } public ICollection<AuditLogActionDto> Actions { get; set; }
public int? EntityChangeCount { get; set; } public int? EntityChangeCount { get; set; }

View file

@ -0,0 +1,9 @@
using Volo.Abp.Application.Dtos;
namespace Sozsoft.Platform.AuditLogs;
public class AuditLogListRequestDto : PagedAndSortedResultRequestDto
{
public string ListFormCode { get; set; }
public string EntityId { get; set; }
}

View file

@ -12,12 +12,12 @@ public class EntityChangeDto : EntityDto<Guid>
PropertyChanges = new List<EntityPropertyChangeDto>(); PropertyChanges = new List<EntityPropertyChangeDto>();
} }
public virtual Guid AuditLogId { get; protected set; } public virtual Guid AuditLogId { get; set; }
public virtual DateTime ChangeTime { get; protected set; } public virtual DateTime ChangeTime { get; set; }
public virtual EntityChangeType ChangeType { get; protected set; } public virtual EntityChangeType ChangeType { get; set; }
public virtual Guid? EntityTenantId { get; protected set; } public virtual Guid? EntityTenantId { get; set; }
public virtual string EntityId { get; protected set; } public virtual string EntityId { get; set; }
public virtual string EntityTypeFullName { get; protected set; } public virtual string EntityTypeFullName { get; set; }
public virtual ICollection<EntityPropertyChangeDto> PropertyChanges { get; protected set; } public virtual ICollection<EntityPropertyChangeDto> PropertyChanges { get; set; }
} }

View file

@ -5,10 +5,10 @@ namespace Sozsoft.Platform.AuditLogs;
public class EntityPropertyChangeDto : EntityDto<Guid> public class EntityPropertyChangeDto : EntityDto<Guid>
{ {
public virtual Guid EntityChangeId { get; protected set; } public virtual Guid EntityChangeId { get; set; }
public virtual string NewValue { get; protected set; } public virtual string NewValue { get; set; }
public virtual string OriginalValue { get; protected set; } public virtual string OriginalValue { get; set; }
public virtual string PropertyName { get; protected set; } public virtual string PropertyName { get; set; }
public virtual string PropertyTypeFullName { get; protected set; } public virtual string PropertyTypeFullName { get; set; }
} }

View file

@ -0,0 +1,11 @@
using System;
using Volo.Abp.Content;
namespace Sozsoft.Platform.Identity.Dto;
public class UserAvatarUpdateInput
{
public Guid UserId { get; set; }
public IRemoteStreamContent Avatar { get; set; }
}

View file

@ -8,16 +8,16 @@ public class AnnouncementDto : FullAuditedEntityDto<Guid>
{ {
public Guid? TenantId { get; set; } public Guid? TenantId { get; set; }
public string Title { get; set; } public string Title { get; set; } = string.Empty;
public string Excerpt { get; set; } public string Excerpt { get; set; } = string.Empty;
public string Content { get; set; } public string Content { get; set; } = string.Empty;
public string ImageUrl { get; set; } public string ImageUrl { get; set; } = string.Empty;
public string Category { get; set; } public string Category { get; set; } = string.Empty;
public Guid? UserId { get; set; } public Guid? UserId { get; set; }
public UserInfoViewModel User { get; set; } public UserInfoViewModel? User { get; set; }
public DateTime PublishDate { get; set; } public DateTime PublishDate { get; set; }
public DateTime? ExpiryDate { get; set; } public DateTime? ExpiryDate { get; set; }
public bool IsPinned { get; set; } public bool IsPinned { get; set; }
public int ViewCount { get; set; } public int ViewCount { get; set; }
public string Attachments { get; set; } public string Attachments { get; set; } = string.Empty;
} }

View file

@ -9,7 +9,7 @@ public class SocialPostDto : FullAuditedEntityDto<Guid>
{ {
public Guid? UserId { get; set; } public Guid? UserId { get; set; }
public UserInfoViewModel? User { get; set; } public UserInfoViewModel? User { get; set; }
public string Content { get; set; } public string Content { get; set; } = string.Empty;
public int LikeCount { get; set; } public int LikeCount { get; set; }
public bool IsLiked { get; set; } public bool IsLiked { get; set; }
@ -17,14 +17,14 @@ public class SocialPostDto : FullAuditedEntityDto<Guid>
public SocialLocationDto? Location { get; set; } public SocialLocationDto? Location { get; set; }
public SocialMediaDto? Media { get; set; } public SocialMediaDto? Media { get; set; }
public List<SocialCommentDto> Comments { get; set; } public List<SocialCommentDto> Comments { get; set; } = [];
public List<SocialLikeDto> Likes { get; set; } public List<SocialLikeDto> Likes { get; set; } = [];
} }
public class SocialLocationDto : FullAuditedEntityDto<Guid> public class SocialLocationDto : FullAuditedEntityDto<Guid>
{ {
public Guid SocialPostId { get; set; } public Guid SocialPostId { get; set; }
public string Name { get; set; } public string Name { get; set; } = string.Empty;
public string? Address { get; set; } public string? Address { get; set; }
public double? Lat { get; set; } public double? Lat { get; set; }
public double? Lng { get; set; } public double? Lng { get; set; }
@ -34,8 +34,8 @@ public class SocialLocationDto : FullAuditedEntityDto<Guid>
public class SocialMediaDto : FullAuditedEntityDto<Guid> public class SocialMediaDto : FullAuditedEntityDto<Guid>
{ {
public Guid SocialPostId { get; set; } public Guid SocialPostId { get; set; }
public string Type { get; set; } // image | video | poll public string Type { get; set; } = string.Empty; // image | video | poll
public string[] Urls { get; set; } public string[] Urls { get; set; } = [];
// Poll Fields // Poll Fields
public string? PollQuestion { get; set; } public string? PollQuestion { get; set; }
@ -43,13 +43,13 @@ public class SocialMediaDto : FullAuditedEntityDto<Guid>
public DateTime? PollEndsAt { get; set; } public DateTime? PollEndsAt { get; set; }
public string? PollUserVoteId { get; set; } public string? PollUserVoteId { get; set; }
public List<SocialPollOptionDto> PollOptions { get; set; } public List<SocialPollOptionDto> PollOptions { get; set; } = [];
} }
public class SocialPollOptionDto : FullAuditedEntityDto<Guid> public class SocialPollOptionDto : FullAuditedEntityDto<Guid>
{ {
public Guid SocialMediaId { get; set; } public Guid SocialMediaId { get; set; }
public string Text { get; set; } public string Text { get; set; } = string.Empty;
public int Votes { get; set; } public int Votes { get; set; }
} }
@ -58,7 +58,7 @@ public class SocialCommentDto : FullAuditedEntityDto<Guid>
public Guid SocialPostId { get; set; } public Guid SocialPostId { get; set; }
public Guid? UserId { get; set; } public Guid? UserId { get; set; }
public UserInfoViewModel? User { get; set; } public UserInfoViewModel? User { get; set; }
public string Content { get; set; } public string Content { get; set; } = string.Empty;
} }
public class SocialLikeDto : FullAuditedEntityDto<Guid> public class SocialLikeDto : FullAuditedEntityDto<Guid>

View file

@ -5,6 +5,7 @@ namespace Sozsoft.Platform.ListForms;
public class WorkflowDto public class WorkflowDto
{ {
public string ApprovalUserFieldName { get; set; } public string ApprovalUserFieldName { get; set; }
public bool IsFilterUserName { get; set; }
public string ApprovalDateFieldName { get; set; } public string ApprovalDateFieldName { get; set; }
public string ApprovalStatusFieldName { get; set; } public string ApprovalStatusFieldName { get; set; }
public string ApprovalDescriptionFieldName { get; set; } public string ApprovalDescriptionFieldName { get; set; }

View file

@ -39,6 +39,7 @@ public class ListFormWizardDto
public string PermissionGroupName { get; set; } public string PermissionGroupName { get; set; }
public string MenuParentCode { get; set; } public string MenuParentCode { get; set; }
public string MenuParentIcon { get; set; }
public string MenuIcon { get; set; } public string MenuIcon { get; set; }
public string DataSourceCode { get; set; } public string DataSourceCode { get; set; }
public string DataSourceConnectionString { get; set; } public string DataSourceConnectionString { get; set; }
@ -68,5 +69,8 @@ public class ListFormWizardDto
public string SchedulerEndDateExpr { get; set; } public string SchedulerEndDateExpr { get; set; }
public List<WizardColumnGroupInputDto> Groups { get; set; } = new(); public List<WizardColumnGroupInputDto> Groups { get; set; } = new();
public List<SubFormDto> SubForms { get; set; } = new();
public List<WidgetEditDto> Widgets { get; set; } = new();
public WorkflowDto Workflow { get; set; } = new();
public List<ListFormWorkflowCriteriaDto> WorkflowCriteria { get; set; } = new();
} }

View file

@ -12,6 +12,7 @@ public class WizardColumnItemInputDto
public string EditorScript { get; set; } public string EditorScript { get; set; }
public int ColSpan { get; set; } = 1; public int ColSpan { get; set; } = 1;
public bool IsRequired { get; set; } public bool IsRequired { get; set; }
public bool IncludeInEditingForm { get; set; } = true;
public DbType DbSourceType { get; set; } = DbType.String; public DbType DbSourceType { get; set; } = DbType.String;
public string TurkishCaption { get; set; } public string TurkishCaption { get; set; }
public string EnglishCaption { get; set; } public string EnglishCaption { get; set; }

View file

@ -1,3 +1,5 @@
using System.Collections.Generic;
namespace Sozsoft.Platform.ListForms; namespace Sozsoft.Platform.ListForms;
public class WorkflowRunResultDto public class WorkflowRunResultDto
@ -8,5 +10,6 @@ public class WorkflowRunResultDto
public string CurrentNodeKind { get; set; } public string CurrentNodeKind { get; set; }
public bool WaitingApproval { get; set; } public bool WaitingApproval { get; set; }
public bool Completed { get; set; } public bool Completed { get; set; }
public List<string> ToastMessages { get; set; } = [];
} }

View file

@ -7,6 +7,7 @@ public class RouteDto : EntityDto<Guid>
{ {
public string Key { get; set; } public string Key { get; set; }
public string Path { get; set; } public string Path { get; set; }
public string ComponentType { get; set; }
public string ComponentPath { get; set; } public string ComponentPath { get; set; }
public string RouteType { get; set; } public string RouteType { get; set; }
public string[] Authority { get; set; } public string[] Authority { get; set; }

View file

@ -3,9 +3,8 @@
<Import Project="..\..\common.props" /> <Import Project="..\..\common.props" />
<PropertyGroup> <PropertyGroup>
<TargetFramework>net9.0</TargetFramework> <TargetFramework>net10.0</TargetFramework>
<RootNamespace>Sozsoft.Platform</RootNamespace> <RootNamespace>Sozsoft.Platform</RootNamespace>
<NoWarn>$(NoWarn);CS8632</NoWarn>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
@ -16,12 +15,12 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Volo.Abp.ObjectExtending" Version="9.0.2" /> <PackageReference Include="Volo.Abp.ObjectExtending" Version="10.0.0" />
<PackageReference Include="Volo.Abp.Account.Application.Contracts" Version="9.0.2" /> <PackageReference Include="Volo.Abp.Account.Application.Contracts" Version="10.0.0" />
<PackageReference Include="Volo.Abp.Identity.Application.Contracts" Version="9.0.2" /> <PackageReference Include="Volo.Abp.Identity.Application.Contracts" Version="10.0.0" />
<PackageReference Include="Volo.Abp.PermissionManagement.Application.Contracts" Version="9.0.2" /> <PackageReference Include="Volo.Abp.PermissionManagement.Application.Contracts" Version="10.0.0" />
<PackageReference Include="Volo.Abp.TenantManagement.Application.Contracts" Version="9.0.2" /> <PackageReference Include="Volo.Abp.TenantManagement.Application.Contracts" Version="10.0.0" />
<PackageReference Include="Volo.Abp.FeatureManagement.Application.Contracts" Version="9.0.2" /> <PackageReference Include="Volo.Abp.FeatureManagement.Application.Contracts" Version="10.0.0" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View file

@ -1,14 +0,0 @@
using AutoMapper;
using Sozsoft.Platform.Entities;
namespace Sozsoft.Platform.AiBots;
public class AiBotAutoMapperProfile : Profile
{
public AiBotAutoMapperProfile()
{
CreateMap<AiBot, AiBotDto>().ReverseMap();
}
}

View file

@ -0,0 +1,33 @@
using Sozsoft.Platform.Entities;
using Riok.Mapperly.Abstractions;
using Volo.Abp.Mapperly;
namespace Sozsoft.Platform.AiBots;
[Mapper(RequiredMappingStrategy = RequiredMappingStrategy.Target)]
public partial class AiBotToAiBotDtoMapper : TwoWayMapperBase<AiBot, AiBotDto>
{
public override partial AiBotDto Map(AiBot source);
public override partial void Map(AiBot source, AiBotDto destination);
public override void BeforeMap(AiBot source)
{
}
public override void AfterMap(AiBot source, AiBotDto destination)
{
}
public override partial AiBot ReverseMap(AiBotDto destination);
public override partial void ReverseMap(AiBotDto destination, AiBot source);
public override void BeforeReverseMap(AiBotDto destination)
{
}
public override void AfterReverseMap(AiBotDto destination, AiBot source)
{
}
}

View file

@ -1,30 +1,43 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Linq.Expressions;
using System.Text.Json;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Sozsoft.Platform.Entities;
using Sozsoft.Platform.ListForms;
using Volo.Abp; using Volo.Abp;
using Volo.Abp.Application.Dtos; using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services; using Volo.Abp.Application.Services;
using Volo.Abp.AuditLogging; using Volo.Abp.AuditLogging;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Uow; using Volo.Abp.Uow;
using static Sozsoft.Platform.Data.Seeds.SeedConsts; using static Sozsoft.Platform.Data.Seeds.SeedConsts;
namespace Sozsoft.Platform.AuditLogs; namespace Sozsoft.Platform.AuditLogs;
public interface IAuditLogAppService public interface IAuditLogAppService
: ICrudAppService<AuditLogDto, Guid> : ICrudAppService<AuditLogDto, Guid, AuditLogListRequestDto>
{ {
} }
[Authorize(AppCodes.IdentityManagement.AuditLogs)] [Authorize(AppCodes.IdentityManagement.AuditLogs)]
public class AuditLogAppService public class AuditLogAppService : CrudAppService<
: CrudAppService<AuditLog, AuditLogDto, Guid> AuditLog,
, IAuditLogAppService AuditLogDto,
Guid,
AuditLogListRequestDto>, IAuditLogAppService
{ {
public AuditLogAppService(IAuditLogRepository auditLogRepository) : base(auditLogRepository) private readonly IRepository<ListForm, Guid> _listFormRepository;
public AuditLogAppService(
IAuditLogRepository auditLogRepository,
IRepository<ListForm, Guid> listFormRepository
) : base(auditLogRepository)
{ {
_listFormRepository = listFormRepository;
} }
public override async Task<AuditLogDto> GetAsync(Guid id) public override async Task<AuditLogDto> GetAsync(Guid id)
@ -35,23 +48,26 @@ public class AuditLogAppService
} }
[UnitOfWork] [UnitOfWork]
public override async Task<PagedResultDto<AuditLogDto>> GetListAsync(PagedAndSortedResultRequestDto input) public override async Task<PagedResultDto<AuditLogDto>> GetListAsync(AuditLogListRequestDto input)
{ {
var query = await CreateFilteredQueryAsync(input); var query = await Repository.WithDetailsAsync();
if (!input.ListFormCode.IsNullOrWhiteSpace())
{
var filterRules = await GetListFormFilterRulesAsync(input.ListFormCode);
query = ApplyAuditLogActionParametersFilter(query, filterRules, input.EntityId);
}
else if (!input.EntityId.IsNullOrWhiteSpace())
{
query = query.Where(a => a.Actions.Any(action => action.Parameters.Contains(input.EntityId)));
}
var totalCount = await AsyncExecuter.CountAsync(query); var totalCount = await AsyncExecuter.CountAsync(query);
query = ApplySorting(query, input); query = ApplySorting(query, input);
query = ApplyPaging(query, input); query = ApplyPaging(query, input);
// EntityChanges ile birlikte getir (N+1 query önlenir) var auditLogsWithDetails = await AsyncExecuter.ToListAsync(query);
var auditLogRepository = (IAuditLogRepository)Repository;
var auditLogsWithDetails = await auditLogRepository.GetListAsync(
sorting: input.Sorting,
maxResultCount: input.MaxResultCount,
skipCount: input.SkipCount,
includeDetails: true
);
// Mapping tek seferde yap // Mapping tek seferde yap
var entityDtos = ObjectMapper.Map<List<AuditLog>, List<AuditLogDto>>(auditLogsWithDetails); var entityDtos = ObjectMapper.Map<List<AuditLog>, List<AuditLogDto>>(auditLogsWithDetails);
@ -69,6 +85,102 @@ public class AuditLogAppService
); );
} }
private async Task<List<AuditLogListFormFilterRule>> GetListFormFilterRulesAsync(string listFormCode)
{
var rules = new List<AuditLogListFormFilterRule>
{
new(listFormCode, null)
};
var listForm = await _listFormRepository.FirstOrDefaultAsync(a => a.ListFormCode == listFormCode);
if (listForm?.SubFormsJson.IsNullOrWhiteSpace() != false)
{
return rules;
}
try
{
var subForms = JsonSerializer.Deserialize<List<SubFormDto>>(listForm.SubFormsJson) ?? [];
foreach (var subForm in subForms.Where(a => !a.Code.IsNullOrWhiteSpace()))
{
var childFieldNames = subForm.Relation?
.Select(a => a.ChildFieldName)
.Where(a => !a.IsNullOrWhiteSpace())
.Distinct(StringComparer.OrdinalIgnoreCase)
.ToList() ?? [];
rules.AddRange(childFieldNames.Select(childFieldName => new AuditLogListFormFilterRule(subForm.Code, childFieldName)));
}
}
catch (JsonException)
{
// Invalid subform JSON should not block audit log listing for the main form.
}
return rules
.DistinctBy(a => $"{a.ListFormCode}|{a.ChildFieldName}".ToLowerInvariant())
.ToList();
}
private static IQueryable<AuditLog> ApplyAuditLogActionParametersFilter(
IQueryable<AuditLog> query,
List<AuditLogListFormFilterRule> rules,
string entityId)
{
var validRules = rules
.Where(rule => !rule.ListFormCode.IsNullOrWhiteSpace())
.ToList();
if (validRules.Count == 0)
{
return query;
}
var auditLog = Expression.Parameter(typeof(AuditLog), "auditLog");
var action = Expression.Parameter(typeof(AuditLogAction), "action");
var parameters = Expression.Property(action, nameof(AuditLogAction.Parameters));
Expression actionBody = Expression.Constant(false);
foreach (var rule in validRules)
{
Expression ruleBody = Contains(parameters, rule.ListFormCode);
if (!entityId.IsNullOrWhiteSpace())
{
ruleBody = Expression.AndAlso(ruleBody, Contains(parameters, entityId));
}
if (!rule.ChildFieldName.IsNullOrWhiteSpace())
{
ruleBody = Expression.AndAlso(ruleBody, Contains(parameters, rule.ChildFieldName));
}
actionBody = Expression.OrElse(actionBody, ruleBody);
}
var actions = Expression.Property(auditLog, nameof(AuditLog.Actions));
var actionPredicate = Expression.Lambda<Func<AuditLogAction, bool>>(actionBody, action);
var anyCall = Expression.Call(
typeof(Enumerable),
nameof(Enumerable.Any),
[typeof(AuditLogAction)],
actions,
actionPredicate);
var auditLogPredicate = Expression.Lambda<Func<AuditLog, bool>>(anyCall, auditLog);
return query.Where(auditLogPredicate);
}
private static MethodCallExpression Contains(MemberExpression source, string value)
{
return Expression.Call(
source,
nameof(string.Contains),
Type.EmptyTypes,
Expression.Constant(value));
}
private sealed record AuditLogListFormFilterRule(string ListFormCode, string? ChildFieldName);
// Audit Log kayitlarini gormek istiyoruz fakat degistirmek istemiyoruz // Audit Log kayitlarini gormek istiyoruz fakat degistirmek istemiyoruz
[RemoteService(IsEnabled = false)] [RemoteService(IsEnabled = false)]
public override Task<AuditLogDto> CreateAsync(AuditLogDto input) public override Task<AuditLogDto> CreateAsync(AuditLogDto input)

View file

@ -1,16 +0,0 @@
using AutoMapper;
using Volo.Abp.AuditLogging;
namespace Sozsoft.Platform.AuditLogs;
public class AuditLogAutoMapperProfile : Profile
{
public AuditLogAutoMapperProfile()
{
CreateMap<AuditLog, AuditLogDto>();
CreateMap<AuditLogAction, AuditLogActionDto>();
CreateMap<EntityChange, EntityChangeDto>();
CreateMap<EntityPropertyChange, EntityPropertyChangeDto>();
}
}

View file

@ -0,0 +1,69 @@
using Volo.Abp.AuditLogging;
using Riok.Mapperly.Abstractions;
using Volo.Abp.Mapperly;
namespace Sozsoft.Platform.AuditLogs;
[Mapper(RequiredMappingStrategy = RequiredMappingStrategy.Target)]
public partial class AuditLogToAuditLogDtoMapper : MapperBase<AuditLog, AuditLogDto>
{
public override partial AuditLogDto Map(AuditLog source);
public override partial void Map(AuditLog source, AuditLogDto destination);
public override void BeforeMap(AuditLog source)
{
}
public override void AfterMap(AuditLog source, AuditLogDto destination)
{
}
}
[Mapper(RequiredMappingStrategy = RequiredMappingStrategy.Target)]
public partial class AuditLogActionToAuditLogActionDtoMapper : MapperBase<AuditLogAction, AuditLogActionDto>
{
public override partial AuditLogActionDto Map(AuditLogAction source);
public override partial void Map(AuditLogAction source, AuditLogActionDto destination);
public override void BeforeMap(AuditLogAction source)
{
}
public override void AfterMap(AuditLogAction source, AuditLogActionDto destination)
{
}
}
[Mapper(RequiredMappingStrategy = RequiredMappingStrategy.Target)]
public partial class EntityChangeToEntityChangeDtoMapper : MapperBase<EntityChange, EntityChangeDto>
{
public override partial EntityChangeDto Map(EntityChange source);
public override partial void Map(EntityChange source, EntityChangeDto destination);
public override void BeforeMap(EntityChange source)
{
}
public override void AfterMap(EntityChange source, EntityChangeDto destination)
{
}
}
[Mapper(RequiredMappingStrategy = RequiredMappingStrategy.Target)]
public partial class EntityPropertyChangeToEntityPropertyChangeDtoMapper : MapperBase<EntityPropertyChange, EntityPropertyChangeDto>
{
public override partial EntityPropertyChangeDto Map(EntityPropertyChange source);
public override partial void Map(EntityPropertyChange source, EntityPropertyChangeDto destination);
public override void BeforeMap(EntityPropertyChange source)
{
}
public override void AfterMap(EntityPropertyChange source, EntityPropertyChangeDto destination)
{
}
}

View file

@ -35,7 +35,7 @@ public class BackgroundWorkerInitializer : ITransientDependency
var turkeyTimeZone = GetTurkeyTimeZone(); var turkeyTimeZone = GetTurkeyTimeZone();
_logger.LogInformation( _logger.LogInformation(
"Background workers Türkiye saat dilimine göre kuruluyor. TimeZoneId: {TimeZoneId}", "Background Works is set up according to the Turkish time zone. TimeZoneId: {TimeZoneId}",
turkeyTimeZone.Id); turkeyTimeZone.Id);
var jobs = JobStorage.Current.GetConnection().GetRecurringJobs(); var jobs = JobStorage.Current.GetConnection().GetRecurringJobs();

View file

@ -1,12 +0,0 @@
using AutoMapper;
using Sozsoft.Platform.Branchs;
public class BranchAutoMapperProfile : Profile
{
public BranchAutoMapperProfile()
{
CreateMap<BranchSeedResult, BranchSeedResultDto>();
CreateMap<BranchSeedDetail, SeedDetailDto>();
}
}

View file

@ -0,0 +1,37 @@
using Sozsoft.Platform.Branchs;
using Riok.Mapperly.Abstractions;
using Volo.Abp.Mapperly;
namespace Sozsoft.Platform.Branchs;
[Mapper(RequiredMappingStrategy = RequiredMappingStrategy.Target)]
public partial class BranchSeedResultToBranchSeedResultDtoMapper : MapperBase<BranchSeedResult, BranchSeedResultDto>
{
public override partial BranchSeedResultDto Map(BranchSeedResult source);
public override partial void Map(BranchSeedResult source, BranchSeedResultDto destination);
public override void BeforeMap(BranchSeedResult source)
{
}
public override void AfterMap(BranchSeedResult source, BranchSeedResultDto destination)
{
}
}
[Mapper(RequiredMappingStrategy = RequiredMappingStrategy.Target)]
public partial class BranchSeedDetailToSeedDetailDtoMapper : MapperBase<BranchSeedDetail, SeedDetailDto>
{
public override partial SeedDetailDto Map(BranchSeedDetail source);
public override partial void Map(BranchSeedDetail source, SeedDetailDto destination);
public override void BeforeMap(BranchSeedDetail source)
{
}
public override void AfterMap(BranchSeedDetail source, SeedDetailDto destination)
{
}
}

View file

@ -1,14 +0,0 @@
using AutoMapper;
using Sozsoft.Platform.Entities;
namespace Sozsoft.Platform.DataSources;
public class DataSourceAutoMapperProfile : Profile
{
public DataSourceAutoMapperProfile()
{
CreateMap<DataSource, DataSourceDto>().ReverseMap();
}
}

View file

@ -0,0 +1,33 @@
using Sozsoft.Platform.Entities;
using Riok.Mapperly.Abstractions;
using Volo.Abp.Mapperly;
namespace Sozsoft.Platform.DataSources;
[Mapper(RequiredMappingStrategy = RequiredMappingStrategy.Target)]
public partial class DataSourceToDataSourceDtoMapper : TwoWayMapperBase<DataSource, DataSourceDto>
{
public override partial DataSourceDto Map(DataSource source);
public override partial void Map(DataSource source, DataSourceDto destination);
public override void BeforeMap(DataSource source)
{
}
public override void AfterMap(DataSource source, DataSourceDto destination)
{
}
public override partial DataSource ReverseMap(DataSourceDto destination);
public override partial void ReverseMap(DataSourceDto destination, DataSource source);
public override void BeforeReverseMap(DataSourceDto destination)
{
}
public override void AfterReverseMap(DataSourceDto destination, DataSource source)
{
}
}

View file

@ -70,14 +70,14 @@ public class CustomEndpointAppService : PlatformAppService
.EnsureStartsWith('/') .EnsureStartsWith('/')
.EnsureEndsWith('/'); .EnsureEndsWith('/');
Logger.LogInformation("Custom Endpoint çağrısı. Kullanıcı:{user} Path:[{method}]{path}", CurrentUser.UserName, "GET", path); Logger.LogInformation("Custom Endpoint called. User: {user} Path: [{method}]{path}", CurrentUser.UserName, "GET", path);
var api = await repo.FirstOrDefaultAsync(a => path.StartsWith(a.Url) && a.Method == method); var api = await repo.FirstOrDefaultAsync(a => path.StartsWith(a.Url) && a.Method == method);
if (api is null) if (api is null)
{ {
Logger.LogInformation("Custom Endpoint bulunamadı"); Logger.LogInformation("Custom Endpoint not found: {path}", path);
return new NotFoundResult(); return new NotFoundResult();
} }
Logger.LogInformation("Custom Endpoint bulundu. {api}", api.Name); Logger.LogInformation("Custom Endpoint found: {api}", api.Name);
var canUse = api.Permissions.Any(a => var canUse = api.Permissions.Any(a =>
(a.ResourceType == "User" && a.ResourceId == CurrentUser.UserName) || (a.ResourceType == "User" && a.ResourceId == CurrentUser.UserName) ||
@ -85,7 +85,7 @@ public class CustomEndpointAppService : PlatformAppService
(a.ResourceType == "Global")); (a.ResourceType == "Global"));
if (!canUse) if (!canUse)
{ {
Logger.LogWarning("Custom Endpoint yetki yok"); Logger.LogWarning("Custom Endpoint has no permission: {path}", path);
return new UnauthorizedResult(); return new UnauthorizedResult();
} }
@ -158,13 +158,12 @@ public class CustomEndpointAppService : PlatformAppService
} }
} }
Logger.LogInformation("Parametreler: {param}", param); Logger.LogInformation("Parameters: {param}", param);
var (dynamicDataRepository, connectionString, _) = await dynamicDataManager.GetAsync(api.DataSourceCode == "!Tenant", api.DataSourceCode); var (dynamicDataRepository, connectionString, _) = await dynamicDataManager.GetAsync(api.DataSourceCode == "!Tenant", api.DataSourceCode);
var result = await dynamicDataRepository.QueryAsync(api.Sql, connectionString, param); var result = await dynamicDataRepository.QueryAsync(api.Sql, connectionString, param);
Logger.LogInformation("Sonuç başarılı"); Logger.LogInformation("Query successful. Result: {result}", result);
Logger.LogInformation("{result}", result);
await uow.CompleteAsync(); await uow.CompleteAsync();

View file

@ -1,22 +0,0 @@
using AutoMapper;
using Sozsoft.Platform.Entities;
namespace Sozsoft.Platform.DeveloperKit;
public class DeveloperKitAutoMapperProfile : Profile
{
public DeveloperKitAutoMapperProfile()
{
// CustomComponent mappings
CreateMap<CustomComponent, CustomComponentDto>();
CreateMap<CreateUpdateCustomComponentDto, CustomComponent>();
// GeneratedEndpoint mappings
CreateMap<CrudEndpoint, CrudEndpointDto>();
CreateMap<CreateUpdateCrudEndpointDto, CrudEndpoint>();
CreateMap<DynamicService, DynamicServiceDto>()
.ForMember(dest => dest.CompilationStatus, opt => opt.MapFrom(src => src.CompilationStatus.ToString()));
}
}

View file

@ -0,0 +1,86 @@
using Sozsoft.Platform.Entities;
using Riok.Mapperly.Abstractions;
using Volo.Abp.Mapperly;
namespace Sozsoft.Platform.DeveloperKit;
[Mapper(RequiredMappingStrategy = RequiredMappingStrategy.Target)]
public partial class CustomComponentToCustomComponentDtoMapper : MapperBase<CustomComponent, CustomComponentDto>
{
public override partial CustomComponentDto Map(CustomComponent source);
public override partial void Map(CustomComponent source, CustomComponentDto destination);
public override void BeforeMap(CustomComponent source)
{
}
public override void AfterMap(CustomComponent source, CustomComponentDto destination)
{
}
}
[Mapper(RequiredMappingStrategy = RequiredMappingStrategy.Target)]
public partial class CreateUpdateCustomComponentDtoToCustomComponentMapper : MapperBase<CreateUpdateCustomComponentDto, CustomComponent>
{
public override partial CustomComponent Map(CreateUpdateCustomComponentDto source);
public override partial void Map(CreateUpdateCustomComponentDto source, CustomComponent destination);
public override void BeforeMap(CreateUpdateCustomComponentDto source)
{
}
public override void AfterMap(CreateUpdateCustomComponentDto source, CustomComponent destination)
{
}
}
[Mapper(RequiredMappingStrategy = RequiredMappingStrategy.Target)]
public partial class CrudEndpointToCrudEndpointDtoMapper : MapperBase<CrudEndpoint, CrudEndpointDto>
{
public override partial CrudEndpointDto Map(CrudEndpoint source);
public override partial void Map(CrudEndpoint source, CrudEndpointDto destination);
public override void BeforeMap(CrudEndpoint source)
{
}
public override void AfterMap(CrudEndpoint source, CrudEndpointDto destination)
{
}
}
[Mapper(RequiredMappingStrategy = RequiredMappingStrategy.Target)]
public partial class CreateUpdateCrudEndpointDtoToCrudEndpointMapper : MapperBase<CreateUpdateCrudEndpointDto, CrudEndpoint>
{
public override partial CrudEndpoint Map(CreateUpdateCrudEndpointDto source);
public override partial void Map(CreateUpdateCrudEndpointDto source, CrudEndpoint destination);
public override void BeforeMap(CreateUpdateCrudEndpointDto source)
{
}
public override void AfterMap(CreateUpdateCrudEndpointDto source, CrudEndpoint destination)
{
}
}
[Mapper(RequiredMappingStrategy = RequiredMappingStrategy.Target)]
public partial class DynamicServiceToDynamicServiceDtoMapper : MapperBase<DynamicService, DynamicServiceDto>
{
public override partial DynamicServiceDto Map(DynamicService source);
public override partial void Map(DynamicService source, DynamicServiceDto destination);
public override void BeforeMap(DynamicService source)
{
}
public override void AfterMap(DynamicService source, DynamicServiceDto destination)
{
destination.CompilationStatus = source.CompilationStatus.ToString();
}
}

View file

@ -36,7 +36,7 @@ public class DynamicAppServiceAppService : PlatformAppService, IDynamicServiceAp
} }
catch (Exception ex) catch (Exception ex)
{ {
Logger.LogError(ex, "Test compile sırasında hata. Tenant: {TenantId}", CurrentTenant.Id); Logger.LogError(ex, "Failed to test compile dynamic service. Tenant: {TenantId}", CurrentTenant.Id);
throw; throw;
} }
} }
@ -152,13 +152,13 @@ public class DynamicAppServiceAppService : PlatformAppService, IDynamicServiceAp
} }
catch (Exception ex) catch (Exception ex)
{ {
Logger.LogError(ex, "AppService yayınlama sırasında hata. Ad: {Name}, Tenant: {TenantId}", Logger.LogError(ex, "Failed to publish dynamic service. Name: {Name}, Tenant: {TenantId}",
request.Name, CurrentTenant.Id); request.Name, CurrentTenant.Id);
return new PublishResultDto return new PublishResultDto
{ {
Success = false, Success = false,
ErrorMessage = $"Yayınlama sırasında beklenmeyen hata: {ex.Message}" ErrorMessage = $"Failed to publish dynamic service: {ex.Message}"
}; };
} }
} }
@ -233,7 +233,7 @@ public class DynamicAppServiceAppService : PlatformAppService, IDynamicServiceAp
if (!result.Success) if (!result.Success)
{ {
Logger.LogWarning( Logger.LogWarning(
"Servis aktif edildi ancak yeniden derleme başarısız. Ad: {Name}, Hata: {Error}", "Failed to recompile and register dynamic service. Name: {Name}, Error: {Error}",
appService.Name, result.ErrorMessage); appService.Name, result.ErrorMessage);
} }
} }
@ -274,7 +274,7 @@ public class DynamicAppServiceAppService : PlatformAppService, IDynamicServiceAp
catch (Exception ex) catch (Exception ex)
{ {
errorCount++; errorCount++;
Logger.LogError(ex, "AppService yeniden yükleme hatası. ID: {Id}", service.Id); Logger.LogError(ex, "Failed to recompile dynamic service. ID: {Id}", service.Id);
service.MarkCompilationError(ex.Message); service.MarkCompilationError(ex.Message);
await _dynamicAppServiceRepository.UpdateAsync(service); await _dynamicAppServiceRepository.UpdateAsync(service);

View file

@ -139,7 +139,7 @@ public class DynamicServiceCompiler : ITransientDependency
result.ErrorMessage = $"Derleme {result.Errors.Count} hata ile başarısız oldu."; result.ErrorMessage = $"Derleme {result.Errors.Count} hata ile başarısız oldu.";
} }
_logger.LogInformation("Kod derlemesi tamamlandı. Başarılı: {Success}, Süre: {Time}ms, Hata sayısı: {ErrorCount}", _logger.LogInformation("Compilation completed. Success: {Success}, Time: {Time}ms, Error Count: {ErrorCount}",
result.Success, stopwatch.ElapsedMilliseconds, result.Errors?.Count ?? 0); result.Success, stopwatch.ElapsedMilliseconds, result.Errors?.Count ?? 0);
return result; return result;
@ -147,7 +147,7 @@ public class DynamicServiceCompiler : ITransientDependency
catch (Exception ex) catch (Exception ex)
{ {
stopwatch.Stop(); stopwatch.Stop();
_logger.LogError(ex, "Kod derlemesi sırasında beklenmeyen hata"); _logger.LogError(ex, "Compilation failed with unexpected error");
return new CompileResultDto return new CompileResultDto
{ {
@ -211,12 +211,12 @@ public class DynamicServiceCompiler : ITransientDependency
} }
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogError(ex, "Assembly yükleme sırasında hata. Tenant: {TenantId}", tenantId); _logger.LogError(ex, "Failed to load assembly. Tenant: {TenantId}", tenantId);
return new CompileResultDto return new CompileResultDto
{ {
Success = false, Success = false,
ErrorMessage = $"Assembly yükleme hatası: {ex.Message}", ErrorMessage = $"Failed to load assembly: {ex.Message}",
Errors = new List<CompilationErrorDto>() Errors = new List<CompilationErrorDto>()
}; };
} }
@ -317,7 +317,7 @@ public class DynamicServiceCompiler : ITransientDependency
} }
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogWarning(ex, "Assembly referansı eklenemedi: {Assembly}", assembly.FullName); _logger.LogWarning(ex, "Failed to add assembly reference: {Assembly}", assembly.FullName);
} }
} }

View file

@ -1,16 +0,0 @@
using AutoMapper;
using Sozsoft.Platform.Forum;
namespace Sozsoft.Platform;
public class ForumAutoMapperProfile : Profile
{
public ForumAutoMapperProfile()
{
// Blog mappings
CreateMap<ForumCategory, ForumCategoryDto>().ReverseMap();
CreateMap<ForumPost, ForumPostDto>().ReverseMap();
CreateMap<ForumTopic, ForumTopicDto>().ReverseMap();
}
}

View file

@ -0,0 +1,89 @@
using Sozsoft.Platform.Forum;
using Riok.Mapperly.Abstractions;
using Volo.Abp.Mapperly;
namespace Sozsoft.Platform;
[Mapper(RequiredMappingStrategy = RequiredMappingStrategy.Target)]
public partial class ForumCategoryToForumCategoryDtoMapper : TwoWayMapperBase<ForumCategory, ForumCategoryDto>
{
public override partial ForumCategoryDto Map(ForumCategory source);
public override partial void Map(ForumCategory source, ForumCategoryDto destination);
public override void BeforeMap(ForumCategory source)
{
}
public override void AfterMap(ForumCategory source, ForumCategoryDto destination)
{
}
public override partial ForumCategory ReverseMap(ForumCategoryDto destination);
public override partial void ReverseMap(ForumCategoryDto destination, ForumCategory source);
public override void BeforeReverseMap(ForumCategoryDto destination)
{
}
public override void AfterReverseMap(ForumCategoryDto destination, ForumCategory source)
{
}
}
[Mapper(RequiredMappingStrategy = RequiredMappingStrategy.Target)]
public partial class ForumPostToForumPostDtoMapper : TwoWayMapperBase<ForumPost, ForumPostDto>
{
public override partial ForumPostDto Map(ForumPost source);
public override partial void Map(ForumPost source, ForumPostDto destination);
public override void BeforeMap(ForumPost source)
{
}
public override void AfterMap(ForumPost source, ForumPostDto destination)
{
}
public override partial ForumPost ReverseMap(ForumPostDto destination);
public override partial void ReverseMap(ForumPostDto destination, ForumPost source);
public override void BeforeReverseMap(ForumPostDto destination)
{
}
public override void AfterReverseMap(ForumPostDto destination, ForumPost source)
{
}
}
[Mapper(RequiredMappingStrategy = RequiredMappingStrategy.Target)]
public partial class ForumTopicToForumTopicDtoMapper : TwoWayMapperBase<ForumTopic, ForumTopicDto>
{
public override partial ForumTopicDto Map(ForumTopic source);
public override partial void Map(ForumTopic source, ForumTopicDto destination);
public override void BeforeMap(ForumTopic source)
{
}
public override void AfterMap(ForumTopic source, ForumTopicDto destination)
{
}
public override partial ForumTopic ReverseMap(ForumTopicDto destination);
public override partial void ReverseMap(ForumTopicDto destination, ForumTopic source);
public override void BeforeReverseMap(ForumTopicDto destination)
{
}
public override void AfterReverseMap(ForumTopicDto destination, ForumTopic source)
{
}
}

View file

@ -1,15 +0,0 @@
using AutoMapper;
using Sozsoft.Platform.Entities;
using Sozsoft.Platform.Hr;
namespace Sozsoft.Platform.Intranet;
public class HrAutoMapperProfile : Profile
{
public HrAutoMapperProfile()
{
CreateMap<Department, DepartmentDto>();
CreateMap<JobPosition, JobPositionDto>();
}
}

View file

@ -0,0 +1,38 @@
using Sozsoft.Platform.Entities;
using Sozsoft.Platform.Hr;
using Riok.Mapperly.Abstractions;
using Volo.Abp.Mapperly;
namespace Sozsoft.Platform.Intranet;
[Mapper(RequiredMappingStrategy = RequiredMappingStrategy.Target)]
public partial class DepartmentToDepartmentDtoMapper : MapperBase<Department, DepartmentDto>
{
public override partial DepartmentDto Map(Department source);
public override partial void Map(Department source, DepartmentDto destination);
public override void BeforeMap(Department source)
{
}
public override void AfterMap(Department source, DepartmentDto destination)
{
}
}
[Mapper(RequiredMappingStrategy = RequiredMappingStrategy.Target)]
public partial class JobPositionToJobPositionDtoMapper : MapperBase<JobPosition, JobPositionDto>
{
public override partial JobPositionDto Map(JobPosition source);
public override partial void Map(JobPosition source, JobPositionDto destination);
public override void BeforeMap(JobPosition source)
{
}
public override void AfterMap(JobPosition source, JobPositionDto destination)
{
}
}

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