diff --git a/.changes/Migration 10.2.0 - 10.4.0.md b/.changes/Migration 10.2.0 - 10.4.0.md new file mode 100644 index 000000000..864bde8f2 --- /dev/null +++ b/.changes/Migration 10.2.0 - 10.4.0.md @@ -0,0 +1,76 @@ +# 10.2.0 - 10.4.0 + +## 模块变更 + +1. [身份标识模块] 增加不活跃用户通知/清理作业,实现了三个通知模板(账户保持活跃通知、账户停用通知、账户删除通知) +2. [身份标识模块] 增加不活跃用户实体 `IdentityUserInactive` 需要执行数据库迁移 +3. [身份标识模块] 增加用户登录Url设置定义: `Abp.Identity.Link.UserLoginUri`, 用于在外部系统中关联用户登录页 +4. [身份认证模块] 增加用户登录Url定义: `Abp.Account.UserLogin` +5. [身份认证模块] 增加关联用户登录功能, 可以实现跨租户用户关联, 切换关联用户登录 +6. [设置管理模块] 增加身份标识模块缺少的设置项: 启用防止密码重用、防止密码重用数量 +7. [设置基础模块] 增加设置定义分组、所属设置、优先级、依赖权限、依赖功能、选择项等常用结构扩展 +8. [设置管理模块] 重构设置管理应用服务接口, 通过预设定的设置定义分组、上下级关系等自动构成Dto结构 + +## 依赖项变更 + +| 库名称 | 原版本 | 现版本 | +| -------------------------------------------- | --------- | ------ | +| Microsoft.AspNetCore.* | 10.0.2 | 10.0.7 | +| Microsoft.Bcl.AsyncInterfaces | 10.0.2 | 10.0.7 | +| Microsoft.Data.Sqlite.Core | 10.0.0 | 10.0.7 | +| Microsoft.EntityFrameworkCore.* | 10.0.2 | 10.0.7 | +| Microting.EntityFrameworkCore.MySql | 10.0.3 | 10.0.7 | +| Microsoft.Extensions.* | 10.0.2 | 10.0.7 | +| OpenTelemetry.Extensions.Hosting | 1.14.0 | 1.15.3 | +| OpenTelemetry.Exporter.Console | 1.14.0 | 1.15.3 | +| OpenTelemetry.Exporter.OpenTelemetryProtocol | 1.14.0 | 1.15.3 | +| OpenTelemetry.Exporter.Zipkin | 1.14.0 | 1.15.3 | +| OpenTelemetry.Instrumentation.AspNetCore | 1.14.0 | 1.15.2 | +| OpenTelemetry.Instrumentation.Http | 1.14.0 | 1.15.1 | +| OpenTelemetry.Instrumentation.Quartz | 1.14.0-beta.2 | 1.15.1-beta.1 | +| OpenTelemetry.Instrumentation.Runtime | 1.14.0 | 1.15.1 | +| OpenTelemetry.Instrumentation.SqlClient | 1.14.0-beta.1 | 1.15.2 | +| OpenIddict.Server.DataProtection | 7.2.0 | 7.5.0 | +| OpenIddict.Validation.DataProtection | 7.2.0 | 7.5.0 | +| System.Threading.Channels | 10.0.0 | 10.0.7 | +| Volo.Abp.* | 10.2.0 | 10.4.0 | +| Volo.Abp.AspNetCore.Mvc.UI.Theme.LeptonXLite | 5.2.0 | 5.4.0 | + + + +## 数据库迁移 + +| Project Name | Database Provider | Scripts | EF Core Version | +| ------------------------ | ----------------- | ---------------------------------------------- | --------------- | +| aspire/AuthServer | PostgreSQL | 20260530060327_Add-Identity-User-Inactive | 10.0.2 | +| services/Single | MySQL | 20260529063257_Add-Identity-User-Inactive | 10.0.3 | +| services/Single | PostgreSQL | 20260530055941_Add-Identity-User-Inactive | 10.0.2 | +| services/Single | SqlServer | 20260530060009_Add-Identity-User-Inactive | 10.0.2 | +| services/AuthServer | MySQL | 20260530061141_Add-Identity-User-Inactive | 10.0.3 | + + +## 数据库连接字符串 + +| Module Name | ConnectionString Name | Example(MySQL) | +| ----------------------------- | ---------------------------- | ------------------------------------------------------------ | +| Default | Default | Server=127.0.0.1;Database=abp;User Id=root;Password=123456;SslMode=None | +| abp/Identity | AbpIdentity | Server=127.0.0.1;Database=abp;User Id=root;Password=123456;SslMode=None | +| abp/IdentityServer | AbpIdentityServer | Server=127.0.0.1;Database=abp;User Id=root;Password=123456;SslMode=None | +| abp/OpenIddict | AbpOpenIddict | Server=127.0.0.1;Database=abp;User Id=root;Password=123456;SslMode=None | +| abp/TenantManagement | AbpTenantManagement(AbpSaas) | Server=127.0.0.1;Database=abp;User Id=root;Password=123456;SslMode=None | +| abp/FeatureManagement | AbpFeatureManagement | Server=127.0.0.1;Database=abp;User Id=root;Password=123456;SslMode=None | +| abp/SettingManagement | AbpSettingManagement | Server=127.0.0.1;Database=abp;User Id=root;Password=123456;SslMode=None | +| abp/PermissionManagement | AbpPermissionManagement | Server=127.0.0.1;Database=abp;User Id=root;Password=123456;SslMode=None | +| labp/AIManagement | AbpAIManagement | Server=127.0.0.1;Database=abp;User Id=root;Password=123456;SslMode=None | +| labp/BlobManagement | AbpBlobManagement | Server=127.0.0.1;Database=abp;User Id=root;Password=123456;SslMode=None | +| labp/DataProtectionManagement | AbpDataProtectionManagement | Server=127.0.0.1;Database=abp;User Id=root;Password=123456;SslMode=None | +| labp/Gdpr | AbpGdpr | Server=127.0.0.1;Database=abp;User Id=root;Password=123456;SslMode=None | +| labp/Saas | AbpSaas | Server=127.0.0.1;Database=abp;User Id=root;Password=123456;SslMode=None | +| labp/LocalizationManagement | AbpLocalizationManagement | Server=127.0.0.1;Database=abp;User Id=root;Password=123456;SslMode=None | +| labp/TextTemplating | AbpTextTemplating | Server=127.0.0.1;Database=abp;User Id=root;Password=123456;SslMode=None | +| labp/Platform | AppPlatform | Server=127.0.0.1;Database=abp;User Id=root;Password=123456;SslMode=None | +| labp/MessageService | MessageService | Server=127.0.0.1;Database=abp;User Id=root;Password=123456;SslMode=None | +| labp/NotificationService | Notifications | Server=127.0.0.1;Database=abp;User Id=root;Password=123456;SslMode=None | +| labp/TaskManagement | TaskManagement | Server=127.0.0.1;Database=abp;User Id=root;Password=123456;SslMode=None | +| labp/WebhooksManagement | WebhooksManagement | Server=127.0.0.1;Database=abp;User Id=root;Password=123456;SslMode=None | +| labp/Elsa | Workflow | Server=127.0.0.1;Database=abp;User Id=root;Password=123456;SslMode=None | diff --git a/Directory.Packages.props b/Directory.Packages.props index 7c7d36b3d..eae775c5f 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -3,17 +3,17 @@ 10.0.0 2.16.1 3.6.0 - 10.2.0 - 10.2.0 - 10.0.2 - 10.0.2 - 10.0.2 + 10.4.0 + 10.4.0 + 10.0.7 + 10.0.7 + 10.0.7 13.1.0 true - + @@ -164,7 +164,7 @@ - + @@ -186,11 +186,11 @@ - + - + @@ -200,7 +200,7 @@ - + @@ -276,16 +276,16 @@ - - - - - - + + + + + + - - - + + + @@ -318,7 +318,7 @@ - + @@ -365,8 +365,8 @@ - - + + @@ -383,7 +383,7 @@ - + diff --git a/apps/vben5/apps/app-antd/src/layouts/basic.vue b/apps/vben5/apps/app-antd/src/layouts/basic.vue index 755598abb..eeb8302f4 100644 --- a/apps/vben5/apps/app-antd/src/layouts/basic.vue +++ b/apps/vben5/apps/app-antd/src/layouts/basic.vue @@ -14,7 +14,7 @@ import { UserDropdown, } from '@vben/layouts'; import { preferences } from '@vben/preferences'; -import { useAccessStore, useUserStore } from '@vben/stores'; +import { useAccessStore, useTabbarStore, useUserStore } from '@vben/stores'; import { useAbpStore } from '@abp/core'; @@ -30,11 +30,12 @@ const notifications = ref([]); useSessions(); -const { replace } = useRouter(); +const router = useRouter(); const abpStore = useAbpStore(); const userStore = useUserStore(); const authStore = useAuthStore(); const accessStore = useAccessStore(); +const tabbarStore = useTabbarStore(); const { destroyWatermark, updateWatermark } = useWatermark(); const showDot = computed(() => notifications.value.some((item) => !item.isRead), @@ -57,7 +58,7 @@ const menus = computed(() => [ }, { handler: () => { - replace('/account/my-settings'); + router.replace('/account/my-settings'); }, icon: UserSettingsIcon, text: $t('abp.account.settings.title'), @@ -109,7 +110,8 @@ async function handleLinkUser(token: string) { async function handleLinkLogin(userId: string, tenantId?: string) { await authStore.linkUseLogin(userId, tenantId, () => { - window.location.reload(); + tabbarStore.closeAllTabs(router); + window.location.replace('/'); }); } watch( diff --git a/apps/vben5/packages/@abp/settings/src/components/settings/SettingForm.vue b/apps/vben5/packages/@abp/settings/src/components/settings/SettingForm.vue index a2dd403ae..0b172671b 100644 --- a/apps/vben5/packages/@abp/settings/src/components/settings/SettingForm.vue +++ b/apps/vben5/packages/@abp/settings/src/components/settings/SettingForm.vue @@ -41,7 +41,6 @@ const emits = defineEmits<{ const FormItem = Form.Item; const TabPane = Tabs.TabPane; const CollapsePanel = Collapse.Panel; -const SelectOption = Select.Option; const defaultModel: SettingsUpdateInput = { settings: [], @@ -104,6 +103,15 @@ function onValueChange(setting: SettingDetail) { } } +function onFilterOption(input: string, option: any) { + if (option?.value || option?.name) { + return ( + option?.name?.toLowerCase().includes(input.toLowerCase()) || + option?.value?.toLowerCase().includes(input.toLowerCase()) + ); + } +} + onMounted(onGet); @@ -190,16 +198,20 @@ onMounted(onGet); - + ([]); +const jobArgsDisplayNameMap = ref>({}); const form = useTemplateRef('form'); const formModel = ref({} as BackgroundJobInfoDto); const { createApi, getApi, getDefinitionsApi, updateApi } = useJobInfosApi(); @@ -101,9 +105,9 @@ const [Drawer, drawerApi] = useVbenDrawer({ priority: JobPriority.Normal, } as BackgroundJobInfoDto; drawerApi.setState({ loading: true }); - const dto = drawerApi.getData(); - if (dto?.id) { - await onGet(dto.id); + const state = drawerApi.getData(); + if (state?.id) { + await onGet(state.id, state.isCopy); } else { await onInitDefaultJobs(); drawerApi.setState({ @@ -117,12 +121,23 @@ const [Drawer, drawerApi] = useVbenDrawer({ }, title: $t('BackgroundJobs:Edit'), }); -async function onGet(id: string) { + +async function onGet(id: string, isCopy?: boolean) { const dto = await getApi(id); + if (isCopy === true) { + dto.id = ''; + dto.name = ''; + dto.source = JobSource.User; + drawerApi.setState({ + title: $t('TaskManagement.BackgroundJobs:AddNew'), + }); + await onInitDefaultJobs(); + } else { + drawerApi.setState({ + title: `${$t('TaskManagement.BackgroundJobs:Edit')} - ${dto.name}`, + }); + } formModel.value = dto; - drawerApi.setState({ - title: `${$t('TaskManagement.BackgroundJobs:Edit')} - ${dto.name}`, - }); } async function onInitDefaultJobs() { @@ -148,14 +163,18 @@ async function onSubmit() { function onJobDefineChange(jobName: string) { formModel.value.args = {}; + jobArgsDisplayNameMap.value = {}; const jobDefine = jobDefinetions.value.find((x) => x.name === jobName); if (jobDefine) { const params: Record = {}; + const paramDisplayNames: Record = {}; jobDefine.paramters.forEach((param) => { params[param.name] = undefined; + paramDisplayNames[param.name] = param.displayName; }); formModel.value.args = params; formModel.value.type = jobDefine.name; + jobArgsDisplayNameMap.value = paramDisplayNames; } } @@ -206,6 +225,7 @@ function onDeleteParam(record: JobParamter) { > @@ -217,6 +237,7 @@ function onDeleteParam(record: JobParamter) { > @@ -228,6 +249,7 @@ function onDeleteParam(record: JobParamter) { > @@ -241,6 +263,7 @@ function onDeleteParam(record: JobParamter) { @@ -280,7 +303,16 @@ function onDeleteParam(record: JobParamter) { /> + + + diff --git a/apps/vben5/packages/@abp/tasks/src/components/job-infos/JobInfoTable.vue b/apps/vben5/packages/@abp/tasks/src/components/job-infos/JobInfoTable.vue index f656debe9..583194136 100644 --- a/apps/vben5/packages/@abp/tasks/src/components/job-infos/JobInfoTable.vue +++ b/apps/vben5/packages/@abp/tasks/src/components/job-infos/JobInfoTable.vue @@ -16,6 +16,7 @@ import { $t } from '@vben/locales'; import { formatToDateTime } from '@abp/core'; import { useVbenVxeGrid } from '@abp/ui'; import { + CopyOutlined, DeleteOutlined, EditOutlined, EllipsisOutlined, @@ -25,6 +26,7 @@ import { Button, Dropdown, Menu, + MenuDivider, MenuItem, message, Modal, @@ -515,6 +517,14 @@ function onBulkStart() { function onMenuClick(row: BackgroundJobInfoDto, info: MenuInfo) { switch (info.key) { + case 'copy': { + jobDrawerApi.setData({ + ...row, + isCopy: true, + }); + jobDrawerApi.open(); + break; + } case 'pause': { onJobStatusChange( row, @@ -722,6 +732,14 @@ function onJobStatusChange( > {{ $t('TaskManagement.BackgroundJobs:Stop') }} + + + {{ $t('TaskManagement.BackgroundJobs:Copy') }} + diff --git a/apps/vben5/packages/@abp/tasks/src/types/job-infos.ts b/apps/vben5/packages/@abp/tasks/src/types/job-infos.ts index bb519da26..82b3eaa9c 100644 --- a/apps/vben5/packages/@abp/tasks/src/types/job-infos.ts +++ b/apps/vben5/packages/@abp/tasks/src/types/job-infos.ts @@ -35,8 +35,7 @@ enum JobSource { } interface BackgroundJobInfoDto - extends ExtensibleAuditedEntityDto, - IHasConcurrencyStamp { + extends ExtensibleAuditedEntityDto, IHasConcurrencyStamp { args: Record; beginTime: string; cron?: string; @@ -53,6 +52,7 @@ interface BackgroundJobInfoDto maxTryCount: number; name: string; nextRunTime?: string; + nodeName?: string; priority: JobPriority; result?: string; source: JobSource; @@ -75,8 +75,7 @@ interface BackgroundJobInfoCreateOrUpdateDto { priority: JobPriority; } -interface BackgroundJobInfoCreateDto - extends BackgroundJobInfoCreateOrUpdateDto { +interface BackgroundJobInfoCreateDto extends BackgroundJobInfoCreateOrUpdateDto { beginTime: string; endTime?: string; group: string; @@ -87,8 +86,7 @@ interface BackgroundJobInfoCreateDto } interface BackgroundJobInfoUpdateDto - extends BackgroundJobInfoCreateOrUpdateDto, - IHasConcurrencyStamp {} + extends BackgroundJobInfoCreateOrUpdateDto, IHasConcurrencyStamp {} interface BackgroundJobInfoGetListInput extends PagedAndSortedResultRequestDto { beginCreationTime?: Date; diff --git a/apps/vben5/packages/@abp/ui/src/components/properties/PropertyTable.vue b/apps/vben5/packages/@abp/ui/src/components/properties/PropertyTable.vue index 1a7d9e1f2..7f7819829 100644 --- a/apps/vben5/packages/@abp/ui/src/components/properties/PropertyTable.vue +++ b/apps/vben5/packages/@abp/ui/src/components/properties/PropertyTable.vue @@ -46,7 +46,7 @@ const getTableColumns = computed((): TableColumnsType => { { align: 'left', dataIndex: 'key', - width: 100, + width: 150, title: $t('component.extra_property_dictionary.key'), customRender: (opt) => { if (props.renderKey && isFunction(props.renderKey)) { @@ -121,7 +121,16 @@ function onChange(prop: Record) { - + + + {{ record.key }} + {{ props.displayNameMap[record.key] }} + + + + ; disabled?: boolean; + displayNameMap?: Dictionary; renderKey?: (key: string) => string | VNode; } diff --git a/apps/vben5/packages/@abp/wechat/src/components/bind-user/index.vue b/apps/vben5/packages/@abp/wechat/src/components/bind-user/index.vue index bd5d15688..ae96254eb 100644 --- a/apps/vben5/packages/@abp/wechat/src/components/bind-user/index.vue +++ b/apps/vben5/packages/@abp/wechat/src/components/bind-user/index.vue @@ -3,11 +3,13 @@ import { useTemplateRef } from 'vue'; import { useVbenModal } from '@vben/common-ui'; -import { buildUUID } from '@abp/core'; +import { buildUUID, useFeatures } from '@abp/core'; import { WWLoginRedirectType, WWLoginType } from '@wecom/jssdk'; import * as ww from '@wecom/jssdk'; +import { Empty } from 'ant-design-vue'; import { userWorkWeixinJsSdkApi } from '../../api/userWorkWeixinJsSdkApi'; +import { WeixinWorkAuthEnable } from '../../constants/features'; const emits = defineEmits<{ /** @@ -18,6 +20,7 @@ const emits = defineEmits<{ }>(); const wxLoginRef = useTemplateRef('wxLogin'); +const { isEnabled } = useFeatures(); const { getAgentConfigApi } = userWorkWeixinJsSdkApi(); const [Modal, modalApi] = useVbenModal({ @@ -54,7 +57,15 @@ async function onInitLogin() { - + + diff --git a/apps/vben5/packages/@abp/wechat/src/constants/features.ts b/apps/vben5/packages/@abp/wechat/src/constants/features.ts new file mode 100644 index 000000000..bab96f2c5 --- /dev/null +++ b/apps/vben5/packages/@abp/wechat/src/constants/features.ts @@ -0,0 +1,2 @@ +/** 启用企业微信认证 */ +export const WeixinWorkAuthEnable = 'Abp.Account.OAuth.WeCom.Enable'; diff --git a/aspnet-core/LINGYUN.MicroService.All.slnx b/aspnet-core/LINGYUN.MicroService.All.slnx index 64367e62e..018ed8791 100644 --- a/aspnet-core/LINGYUN.MicroService.All.slnx +++ b/aspnet-core/LINGYUN.MicroService.All.slnx @@ -8,6 +8,7 @@ + diff --git a/aspnet-core/LINGYUN.MicroService.Aspire.slnx b/aspnet-core/LINGYUN.MicroService.Aspire.slnx index f247470fb..bf4fcb03f 100644 --- a/aspnet-core/LINGYUN.MicroService.Aspire.slnx +++ b/aspnet-core/LINGYUN.MicroService.Aspire.slnx @@ -1,6 +1,7 @@ + @@ -318,7 +319,9 @@ + + @@ -459,6 +462,9 @@ + + + @@ -495,6 +501,7 @@ + @@ -572,6 +579,7 @@ + diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService/AIServiceModule.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService/AIServiceModule.cs index 148ceb0c3..25cf39627 100644 --- a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService/AIServiceModule.cs +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService/AIServiceModule.cs @@ -14,6 +14,7 @@ using LINGYUN.Abp.EventBus.CAP; using LINGYUN.Abp.ExceptionHandling.Emailing; using LINGYUN.Abp.Identity.Session.AspNetCore; using LINGYUN.Abp.Localization.CultureMap; +using LINGYUN.Abp.LocalizationManagement.EntityFrameworkCore; using LINGYUN.Abp.Logging.Serilog.Elasticsearch; using LINGYUN.Abp.Serilog.Enrichers.Application; using LINGYUN.Abp.Serilog.Enrichers.UniqueId; @@ -57,6 +58,7 @@ namespace LINGYUN.Abp.MicroService.AIService; typeof(AbpAIManagementApplicationModule), typeof(AbpAIManagementHttpApiModule), typeof(AIServiceMigrationsEntityFrameworkCoreModule), + typeof(AbpLocalizationManagementEntityFrameworkCoreModule), typeof(AbpDataDbMigratorModule), typeof(AbpAspNetCoreAuthenticationJwtBearerModule), typeof(AbpEmailingExceptionHandlingModule), diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService/appsettings.Development.json b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService/appsettings.Development.json index 095e88d8f..efa09e2e7 100644 --- a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService/appsettings.Development.json +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AIService/appsettings.Development.json @@ -35,7 +35,8 @@ "CollectorCleaningInterval": 3600000 }, "PostgreSql": { - "TableNamePrefix": "admin", + "Schema": "ai", + "TableNamePrefix": "ai", "ConnectionString": "Host=127.0.0.1;Database=abp;Username=postgres;Password=123456" }, "RabbitMQ": { diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AdminService.EntityFrameworkCore/AdminServiceDataSeeder.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AdminService.EntityFrameworkCore/AdminServiceDataSeeder.cs index a94e9bc6d..49ca51707 100644 --- a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AdminService.EntityFrameworkCore/AdminServiceDataSeeder.cs +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AdminService.EntityFrameworkCore/AdminServiceDataSeeder.cs @@ -7,6 +7,7 @@ using Volo.Abp.Data; using Volo.Abp.DependencyInjection; using Volo.Abp.MultiTenancy; using Volo.Abp.PermissionManagement; +using Volo.Abp.Roles; namespace LINGYUN.Abp.MicroService.AdminService; public class AdminServiceDataSeeder : ITransientDependency @@ -49,7 +50,7 @@ public class AdminServiceDataSeeder : ITransientDependency await PermissionDataSeeder.SeedAsync( RolePermissionValueProvider.ProviderName, - "admin", + AbpRoleConsts.AdminRoleName, permissionNames, context?.TenantId ); diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AdminService/appsettings.Development.json b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AdminService/appsettings.Development.json index b49b3ff7f..7901df684 100644 --- a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AdminService/appsettings.Development.json +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AdminService/appsettings.Development.json @@ -27,6 +27,7 @@ "CollectorCleaningInterval": 3600000 }, "PostgreSql": { + "Schema": "admin", "TableNamePrefix": "admin", "ConnectionString": "Host=127.0.0.1;Database=abp;Username=postgres;Password=123456" }, diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.ApiGateway/yarp.json b/aspnet-core/aspire/LINGYUN.Abp.MicroService.ApiGateway/yarp.json index 0b523b419..4d6c69e54 100644 --- a/aspnet-core/aspire/LINGYUN.Abp.MicroService.ApiGateway/yarp.json +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.ApiGateway/yarp.json @@ -143,6 +143,21 @@ } ] }, + "gdpr-route": { + "ClusterId": "identity-service-cluster", + "Match": { + "Path": "/api/gdpr/{**everything}" + }, + "Transforms": [ + { + "HeaderPrefix": "X-Forwarded-", + "X-Forwarded": "Append" + }, + { + "ResponseHeadersAllowed": "_AbpWrapResult;_AbpDontWrapResult;_AbpErrorFormat" + } + ] + }, "identity-server-route": { "ClusterId": "identity-service-cluster", "Match": { @@ -293,6 +308,21 @@ } ] }, + "setting-management-v2-route": { + "ClusterId": "admin-service-cluster", + "Match": { + "Path": "/api/v2/setting-management/{**everything}" + }, + "Transforms": [ + { + "HeaderPrefix": "X-Forwarded-", + "X-Forwarded": "Append" + }, + { + "ResponseHeadersAllowed": "_AbpWrapResult;_AbpDontWrapResult;_AbpErrorFormat" + } + ] + }, "localization-management-route": { "ClusterId": "localization-service-cluster", "Match": { diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AppHost/AppHost.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AppHost/AppHost.cs index cf5b01b09..203b63814 100644 --- a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AppHost/AppHost.cs +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AppHost/AppHost.cs @@ -5,7 +5,8 @@ var builder = DistributedApplication.CreateBuilder(args); // Redis var redis = builder.AddRedis("redis", password: builder.AddParameter("redis-password", "123456", secret: true)) - .WithContainerName("redis") + .WithContainerName("redis-aspire") + .WithImageTag("8.0.2") .WithDataVolume("redis-dev"); if (builder.Environment.IsDevelopment()) @@ -16,8 +17,9 @@ if (builder.Environment.IsDevelopment()) } // Elasticsearch -var elasticsearch = builder.AddElasticsearch("elasticsearch") - .WithContainerName("elasticsearch") +var elasticsearch = builder.AddElasticsearch("elasticsearch", + password: builder.AddParameter("elasticsearch-password", "123456", secret: true)) + .WithContainerName("elasticsearch-aspire") .WithImageTag("8.17.3") .WithDataVolume("elasticsearch-dev") .WithEnvironment("ES_JAVA_OPTS", "-Xms2g -Xmx2g") @@ -26,15 +28,17 @@ var elasticsearch = builder.AddElasticsearch("elasticsearch") // Kibana builder.AddContainer("kibana", "kibana", "8.17.3") + .WithContainerName("kibana-aspire") .WithReference(elasticsearch) .WithEndpoint(5601, 5601) .WaitFor(elasticsearch); // Postgres -var postgres = builder.AddPostgres("postgres") - .WithPassword(builder.AddParameter("postgres-pwd", "123456", secret: true)) +var postgres = builder.AddPostgres("postgres", + userName: builder.AddParameter("postgres-username", "postgres", secret: true), + password: builder.AddParameter("postgres-pwd", "123456", secret: true)) .WithImage("postgres", "17-alpine") - .WithContainerName("postgres") + .WithContainerName("postgres-aspire") .WithDataVolume("postgres-dev"); var abpDb = postgres.AddDatabase("abp"); @@ -43,7 +47,8 @@ var abpDb = postgres.AddDatabase("abp"); var rabbitmq = builder.AddRabbitMQ("rabbitmq", userName: builder.AddParameter("rabbitmq-username", "admin", secret: true), password: builder.AddParameter("rabbitmq-password", "123456", secret: true)) - .WithContainerName("rabbitmq") + .WithContainerName("rabbitmq-aspire") + .WithImageTag("3.13.1") .WithDataVolume("rabbitmq-dev") .WithManagementPlugin(); diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer.EntityFrameworkCore/DataSeeds/OpenIddictDataSeeder.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer.EntityFrameworkCore/DataSeeds/OpenIddictDataSeeder.cs index f19bb7e10..29398ecb0 100644 --- a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer.EntityFrameworkCore/DataSeeds/OpenIddictDataSeeder.cs +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer.EntityFrameworkCore/DataSeeds/OpenIddictDataSeeder.cs @@ -478,7 +478,9 @@ public class OpenIddictDataSeeder : OpenIddictDataSeedContributorBase, ITransien [OpenIddictConstants.GrantTypes.AuthorizationCode, OpenIddictConstants.GrantTypes.Implicit, OpenIddictConstants.GrantTypes.Password, - OpenIddictConstants.GrantTypes.RefreshToken], + OpenIddictConstants.GrantTypes.RefreshToken, + // TODO: 引用项目? + "link_user"], [OpenIddictConstants.Scopes.OpenId, OpenIddictConstants.Scopes.Email, OpenIddictConstants.Scopes.Roles, @@ -540,7 +542,9 @@ public class OpenIddictDataSeeder : OpenIddictDataSeedContributorBase, ITransien "Abp OAuth Client", null, [OpenIddictConstants.GrantTypes.AuthorizationCode, - OpenIddictConstants.GrantTypes.RefreshToken], + OpenIddictConstants.GrantTypes.RefreshToken, + // TODO: 引用项目? + "link_user"], [OpenIddictConstants.Scopes.OpenId, OpenIddictConstants.Scopes.Email, OpenIddictConstants.Scopes.Roles, diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer/appsettings.Development.json b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer/appsettings.Development.json index 4714cca37..e0ab7ab27 100644 --- a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer/appsettings.Development.json +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer/appsettings.Development.json @@ -58,6 +58,7 @@ "CollectorCleaningInterval": 3600000 }, "PostgreSql": { + "Schema": "auth", "TableNamePrefix": "auth", "ConnectionString": "Host=localhost;Database=abp;Username=postgres;Password=123456" }, diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer/package.json b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer/package.json index 9c6413220..25ada3235 100644 --- a/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer/package.json +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.AuthServer/package.json @@ -1,9 +1,9 @@ { - "version": "10.2.0", - "name": "my-app-authserver", + "version": "10.4.0", + "name": "aspire-authserver", "private": true, "dependencies": { - "@abp/aspnetcore.mvc.ui.theme.leptonxlite": "5.2.0", - "@abp/qrcode": "10.2.0" + "@abp/aspnetcore.mvc.ui.theme.leptonxlite": "5.4.0", + "@abp/qrcode": "10.4.0" } } \ No newline at end of file diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.IdentityService/appsettings.Development.json b/aspnet-core/aspire/LINGYUN.Abp.MicroService.IdentityService/appsettings.Development.json index 8d1c4cecd..fbc9c877b 100644 --- a/aspnet-core/aspire/LINGYUN.Abp.MicroService.IdentityService/appsettings.Development.json +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.IdentityService/appsettings.Development.json @@ -47,6 +47,7 @@ "CollectorCleaningInterval": 3600000 }, "PostgreSql": { + "Schema": "ida", "TableNamePrefix": "ida", "ConnectionString": "Host=127.0.0.1;Database=abp;Username=postgres;Password=123456" }, diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.LocalizationService/LocalizationServiceModule.Configure.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.LocalizationService/LocalizationServiceModule.Configure.cs index e1b21d7a1..fcc5889ed 100644 --- a/aspnet-core/aspire/LINGYUN.Abp.MicroService.LocalizationService/LocalizationServiceModule.Configure.cs +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.LocalizationService/LocalizationServiceModule.Configure.cs @@ -250,6 +250,14 @@ public partial class LocalizationServiceModule }); } + private void PreConfigureLocalization() + { + Configure(options => + { + options.IsDynamicLocalizationInitializerHost = true; + }); + } + private void ConfigureLocalization() { // 默认支持的本地化语言类型 diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.LocalizationService/LocalizationServiceModule.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.LocalizationService/LocalizationServiceModule.cs index 4f8fdca08..57775d94d 100644 --- a/aspnet-core/aspire/LINGYUN.Abp.MicroService.LocalizationService/LocalizationServiceModule.cs +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.LocalizationService/LocalizationServiceModule.cs @@ -70,6 +70,7 @@ public partial class LocalizationServiceModule : AbpModule PreConfigureWrapper(); PreConfigureFeature(); PreForwardedHeaders(); + PreConfigureLocalization(); PreConfigureApp(configuration); PreConfigureCAP(configuration); } diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.LocalizationService/appsettings.Development.json b/aspnet-core/aspire/LINGYUN.Abp.MicroService.LocalizationService/appsettings.Development.json index f913efab6..3acfe1ef5 100644 --- a/aspnet-core/aspire/LINGYUN.Abp.MicroService.LocalizationService/appsettings.Development.json +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.LocalizationService/appsettings.Development.json @@ -27,6 +27,7 @@ "CollectorCleaningInterval": 3600000 }, "PostgreSql": { + "Schema": "lta", "TableNamePrefix": "lta", "ConnectionString": "Host=127.0.0.1;Database=abp;Username=postgres;Password=123456" }, diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService.EntityFrameworkCore/DataSeeds/NotificationDataSeeder.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService.EntityFrameworkCore/DataSeeds/NotificationDataSeeder.cs new file mode 100644 index 000000000..bd9c2b459 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService.EntityFrameworkCore/DataSeeds/NotificationDataSeeder.cs @@ -0,0 +1,120 @@ +using LINGYUN.Abp.Notifications; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Volo.Abp.Data; +using Volo.Abp.DependencyInjection; +using Volo.Abp.MultiTenancy; +using Volo.Abp.Users; + +namespace LINGYUN.Abp.MicroService.MessageService.DataSeeds; + +public class NotificationDataSeeder : ITransientDependency +{ + public ILogger Logger { protected get; set; } + protected INotificationSender NotificationSender { get; } + protected INotificationSubscriptionManager NotificationSubscriptionManager { get; } + public NotificationDataSeeder( + INotificationSender notificationSender, + INotificationSubscriptionManager notificationSubscriptionManager) + { + NotificationSender = notificationSender; + NotificationSubscriptionManager = notificationSubscriptionManager; + + Logger = NullLogger.Instance; + } + + public virtual async Task SeedAsync(DataSeedContext context) + { + await SubscribeDefaultNotifierAsync(context); + await SeedWelcomeNotifierAsync(context); + } + + public async virtual Task SubscribeDefaultNotifierAsync(DataSeedContext context) + { + if (!context.Properties.TryGetValue(MessageServiceDataSeedConsts.AdminUserIdPropertyName, out var userIdString) || + !Guid.TryParse(userIdString?.ToString(), out var adminUserId)) + { + + return; + } + var adminUserName = context.Properties.GetOrDefault(MessageServiceDataSeedConsts.AdminUserNamePropertyName)?.ToString() + ?? MessageServiceDataSeedConsts.AdminUserNameDefaultValue; + var userIdentifer = new UserIdentifier(adminUserId, adminUserName); + // 订阅内置通知 + await NotificationSubscriptionManager + .SubscribeAsync( + context.TenantId, + userIdentifer, + DefaultNotifications.SystemNotice); + await NotificationSubscriptionManager + .SubscribeAsync( + context.TenantId, + userIdentifer, + DefaultNotifications.OnsideNotice); + await NotificationSubscriptionManager + .SubscribeAsync( + context.TenantId, + userIdentifer, + DefaultNotifications.ActivityNotice); + // 订阅用户欢迎消息 + await NotificationSubscriptionManager + .SubscribeAsync( + context.TenantId, + userIdentifer, + UserNotificationNames.WelcomeToApplication); + } + + public async virtual Task SeedWelcomeNotifierAsync(DataSeedContext context) + { + try + { + if (!context.TenantId.HasValue) + { + return; + } + if (!context.Properties.TryGetValue(MessageServiceDataSeedConsts.AdminUserIdPropertyName, out var userIdString) || + !Guid.TryParse(userIdString?.ToString(), out var adminUserId)) + { + return; + } + var adminEmailAddress = context.Properties.GetOrDefault(MessageServiceDataSeedConsts.AdminEmailPropertyName)?.ToString() + ?? MessageServiceDataSeedConsts.AdminEmailDefaultValue; + var adminUserName = context.Properties.GetOrDefault(MessageServiceDataSeedConsts.AdminUserNamePropertyName)?.ToString() + ?? MessageServiceDataSeedConsts.AdminUserNameDefaultValue; + + var tenantAdminUserIdentifier = new UserIdentifier(adminUserId, adminEmailAddress); + + // 租户管理员订阅事件 + await NotificationSubscriptionManager + .SubscribeAsync( + context.TenantId, + tenantAdminUserIdentifier, + TenantNotificationNames.NewTenantRegistered); + + Logger.LogInformation("publish new tenant notification.."); + await NotificationSender.SendNofiterAsync( + TenantNotificationNames.NewTenantRegistered, + new NotificationTemplate( + TenantNotificationNames.NewTenantRegistered, + formUser: adminEmailAddress, + data: new Dictionary + { + { "name", adminUserName }, + { "email", adminEmailAddress }, + { "id", context.TenantId }, + }), + tenantAdminUserIdentifier, + context.TenantId, + NotificationSeverity.Success); + + Logger.LogInformation("tenant administrator subscribes to new tenant events.."); + } + catch (Exception ex) + { + Logger.LogWarning(ex, "Failed to send the tenant initialization notification."); + } + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService.EntityFrameworkCore/MessageServiceDataSeedConsts.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService.EntityFrameworkCore/MessageServiceDataSeedConsts.cs new file mode 100644 index 000000000..1815d1ddf --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService.EntityFrameworkCore/MessageServiceDataSeedConsts.cs @@ -0,0 +1,10 @@ +namespace LINGYUN.Abp.MicroService.MessageService; + +public static class MessageServiceDataSeedConsts +{ + public const string AdminUserIdPropertyName = "AdminUserId"; + public const string AdminEmailPropertyName = "AdminEmail"; + public const string AdminEmailDefaultValue = "admin@abp.io"; + public const string AdminUserNamePropertyName = "AdminUserName"; + public const string AdminUserNameDefaultValue = "admin"; +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService.EntityFrameworkCore/MessageServiceDataSeeder.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService.EntityFrameworkCore/MessageServiceDataSeeder.cs new file mode 100644 index 000000000..abdf14609 --- /dev/null +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService.EntityFrameworkCore/MessageServiceDataSeeder.cs @@ -0,0 +1,33 @@ +using LINGYUN.Abp.MicroService.MessageService.DataSeeds; +using System.Threading.Tasks; +using Volo.Abp.Data; +using Volo.Abp.DependencyInjection; +using Volo.Abp.MultiTenancy; + +namespace LINGYUN.Abp.MicroService.MessageService; + +public class MessageServiceDataSeeder : ITransientDependency +{ + protected NotificationDataSeeder NotificationDataSeeder { get; } + protected ICurrentTenant CurrentTenant { get; } + public MessageServiceDataSeeder( + ICurrentTenant currentTenant, + NotificationDataSeeder notificationDataSeeder) + { + CurrentTenant = currentTenant; + NotificationDataSeeder = notificationDataSeeder; + } + + public async virtual Task SeedAsync(DataSeedContext context) + { + using (CurrentTenant.Change(context.TenantId)) + { + await SeedNotificationAsync(context); + } + } + + private async Task SeedNotificationAsync(DataSeedContext context) + { + await NotificationDataSeeder.SeedAsync(context); + } +} diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService.EntityFrameworkCore/MessageServiceDbMigrationEventHandler.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService.EntityFrameworkCore/MessageServiceDbMigrationEventHandler.cs index 4b28e3993..d3ec88822 100644 --- a/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService.EntityFrameworkCore/MessageServiceDbMigrationEventHandler.cs +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService.EntityFrameworkCore/MessageServiceDbMigrationEventHandler.cs @@ -1,7 +1,4 @@ -using LINGYUN.Abp.Notifications; -using Microsoft.Extensions.Logging; -using System; -using System.Collections.Generic; +using Microsoft.Extensions.Logging; using System.Threading.Tasks; using Volo.Abp.Data; using Volo.Abp.DistributedLocking; @@ -13,8 +10,7 @@ using Volo.Abp.Uow; namespace LINGYUN.Abp.MicroService.MessageService; public class MessageServiceDbMigrationEventHandler : EfCoreDatabaseMigrationEventHandlerBase { - protected INotificationSender NotificationSender { get; } - protected INotificationSubscriptionManager NotificationSubscriptionManager { get; } + protected MessageServiceDataSeeder MessageServiceDataSeeder { get; } public MessageServiceDbMigrationEventHandler( ICurrentTenant currentTenant, @@ -23,65 +19,27 @@ public class MessageServiceDbMigrationEventHandler : EfCoreDatabaseMigrationEven IAbpDistributedLock abpDistributedLock, IDistributedEventBus distributedEventBus, ILoggerFactory loggerFactory, - INotificationSender notificationSender, - INotificationSubscriptionManager notificationSubscriptionManager) + MessageServiceDataSeeder messageServiceDataSeeder) : base( ConnectionStringNameAttribute.GetConnStringName(), currentTenant, unitOfWorkManager, tenantStore, abpDistributedLock, distributedEventBus, loggerFactory) { - NotificationSender = notificationSender; - NotificationSubscriptionManager = notificationSubscriptionManager; + MessageServiceDataSeeder = messageServiceDataSeeder; } protected async override Task AfterTenantCreated(TenantCreatedEto eventData, bool schemaMigrated) { using (CurrentTenant.Change(eventData.Id)) { - await SendNotificationAsync(eventData); - } - } - - protected async virtual Task SendNotificationAsync(TenantCreatedEto eventData) - { - try - { - if (!eventData.Properties.TryGetValue("AdminUserId", out var userIdString) || - !Guid.TryParse(userIdString, out var adminUserId)) + var context = new DataSeedContext(eventData.Id); + if (eventData.Properties != null) { - return; + foreach (var prop in eventData.Properties) + { + context.WithProperty(prop.Key, prop.Value); + } } - var adminEmailAddress = eventData.Properties.GetOrDefault("AdminEmail") ?? "admin@abp.io"; - - var tenantAdminUserIdentifier = new UserIdentifier(adminUserId, adminEmailAddress); - - // 租户管理员订阅事件 - await NotificationSubscriptionManager - .SubscribeAsync( - eventData.Id, - tenantAdminUserIdentifier, - TenantNotificationNames.NewTenantRegistered); - - Logger.LogInformation("publish new tenant notification.."); - await NotificationSender.SendNofiterAsync( - TenantNotificationNames.NewTenantRegistered, - new NotificationTemplate( - TenantNotificationNames.NewTenantRegistered, - formUser: adminEmailAddress, - data: new Dictionary - { - { "name", eventData.Name }, - { "email", adminEmailAddress }, - { "id", eventData.Id }, - }), - tenantAdminUserIdentifier, - eventData.Id, - NotificationSeverity.Success); - - Logger.LogInformation("tenant administrator subscribes to new tenant events.."); - } - catch (Exception ex) - { - Logger.LogWarning(ex, "Failed to send the tenant initialization notification."); + await MessageServiceDataSeeder.SeedAsync(context); } } } diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService.EntityFrameworkCore/MessageServiceDbMigrationService.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService.EntityFrameworkCore/MessageServiceDbMigrationService.cs index 53b74d610..510b9fded 100644 --- a/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService.EntityFrameworkCore/MessageServiceDbMigrationService.cs +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService.EntityFrameworkCore/MessageServiceDbMigrationService.cs @@ -1,6 +1,7 @@ using LINGYUN.Abp.Data.DbMigrator; using Microsoft.Extensions.Logging; using System; +using System.Threading.Tasks; using Volo.Abp.Data; using Volo.Abp.DependencyInjection; using Volo.Abp.DistributedLocking; @@ -11,7 +12,9 @@ using Volo.Abp.Uow; namespace LINGYUN.Abp.MicroService.MessageService; public class MessageServiceDbMigrationService : EfCoreRuntimeDbMigratorBase, ITransientDependency { + protected MessageServiceDataSeeder DataSeeder { get; } public MessageServiceDbMigrationService( + MessageServiceDataSeeder dataSeeder, ICurrentTenant currentTenant, IUnitOfWorkManager unitOfWorkManager, IServiceProvider serviceProvider, @@ -22,5 +25,12 @@ public class MessageServiceDbMigrationService : EfCoreRuntimeDbMigratorBase(), unitOfWorkManager, serviceProvider, currentTenant, abpDistributedLock, distributedEventBus, loggerFactory) { + DataSeeder = dataSeeder; + } + + protected async override Task SeedAsync() + { + // DbMigrator迁移数据种子 + await DataSeeder.SeedAsync(new DataSeedContext()); } } diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService/appsettings.Development.json b/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService/appsettings.Development.json index 322085e37..5748c62fd 100644 --- a/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService/appsettings.Development.json +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.MessageService/appsettings.Development.json @@ -93,6 +93,7 @@ "CollectorCleaningInterval": 3600000 }, "PostgreSql": { + "Schema": "msg", "TableNamePrefix": "msg", "ConnectionString": "Host=127.0.0.1;Database=abp;Username=postgres;Password=123456" }, diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService/LINGYUN.Abp.MicroService.PlatformService.csproj b/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService/LINGYUN.Abp.MicroService.PlatformService.csproj index a78d6306b..740263e9f 100644 --- a/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService/LINGYUN.Abp.MicroService.PlatformService.csproj +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService/LINGYUN.Abp.MicroService.PlatformService.csproj @@ -56,6 +56,7 @@ + diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService/PlatformServiceModule.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService/PlatformServiceModule.cs index 640aa685b..e2884068e 100644 --- a/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService/PlatformServiceModule.cs +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService/PlatformServiceModule.cs @@ -6,6 +6,7 @@ using LINGYUN.Abp.Authorization.OrganizationUnits; using LINGYUN.Abp.BlobManagement; using LINGYUN.Abp.BlobManagement.Aliyun; using LINGYUN.Abp.BlobManagement.FileSystem; +using LINGYUN.Abp.BlobManagement.MimeCheck; using LINGYUN.Abp.BlobManagement.Minio; using LINGYUN.Abp.BlobManagement.Tencent; using LINGYUN.Abp.BlobStoring.BlobManagement; @@ -62,6 +63,7 @@ namespace LINGYUN.Abp.MicroService.PlatformService; typeof(AbpBlobManagementMinioModule), typeof(AbpBlobManagementTencentModule), typeof(AbpBlobManagementHttpApiModule), + typeof(AbpBlobManagementMimeCheckModule), typeof(AbpBlobStoringBlobManagementModule), typeof(AbpImagingImageSharpModule), diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService/appsettings.Development.json b/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService/appsettings.Development.json index 36fc4412c..f9fe8b0e8 100644 --- a/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService/appsettings.Development.json +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.PlatformService/appsettings.Development.json @@ -58,6 +58,7 @@ "CollectorCleaningInterval": 3600000 }, "PostgreSql": { + "Schema": "plt", "TableNamePrefix": "plt", "ConnectionString": "Host=127.0.0.1;Database=abp;Username=postgres;Password=123456" }, diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.TaskService/appsettings.Development.json b/aspnet-core/aspire/LINGYUN.Abp.MicroService.TaskService/appsettings.Development.json index c1a475ebb..2937a93de 100644 --- a/aspnet-core/aspire/LINGYUN.Abp.MicroService.TaskService/appsettings.Development.json +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.TaskService/appsettings.Development.json @@ -24,6 +24,7 @@ "CollectorCleaningInterval": 3600000 }, "PostgreSql": { + "Schema": "tsk", "TableNamePrefix": "tsk", "ConnectionString": "Host=127.0.0.1;Database=abp;Username=postgres;Password=123456" }, diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.WeChatService/WeChatServiceModule.Configure.cs b/aspnet-core/aspire/LINGYUN.Abp.MicroService.WeChatService/WeChatServiceModule.Configure.cs index 82fcc92ca..f7ccc8cfa 100644 --- a/aspnet-core/aspire/LINGYUN.Abp.MicroService.WeChatService/WeChatServiceModule.Configure.cs +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.WeChatService/WeChatServiceModule.Configure.cs @@ -280,6 +280,7 @@ public partial class WeChatServiceModule Configure(options => { options.IsDynamicFeatureStoreEnabled = true; + options.SaveStaticFeaturesToDatabase = true; }); } @@ -288,7 +289,7 @@ public partial class WeChatServiceModule Configure(options => { options.IsDynamicPermissionStoreEnabled = true; - options.SaveStaticPermissionsToDatabase = false; + options.SaveStaticPermissionsToDatabase = true; }); } @@ -297,6 +298,7 @@ public partial class WeChatServiceModule Configure(options => { options.IsDynamicSettingStoreEnabled = true; + options.SaveStaticSettingsToDatabase = true; }); } diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.WeChatService/appsettings.Development.json b/aspnet-core/aspire/LINGYUN.Abp.MicroService.WeChatService/appsettings.Development.json index cfd0b2c43..2cc43115c 100644 --- a/aspnet-core/aspire/LINGYUN.Abp.MicroService.WeChatService/appsettings.Development.json +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.WeChatService/appsettings.Development.json @@ -50,6 +50,7 @@ "FailedRetryCount": 10 }, "MySql": { + "Schema": "wechat", "TableNamePrefix": "wechat", "ConnectionString": "Host=127.0.0.1;Database=abp;Username=postgres;Password=123456" }, diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.WebhookService/appsettings.Development.json b/aspnet-core/aspire/LINGYUN.Abp.MicroService.WebhookService/appsettings.Development.json index 41e00a9bc..aab397c5b 100644 --- a/aspnet-core/aspire/LINGYUN.Abp.MicroService.WebhookService/appsettings.Development.json +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.WebhookService/appsettings.Development.json @@ -55,6 +55,7 @@ "FailedRetryCount": 10 }, "PostgreSql": { + "Schema": "wkm", "TableNamePrefix": "wkm", "ConnectionString": "Host=127.0.0.1;Database=abp;Username=postgres;Password=123456" }, diff --git a/aspnet-core/aspire/LINGYUN.Abp.MicroService.WorkflowService/appsettings.Development.json b/aspnet-core/aspire/LINGYUN.Abp.MicroService.WorkflowService/appsettings.Development.json index d7b7c1a12..9e4f85d16 100644 --- a/aspnet-core/aspire/LINGYUN.Abp.MicroService.WorkflowService/appsettings.Development.json +++ b/aspnet-core/aspire/LINGYUN.Abp.MicroService.WorkflowService/appsettings.Development.json @@ -136,6 +136,7 @@ "CollectorCleaningInterval": 3600000 }, "PostgreSql": { + "Schema": "wf", "TableNamePrefix": "wf", "ConnectionString": "Host=127.0.0.1;Database=abp;Username=postgres;Password=123456" }, diff --git a/aspnet-core/framework/common/LINGYUN.Abp.EventBus.CAP/LINGYUN/Abp/EventBus/CAP/CAPDistributedEventBus.cs b/aspnet-core/framework/common/LINGYUN.Abp.EventBus.CAP/LINGYUN/Abp/EventBus/CAP/CAPDistributedEventBus.cs index bf5f566be..899812e64 100644 --- a/aspnet-core/framework/common/LINGYUN.Abp.EventBus.CAP/LINGYUN/Abp/EventBus/CAP/CAPDistributedEventBus.cs +++ b/aspnet-core/framework/common/LINGYUN.Abp.EventBus.CAP/LINGYUN/Abp/EventBus/CAP/CAPDistributedEventBus.cs @@ -44,6 +44,10 @@ public class CAPDistributedEventBus : DistributedEventBusBase, IDistributedEvent /// protected ConcurrentDictionary> HandlerFactories { get; } /// + /// 本地动态事件处理器工厂对象集合 + /// + protected ConcurrentDictionary> DynamicHandlerFactories { get; } + /// /// 本地事件集合 /// protected ConcurrentDictionary EventTypes { get; } @@ -113,6 +117,7 @@ public class CAPDistributedEventBus : DistributedEventBusBase, IDistributedEvent JsonSerializer = jsonSerializer; CancellationTokenProvider = cancellationTokenProvider; CustomDistributedEventSubscriber = customDistributedEventSubscriber; + DynamicHandlerFactories = new ConcurrentDictionary>(); HandlerFactories = new ConcurrentDictionary>(); EventTypes = new ConcurrentDictionary(); } @@ -165,9 +170,7 @@ public class CAPDistributedEventBus : DistributedEventBusBase, IDistributedEvent /// protected override async Task PublishToEventBusAsync(Type eventType, object eventData) { - var eventName = EventNameAttribute.GetNameOrDefault(eventType); - - await PublishToCapAsync(eventName, eventData, messageId: null, correlationId: CorrelationIdProvider.Get()); + await PublishToCapAsync(eventType, eventData, messageId: null, correlationId: CorrelationIdProvider.Get()); } /// @@ -178,31 +181,24 @@ public class CAPDistributedEventBus : DistributedEventBusBase, IDistributedEvent protected override IEnumerable GetHandlerFactories(Type eventType) { var handlerFactoryList = new List(); + var eventNames = EventTypes.Where(x => ShouldTriggerEventForHandler(eventType, x.Value)).Select(x => x.Key).ToList(); foreach (var handlerFactory in HandlerFactories.Where(hf => ShouldTriggerEventForHandler(eventType, hf.Key))) { handlerFactoryList.Add(new EventTypeWithEventHandlerFactories(handlerFactory.Key, handlerFactory.Value)); } - return handlerFactoryList.ToArray(); - } - - private static bool ShouldTriggerEventForHandler(Type targetEventType, Type handlerEventType) - { - //Should trigger same type - if (handlerEventType == targetEventType) + foreach (var handlerFactory in DynamicHandlerFactories.Where(aehf => eventNames.Contains(aehf.Key))) { - return true; + handlerFactoryList.Add(new EventTypeWithEventHandlerFactories(typeof(DynamicEventData), handlerFactory.Value)); } - //TODO: Support inheritance? But it does not support on subscription to RabbitMq! - //Should trigger for inherited types - if (handlerEventType.IsAssignableFrom(targetEventType)) - { - return true; - } + return handlerFactoryList.ToArray(); + } - return false; + protected override Type GetEventTypeByEventName(string eventName) + { + return EventTypes.GetOrDefault(eventName); } protected override byte[] Serialize(object eventData) @@ -242,20 +238,27 @@ public class CAPDistributedEventBus : DistributedEventBusBase, IDistributedEvent public override async Task ProcessFromInboxAsync(IncomingEventInfo incomingEvent, InboxConfig inboxConfig) { + var eventJson = Encoding.UTF8.GetString(incomingEvent.EventData); var eventType = EventTypes.GetOrDefault(incomingEvent.EventName); - if (eventType == null) + object eventData; + if (eventType != null) + { + eventData = JsonSerializer.Deserialize(eventType, eventJson); + } + else if (DynamicHandlerFactories.ContainsKey(incomingEvent.EventName)) + { + eventData = new DynamicEventData(incomingEvent.EventName, JsonSerializer.Deserialize(eventJson)); + eventType = typeof(DynamicEventData); + } + else { return; } - - var eventJson = Encoding.UTF8.GetString(incomingEvent.EventData); - var eventData = JsonSerializer.Deserialize(eventType, eventJson); var exceptions = new List(); using (CorrelationIdProvider.Change(incomingEvent.GetCorrelationId())) { await TriggerHandlersFromInboxAsync(eventType, eventData, exceptions, inboxConfig); } - if (exceptions.Any()) { ThrowOriginalExceptions(eventType, exceptions); @@ -264,7 +267,8 @@ public class CAPDistributedEventBus : DistributedEventBusBase, IDistributedEvent protected virtual async Task PublishToCapAsync(Type eventType, object eventData, Guid? messageId, string correlationId = null) { - await PublishToCapAsync(EventNameAttribute.GetNameOrDefault(eventType), eventData, null, correlationId); + var (eventName, resolvedData) = ResolveEventForPublishing(eventType, eventData); + await PublishToCapAsync(eventName, resolvedData, null, correlationId); } protected virtual async Task PublishToCapAsync(string eventName, object eventData, Guid? messageId, string correlationId = null) @@ -293,4 +297,73 @@ public class CAPDistributedEventBus : DistributedEventBusBase, IDistributedEvent await CapPublisher.PublishAsync(eventName, eventData, headers, CancellationTokenProvider.FallbackToProvider()); } + + public override IDisposable Subscribe(string eventName, IEventHandlerFactory handler) + { + return NullDisposable.Instance; + } + + public override void Unsubscribe(string eventName, IEventHandlerFactory factory) + { + + } + + public override void Unsubscribe(string eventName, IEventHandler handler) + { + + } + + public override void UnsubscribeAll(string eventName) + { + + } + + public override Task PublishAsync(string eventName, object eventData, bool onUnitOfWorkComplete = true) + { + var eventType = EventTypes.GetOrDefault(eventName); + var dynamicEventData = eventData as DynamicEventData ?? new DynamicEventData(eventName, eventData); + + if (eventType != null) + { + return PublishAsync(eventType, ConvertDynamicEventData(dynamicEventData.Data, eventType), onUnitOfWorkComplete); + } + + return PublishAsync(typeof(DynamicEventData), dynamicEventData, onUnitOfWorkComplete); + } + + protected override IEnumerable GetDynamicHandlerFactories(string eventName) + { + var result = new List(); + + var eventType = GetEventTypeByEventName(eventName); + if (eventType != null) + { + return GetHandlerFactories(eventType); + } + + foreach (var handlerFactory in DynamicHandlerFactories.Where(hf => hf.Key == eventName)) + { + result.Add(new EventTypeWithEventHandlerFactories(typeof(DynamicEventData), handlerFactory.Value)); + } + + return result; + } + + private static bool ShouldTriggerEventForHandler(Type targetEventType, Type handlerEventType) + { + //Should trigger same type + if (handlerEventType == targetEventType) + { + return true; + } + + //TODO: Support inheritance? But it does not support on subscription to RabbitMq! + //Should trigger for inherited types + if (handlerEventType.IsAssignableFrom(targetEventType)) + { + return true; + } + + return false; + } } diff --git a/aspnet-core/framework/telemetry/LINGYUN.Abp.Telemetry.OpenTelemetry/LINGYUN/Abp/Telemetry/OpenTelemetry/AbpTelemetryOpenTelemetryModule.cs b/aspnet-core/framework/telemetry/LINGYUN.Abp.Telemetry.OpenTelemetry/LINGYUN/Abp/Telemetry/OpenTelemetry/AbpTelemetryOpenTelemetryModule.cs index 67619eaed..d7921e72c 100644 --- a/aspnet-core/framework/telemetry/LINGYUN.Abp.Telemetry.OpenTelemetry/LINGYUN/Abp/Telemetry/OpenTelemetry/AbpTelemetryOpenTelemetryModule.cs +++ b/aspnet-core/framework/telemetry/LINGYUN.Abp.Telemetry.OpenTelemetry/LINGYUN/Abp/Telemetry/OpenTelemetry/AbpTelemetryOpenTelemetryModule.cs @@ -129,16 +129,16 @@ public class AbpTelemetryOpenTelemetryModule : AbpModule }); } - if (configuration.GetValue("OpenTelemetry:ZipKin:IsEnabled", false)) - { - tracing.AddZipkinExporter(zipKinOptions => - { - var zipkinEndPoint = configuration["OpenTelemetry:ZipKin:Endpoint"]; - Check.NotNullOrWhiteSpace(zipkinEndPoint, nameof(zipkinEndPoint)); - - zipKinOptions.Endpoint = new Uri(zipkinEndPoint); - }); - } + //if (configuration.GetValue("OpenTelemetry:ZipKin:IsEnabled", false)) + //{ + // tracing.AddZipkinExporter(zipKinOptions => + // { + // var zipkinEndPoint = configuration["OpenTelemetry:ZipKin:Endpoint"]; + // Check.NotNullOrWhiteSpace(zipkinEndPoint, nameof(zipkinEndPoint)); + + // zipKinOptions.Endpoint = new Uri(zipkinEndPoint); + // }); + //} } private static void ConfigureMetrics(MeterProviderBuilder metrics, IConfiguration configuration) diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Common/LINGYUN/Abp/WeChat/Common/Utils/Cryptography.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Common/LINGYUN/Abp/WeChat/Common/Utils/Cryptography.cs index a532e10e1..303bfbb5c 100644 --- a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Common/LINGYUN/Abp/WeChat/Common/Utils/Cryptography.cs +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Common/LINGYUN/Abp/WeChat/Common/Utils/Cryptography.cs @@ -97,7 +97,11 @@ public class Cryptography private static string AES_encrypt(string Input, byte[] Iv, byte[] Key) { +#if NET462 var aes = new RijndaelManaged(); +#else + var aes = Aes.Create(); +#endif //秘钥的大小,以位为单位 aes.KeySize = 256; //支持的块大小 @@ -125,7 +129,11 @@ public class Cryptography private static string AES_encrypt(byte[] Input, byte[] Iv, byte[] Key) { +#if NET462 var aes = new RijndaelManaged(); +#else + var aes = Aes.Create(); +#endif //秘钥的大小,以位为单位 aes.KeySize = 256; //支持的块大小 @@ -196,7 +204,11 @@ public class Cryptography } private static byte[] AES_decrypt(string Input, byte[] Iv, byte[] Key) { +#if NET462 var aes = new RijndaelManaged(); +#else + var aes = Aes.Create(); +#endif aes.KeySize = 256; aes.BlockSize = 128; aes.Mode = CipherMode.CBC; diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Common/LINGYUN/Abp/WeChat/Common/Utils/WXBizMsgCrypt.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Common/LINGYUN/Abp/WeChat/Common/Utils/WXBizMsgCrypt.cs index 62f8a177e..7a3262441 100644 --- a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Common/LINGYUN/Abp/WeChat/Common/Utils/WXBizMsgCrypt.cs +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Common/LINGYUN/Abp/WeChat/Common/Utils/WXBizMsgCrypt.cs @@ -241,10 +241,14 @@ public class WXBizMsgCrypt var hash = ""; try { +#if NET462 sha = new SHA1CryptoServiceProvider(); +#else + sha = SHA1.Create(); +#endif enc = new ASCIIEncoding(); - var dataToHash = enc.GetBytes(raw); - var dataHashed = sha.ComputeHash(dataToHash); + byte[] dataToHash = enc.GetBytes(raw); + byte[] dataHashed = sha.ComputeHash(dataToHash); hash = BitConverter.ToString(dataHashed).Replace("-", ""); hash = hash.ToLower(); } diff --git a/aspnet-core/migrate-database.bat b/aspnet-core/migrate-database.bat index f94f20e30..68b63f138 100644 --- a/aspnet-core/migrate-database.bat +++ b/aspnet-core/migrate-database.bat @@ -1,9 +1,8 @@ @echo off cls -call .\migrate-db-cmd.bat LY.MicroService.Platform.DbMigrator platform --run call .\migrate-db-cmd.bat LY.MicroService.AuthServer.DbMigrator auth-server --run -call .\migrate-db-cmd.bat LY.MicroService.IdentityServer.DbMigrator identityserver4-admin --run +call .\migrate-db-cmd.bat LY.MicroService.Platform.DbMigrator platform --run call .\migrate-db-cmd.bat LY.MicroService.LocalizationManagement.DbMigrator localization --run call .\migrate-db-cmd.bat LY.MicroService.RealtimeMessage.DbMigrator messages --run call .\migrate-db-cmd.bat LY.MicroService.TaskManagement.DbMigrator task-management --run diff --git a/aspnet-core/migrations/LY.MicroService.Applications.Single.EntityFrameworkCore/DataSeeder/OpenIddictDataSeederContributor.cs b/aspnet-core/migrations/LY.MicroService.Applications.Single.EntityFrameworkCore/DataSeeder/OpenIddictDataSeederContributor.cs index 9b30eefd8..b37e3030a 100644 --- a/aspnet-core/migrations/LY.MicroService.Applications.Single.EntityFrameworkCore/DataSeeder/OpenIddictDataSeederContributor.cs +++ b/aspnet-core/migrations/LY.MicroService.Applications.Single.EntityFrameworkCore/DataSeeder/OpenIddictDataSeederContributor.cs @@ -236,7 +236,9 @@ public class OpenIddictDataSeederContributor : OpenIddictDataSeedContributorBase [OpenIddictConstants.GrantTypes.AuthorizationCode, OpenIddictConstants.GrantTypes.Implicit, OpenIddictConstants.GrantTypes.Password, - OpenIddictConstants.GrantTypes.RefreshToken], + OpenIddictConstants.GrantTypes.RefreshToken, + // TODO: 引用项目? + "link_user"], [OpenIddictConstants.Scopes.OpenId, OpenIddictConstants.Scopes.Email, OpenIddictConstants.Scopes.Roles, @@ -298,7 +300,9 @@ public class OpenIddictDataSeederContributor : OpenIddictDataSeedContributorBase "Abp OAuth Client", null, [OpenIddictConstants.GrantTypes.AuthorizationCode, - OpenIddictConstants.GrantTypes.RefreshToken], + OpenIddictConstants.GrantTypes.RefreshToken, + // TODO: 引用项目? + "link_user"], [OpenIddictConstants.Scopes.OpenId, OpenIddictConstants.Scopes.Email, OpenIddictConstants.Scopes.Roles, diff --git a/aspnet-core/migrations/LY.MicroService.AuthServer.EntityFrameworkCore/DataSeeds/OpenIddictDataSeeder.cs b/aspnet-core/migrations/LY.MicroService.AuthServer.EntityFrameworkCore/DataSeeds/OpenIddictDataSeeder.cs index 7cf0622a7..04272eddf 100644 --- a/aspnet-core/migrations/LY.MicroService.AuthServer.EntityFrameworkCore/DataSeeds/OpenIddictDataSeeder.cs +++ b/aspnet-core/migrations/LY.MicroService.AuthServer.EntityFrameworkCore/DataSeeds/OpenIddictDataSeeder.cs @@ -479,7 +479,9 @@ public class OpenIddictDataSeeder : OpenIddictDataSeedContributorBase, ITransien [OpenIddictConstants.GrantTypes.AuthorizationCode, OpenIddictConstants.GrantTypes.Implicit, OpenIddictConstants.GrantTypes.Password, - OpenIddictConstants.GrantTypes.RefreshToken], + OpenIddictConstants.GrantTypes.RefreshToken, + // TODO: 引用项目? + "link_user"], [OpenIddictConstants.Scopes.OpenId, OpenIddictConstants.Scopes.Email, OpenIddictConstants.Scopes.Roles, @@ -541,7 +543,9 @@ public class OpenIddictDataSeeder : OpenIddictDataSeedContributorBase, ITransien "Abp OAuth Client", null, [OpenIddictConstants.GrantTypes.AuthorizationCode, - OpenIddictConstants.GrantTypes.RefreshToken], + OpenIddictConstants.GrantTypes.RefreshToken, + // TODO: 引用项目? + "link_user"], [OpenIddictConstants.Scopes.OpenId, OpenIddictConstants.Scopes.Email, OpenIddictConstants.Scopes.Roles, diff --git a/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Domain/LINGYUN/Abp/Identity/Session/IdentitySessionUserInactiveSynchronizer.cs b/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Domain/LINGYUN/Abp/Identity/Session/IdentitySessionUserInactiveSynchronizer.cs index 3f458a83c..ed6d3dc1a 100644 --- a/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Domain/LINGYUN/Abp/Identity/Session/IdentitySessionUserInactiveSynchronizer.cs +++ b/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Domain/LINGYUN/Abp/Identity/Session/IdentitySessionUserInactiveSynchronizer.cs @@ -1,5 +1,6 @@ using System.Threading.Tasks; using Volo.Abp.DependencyInjection; +using Volo.Abp.DistributedLocking; using Volo.Abp.Domain.Entities.Events.Distributed; using Volo.Abp.EventBus.Distributed; using Volo.Abp.Uow; @@ -10,20 +11,29 @@ public class IdentitySessionUserInactiveSynchronizer : IDistributedEventHandler>, ITransientDependency { + private readonly IAbpDistributedLock _distributedLock; private readonly IIdentityUserInactiveRepository _identityUserInactiveRepository; - public IdentitySessionUserInactiveSynchronizer(IIdentityUserInactiveRepository identityUserInactiveRepository) + public IdentitySessionUserInactiveSynchronizer( + IAbpDistributedLock distributedLock, + IIdentityUserInactiveRepository identityUserInactiveRepository) { + _distributedLock = distributedLock; _identityUserInactiveRepository = identityUserInactiveRepository; } [UnitOfWork] public async virtual Task HandleEventAsync(EntityCreatedEto eventData) { - var userInactive = await _identityUserInactiveRepository.FindByUserIdAsync(eventData.Entity.UserId); - if (userInactive == null) + await using var lockHandle = await _distributedLock.TryAcquireAsync( + $"{nameof(IdentitySessionUserInactiveSynchronizer)}_{nameof(IdentitySessionEto)}"); + if (lockHandle != null) { - await _identityUserInactiveRepository.DeleteAsync(userInactive); + var userInactive = await _identityUserInactiveRepository.FindByUserIdAsync(eventData.Entity.UserId); + if (userInactive != null) + { + await _identityUserInactiveRepository.DeleteAsync(userInactive); + } } } } diff --git a/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Notifications/LINGYUN/Abp/Identity/Notifications/Templates/InactiveUserDeactivationNotifier.tpl b/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Notifications/LINGYUN/Abp/Identity/Notifications/Templates/InactiveUserDeactivationNotifier.tpl index c5e4156e7..6ab032f43 100644 --- a/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Notifications/LINGYUN/Abp/Identity/Notifications/Templates/InactiveUserDeactivationNotifier.tpl +++ b/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Notifications/LINGYUN/Abp/Identity/Notifications/Templates/InactiveUserDeactivationNotifier.tpl @@ -1,5 +1,5 @@ - + {{L "InactiveUserDeactivationNotifier"}} diff --git a/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Notifications/LINGYUN/Abp/Identity/Notifications/Templates/InactiveUserDeletionNotifier.tpl b/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Notifications/LINGYUN/Abp/Identity/Notifications/Templates/InactiveUserDeletionNotifier.tpl index 3388ba945..b4d4ac51a 100644 --- a/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Notifications/LINGYUN/Abp/Identity/Notifications/Templates/InactiveUserDeletionNotifier.tpl +++ b/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Notifications/LINGYUN/Abp/Identity/Notifications/Templates/InactiveUserDeletionNotifier.tpl @@ -1,5 +1,5 @@ - + {{L "InactiveUserDeletionNotifier"}} diff --git a/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Notifications/LINGYUN/Abp/Identity/Notifications/Templates/InactiveUserReminderNotifier.tpl b/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Notifications/LINGYUN/Abp/Identity/Notifications/Templates/InactiveUserReminderNotifier.tpl index b00cc704a..acd422495 100644 --- a/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Notifications/LINGYUN/Abp/Identity/Notifications/Templates/InactiveUserReminderNotifier.tpl +++ b/aspnet-core/modules/identity/LINGYUN.Abp.Identity.Notifications/LINGYUN/Abp/Identity/Notifications/Templates/InactiveUserReminderNotifier.tpl @@ -1,5 +1,5 @@ - + {{L "InactiveUserReminderNotifier"}} diff --git a/aspnet-core/modules/platform/LINGYUN.Abp.UI.Navigation.VueVbenAdmin5/LINGYUN/Abp/UI/Navigation/VueVbenAdmin5/AbpUINavigationVueVbenAdmin5NavigationDefinitionProvider.cs b/aspnet-core/modules/platform/LINGYUN.Abp.UI.Navigation.VueVbenAdmin5/LINGYUN/Abp/UI/Navigation/VueVbenAdmin5/AbpUINavigationVueVbenAdmin5NavigationDefinitionProvider.cs index 110e715f8..95c979535 100644 --- a/aspnet-core/modules/platform/LINGYUN.Abp.UI.Navigation.VueVbenAdmin5/LINGYUN/Abp/UI/Navigation/VueVbenAdmin5/AbpUINavigationVueVbenAdmin5NavigationDefinitionProvider.cs +++ b/aspnet-core/modules/platform/LINGYUN.Abp.UI.Navigation.VueVbenAdmin5/LINGYUN/Abp/UI/Navigation/VueVbenAdmin5/AbpUINavigationVueVbenAdmin5NavigationDefinitionProvider.cs @@ -17,6 +17,7 @@ public class AbpUINavigationVueVbenAdmin5NavigationDefinitionProvider : Navigati context.Add(GetTaskManagement()); context.Add(GetWebhooksManagement()); context.Add(GetTextTemplating()); + context.Add(GetWeChatManagement()); context.Add(GetVbenDemos()); } @@ -811,4 +812,27 @@ public class AbpUINavigationVueVbenAdmin5NavigationDefinitionProvider : Navigati return new NavigationDefinition(textTemplating); } + + private static NavigationDefinition GetWeChatManagement() + { + var wechat = new ApplicationMenu( + name: "Vben5Wechat", + displayName: "微信集成", + url: "/wechat", + component: "", + description: "微信集成", + icon: "ant-design:wechat-outlined") + .SetProperty("title", "abp.wechat.title"); + wechat.AddItem( + new ApplicationMenu( + name: "Vben5WechatSettings", + displayName: "微信设置", + url: "/wechat/settings", + component: "/wechat/settings/index", + icon: "ant-design:setting-outlined", + description: "微信设置") + .SetProperty("title", "abp.wechat.settings")); + + return new NavigationDefinition(wechat); + } } diff --git a/aspnet-core/modules/task-management/LINGYUN.Abp.TaskManagement.Application.Contracts/LINGYUN/Abp/TaskManagement/BackgroundJobInfoDto.cs b/aspnet-core/modules/task-management/LINGYUN.Abp.TaskManagement.Application.Contracts/LINGYUN/Abp/TaskManagement/BackgroundJobInfoDto.cs index da915aa09..f4027627b 100644 --- a/aspnet-core/modules/task-management/LINGYUN.Abp.TaskManagement.Application.Contracts/LINGYUN/Abp/TaskManagement/BackgroundJobInfoDto.cs +++ b/aspnet-core/modules/task-management/LINGYUN.Abp.TaskManagement.Application.Contracts/LINGYUN/Abp/TaskManagement/BackgroundJobInfoDto.cs @@ -105,4 +105,8 @@ public class BackgroundJobInfoDto : ExtensibleAuditedEntityDto, IHasConc /// 0或更小不生效 /// public int LockTimeOut { get; set; } + /// + /// 指定作业运行节点 + /// + public string NodeName { get; set; } } diff --git a/aspnet-core/services/LY.MicroService.Applications.Single/MicroServiceApplicationsSingleModule.Configure.cs b/aspnet-core/services/LY.MicroService.Applications.Single/MicroServiceApplicationsSingleModule.Configure.cs index 4d759c6e1..7a7bd8b56 100644 --- a/aspnet-core/services/LY.MicroService.Applications.Single/MicroServiceApplicationsSingleModule.Configure.cs +++ b/aspnet-core/services/LY.MicroService.Applications.Single/MicroServiceApplicationsSingleModule.Configure.cs @@ -788,6 +788,7 @@ public partial class MicroServiceApplicationsSingleModule Configure(options => { options.SaveStaticLocalizationsToDatabase = true; + options.IsDynamicLocalizationInitializerHost = true; }); } diff --git a/aspnet-core/services/LY.MicroService.Applications.Single/MicroServiceApplicationsSingleModule.cs b/aspnet-core/services/LY.MicroService.Applications.Single/MicroServiceApplicationsSingleModule.cs index fc1ef5c75..6d11fe363 100644 --- a/aspnet-core/services/LY.MicroService.Applications.Single/MicroServiceApplicationsSingleModule.cs +++ b/aspnet-core/services/LY.MicroService.Applications.Single/MicroServiceApplicationsSingleModule.cs @@ -121,6 +121,8 @@ namespace LY.MicroService.Applications.Single; typeof(AbpOpenIddictWeChatModule), // OpenIddict扩展模块 企业微信认证 typeof(AbpOpenIddictWeChatWorkModule), + // OpenIddict扩展模块 关联账户 + typeof(AbpOpenIddictLinkUserModule), // OpenIddict扩展模块 扫码登录 typeof(AbpOpenIddictQrCodeModule), diff --git a/aspnet-core/services/LY.MicroService.Applications.Single/Settings/SystemGroupSettingDefinitionProvider.cs b/aspnet-core/services/LY.MicroService.Applications.Single/Settings/SystemGroupSettingDefinitionProvider.cs new file mode 100644 index 000000000..c90c5eb08 --- /dev/null +++ b/aspnet-core/services/LY.MicroService.Applications.Single/Settings/SystemGroupSettingDefinitionProvider.cs @@ -0,0 +1,253 @@ +using Microsoft.Extensions.Localization; +using Microsoft.Extensions.Options; +using Volo.Abp.Emailing; +using Volo.Abp.Settings; +using Volo.Abp.Timing; +using ValueType = Volo.Abp.Settings.ValueType; + +namespace LY.MicroService.Applications.Single.Settings; + +public class SystemGroupSettingDefinitionProvider : SettingDefinitionProvider +{ + private const string GroupName = "System"; + + protected ITimezoneProvider TimezoneProvider { get; } + protected AbpLocalizationOptions LocalizationOptions { get; } + protected IStringLocalizerFactory StringLocalizerFactory { get; } + + public SystemGroupSettingDefinitionProvider( + ITimezoneProvider timezoneProvider, + IStringLocalizerFactory stringLocalizerFactory, + IOptions localizationOptions) + { + TimezoneProvider = timezoneProvider; + StringLocalizerFactory = stringLocalizerFactory; + LocalizationOptions = localizationOptions.Value; + } + + public override void Define(ISettingDefinitionContext context) + { + SetSystemSettingGroup(context); + SetEmailSettingGroup(context); + } + + private void SetSystemSettingGroup(ISettingDefinitionContext context) + { + context.GetOrNull(LocalizationSettingNames.DefaultLanguage) + ?.WithGroup(GroupName, L("Settings:System"), order: 0) + ?.WithParent("Language", L("Settings:System.Language"), order: 0) + ?.WithOrder(0) + ?.WithOptions(LocalizationOptions.Languages.Select(l => new NameValue(l.DisplayName, l.CultureName))) + ?.ReplaceProviders( + DefaultValueSettingValueProvider.ProviderName, + ConfigurationSettingValueProvider.ProviderName, + GlobalSettingValueProvider.ProviderName, + TenantSettingValueProvider.ProviderName); + + var timezoneSetting = context.GetOrNull(TimingSettingNames.TimeZone); + if (timezoneSetting != null) + { + var stringLocalizer = StringLocalizerFactory.Create(); + var timezones = TimeZoneHelper.GetTimezones(TimezoneProvider.GetIanaTimezones()); + timezones.Insert(0, new NameValue + { + Name = stringLocalizer["DefaultTimeZone"], + Value = "Unspecified" + }); + + timezoneSetting + .WithGroup( + GroupName, + L("Settings:System"), + order: 0, + requiredPermissions: [Volo.Abp.SettingManagement.SettingManagementPermissions.TimeZone]) + .WithParent("Timing", L("Settings:System.Timing"), order: 0) + .WithOrder(1) + .WithOptions(timezones) + .ReplaceProviders( + DefaultValueSettingValueProvider.ProviderName, + ConfigurationSettingValueProvider.ProviderName, + GlobalSettingValueProvider.ProviderName, + TenantSettingValueProvider.ProviderName); + } + } + + private static void SetEmailSettingGroup(ISettingDefinitionContext context) + { + context.GetOrNull(EmailSettingNames.DefaultFromAddress) + ?.WithGroup( + "Emailing", + L("Settings:Emailing"), + order: 1, + requiredFeatures: [SettingManagementFeatures.Enable, SettingManagementFeatures.AllowChangingEmailSettings], + requiredPermissions: [Volo.Abp.SettingManagement.SettingManagementPermissions.Emailing]) + ?.WithParent( + "Default", + L("Settings:Emailing.Default"), + order: 0) + ?.WithOrder(0) + ?.WithValueType(ValueType.String) + ?.ReplaceProviders( + DefaultValueSettingValueProvider.ProviderName, + ConfigurationSettingValueProvider.ProviderName, + GlobalSettingValueProvider.ProviderName, + TenantSettingValueProvider.ProviderName); + context.GetOrNull(EmailSettingNames.DefaultFromDisplayName) + ?.WithGroup( + "Emailing", + L("Settings:Emailing"), + order: 1, + requiredFeatures: [SettingManagementFeatures.Enable, SettingManagementFeatures.AllowChangingEmailSettings], + requiredPermissions: [Volo.Abp.SettingManagement.SettingManagementPermissions.Emailing]) + ?.WithParent( + "Default", + L("Settings:Emailing.Default"), + order: 0) + ?.WithOrder(1) + ?.WithValueType(ValueType.String) + ?.ReplaceProviders( + DefaultValueSettingValueProvider.ProviderName, + ConfigurationSettingValueProvider.ProviderName, + GlobalSettingValueProvider.ProviderName, + TenantSettingValueProvider.ProviderName); + + context.GetOrNull(EmailSettingNames.Smtp.Domain) + ?.WithGroup( + "Emailing", + L("Settings:Emailing"), + order: 1, + requiredFeatures: [SettingManagementFeatures.Enable, SettingManagementFeatures.AllowChangingEmailSettings], + requiredPermissions: [Volo.Abp.SettingManagement.SettingManagementPermissions.Emailing]) + ?.WithParent( + "Smtp", + L("Settings:Emailing.Smtp"), + order: 1, + requiredPermissions: [AbpSettingManagementPermissions.Settings.Manager]) + ?.WithOrder(0) + ?.WithValueType(ValueType.String) + ?.ReplaceProviders( + DefaultValueSettingValueProvider.ProviderName, + ConfigurationSettingValueProvider.ProviderName, + GlobalSettingValueProvider.ProviderName, + TenantSettingValueProvider.ProviderName); + context.GetOrNull(EmailSettingNames.Smtp.Host) + ?.WithGroup( + "Emailing", + L("Settings:Emailing"), + order: 1, + requiredFeatures: [SettingManagementFeatures.Enable, SettingManagementFeatures.AllowChangingEmailSettings], + requiredPermissions: [Volo.Abp.SettingManagement.SettingManagementPermissions.Emailing]) + ?.WithParent( + "Smtp", + L("Settings:Emailing.Smtp"), + order: 1, + requiredPermissions: [AbpSettingManagementPermissions.Settings.Manager]) + ?.WithOrder(1) + ?.WithValueType(ValueType.String) + ?.ReplaceProviders( + DefaultValueSettingValueProvider.ProviderName, + ConfigurationSettingValueProvider.ProviderName, + GlobalSettingValueProvider.ProviderName, + TenantSettingValueProvider.ProviderName); + context.GetOrNull(EmailSettingNames.Smtp.Port) + ?.WithGroup( + "Emailing", + L("Settings:Emailing"), + order: 1, + requiredFeatures: [SettingManagementFeatures.Enable, SettingManagementFeatures.AllowChangingEmailSettings], + requiredPermissions: [Volo.Abp.SettingManagement.SettingManagementPermissions.Emailing]) + ?.WithParent( + "Smtp", + L("Settings:Emailing.Smtp"), + order: 1, + requiredPermissions: [AbpSettingManagementPermissions.Settings.Manager]) + ?.WithOrder(2) + ?.WithValueType(ValueType.Number) + ?.ReplaceProviders( + DefaultValueSettingValueProvider.ProviderName, + ConfigurationSettingValueProvider.ProviderName, + GlobalSettingValueProvider.ProviderName, + TenantSettingValueProvider.ProviderName); + context.GetOrNull(EmailSettingNames.Smtp.UserName) + ?.WithGroup( + "Emailing", + L("Settings:Emailing"), + order: 1, + requiredFeatures: [SettingManagementFeatures.Enable, SettingManagementFeatures.AllowChangingEmailSettings], + requiredPermissions: [Volo.Abp.SettingManagement.SettingManagementPermissions.Emailing]) + ?.WithParent( + "Smtp", + L("Settings:Emailing.Smtp"), + order: 1, + requiredPermissions: [AbpSettingManagementPermissions.Settings.Manager]) + ?.WithOrder(3) + ?.WithValueType(ValueType.String) + ?.ReplaceProviders( + DefaultValueSettingValueProvider.ProviderName, + ConfigurationSettingValueProvider.ProviderName, + GlobalSettingValueProvider.ProviderName, + TenantSettingValueProvider.ProviderName); + context.GetOrNull(EmailSettingNames.Smtp.Password) + ?.WithGroup( + "Emailing", + L("Settings:Emailing"), + order: 1, + requiredFeatures: [SettingManagementFeatures.Enable, SettingManagementFeatures.AllowChangingEmailSettings], + requiredPermissions: [Volo.Abp.SettingManagement.SettingManagementPermissions.Emailing]) + ?.WithParent( + "Smtp", + L("Settings:Emailing.Smtp"), + order: 1, + requiredPermissions: [AbpSettingManagementPermissions.Settings.Manager]) + ?.WithOrder(4) + ?.WithValueType(ValueType.String) + ?.ReplaceProviders( + DefaultValueSettingValueProvider.ProviderName, + ConfigurationSettingValueProvider.ProviderName, + GlobalSettingValueProvider.ProviderName, + TenantSettingValueProvider.ProviderName); + context.GetOrNull(EmailSettingNames.Smtp.EnableSsl) + ?.WithGroup( + "Emailing", + L("Settings:Emailing"), + order: 1, + requiredFeatures: [SettingManagementFeatures.Enable, SettingManagementFeatures.AllowChangingEmailSettings], + requiredPermissions: [Volo.Abp.SettingManagement.SettingManagementPermissions.Emailing]) + ?.WithParent( + "Smtp", + L("Settings:Emailing.Smtp"), + order: 1, + requiredPermissions: [AbpSettingManagementPermissions.Settings.Manager]) + ?.WithOrder(5) + ?.WithValueType(ValueType.Boolean) + ?.ReplaceProviders( + DefaultValueSettingValueProvider.ProviderName, + ConfigurationSettingValueProvider.ProviderName, + GlobalSettingValueProvider.ProviderName, + TenantSettingValueProvider.ProviderName); + context.GetOrNull(EmailSettingNames.Smtp.UseDefaultCredentials) + ?.WithGroup( + "Emailing", + L("Settings:Emailing"), + order: 1, + requiredFeatures: [SettingManagementFeatures.Enable, SettingManagementFeatures.AllowChangingEmailSettings], + requiredPermissions: [Volo.Abp.SettingManagement.SettingManagementPermissions.Emailing]) + ?.WithParent( + "Smtp", + L("Settings:Emailing.Smtp"), + order: 1, + requiredPermissions: [AbpSettingManagementPermissions.Settings.Manager]) + ?.WithOrder(6) + ?.WithValueType(ValueType.Boolean) + ?.ReplaceProviders( + DefaultValueSettingValueProvider.ProviderName, + ConfigurationSettingValueProvider.ProviderName, + GlobalSettingValueProvider.ProviderName, + TenantSettingValueProvider.ProviderName); + } + + public static LocalizableString L(string name) + { + return LocalizableString.Create(name); + } +} diff --git a/aspnet-core/services/LY.MicroService.Applications.Single/appsettings.Development.json b/aspnet-core/services/LY.MicroService.Applications.Single/appsettings.Development.json index 582698e86..0a8e00dab 100644 --- a/aspnet-core/services/LY.MicroService.Applications.Single/appsettings.Development.json +++ b/aspnet-core/services/LY.MicroService.Applications.Single/appsettings.Development.json @@ -27,7 +27,6 @@ "Auditing": { "AllEntitiesSelector": true }, - "CAP": { "IsEnabled": false, "EventBus": { @@ -49,6 +48,25 @@ "Configuration": "localhost" } }, + "Calendar": { + "DefaultWorkdays": [ + "Monday", + "Tuesday", + "Wednesday", + "Thursday", + "Friday" + ], + "DefaultWorkTimes": [ + { + "StartTime": "08:00:00", + "EndTime": "12:00:00" + }, + { + "StartTime": "14:00:00", + "EndTime": "18:00:00" + } + ] + }, "DistributedCache": { "HideErrors": true, "KeyPrefix": "LINGYUN.Abp.Application", @@ -147,7 +165,7 @@ }, "Lifetime": { "AuthorizationCode": "00:05:00", - "AccessToken": "00:05:00", + "AccessToken": "02:00:00", "DeviceCode": "00:10:00", "IdentityToken": "00:20:00", "RefreshToken": "06:00:00", @@ -181,6 +199,9 @@ "RequireConfirmedPhoneNumber": false } }, + "AIManagement": { + "IsDynamicStoreEnabled": true + }, "FeatureManagement": { "IsDynamicStoreEnabled": true }, @@ -220,14 +241,6 @@ "Elasticsearch": { "NodeUris": "http://localhost:9200" }, - "Minio": { - "WithSSL": false, - "BucketName": "blobs", - "EndPoint": "localhost:19000", - "AccessKey": "ZD43kNpimiJf9mCuomTP", - "SecretKey": "w8IqMgi4Tnz0DGzN8jZ7IJWq7OEdbUnAU0jlZxQK", - "CreateBucketIfNotExists": false - }, "Serilog": { "MinimumLevel": { "Default": "Information", @@ -235,6 +248,7 @@ "System": "Warning", "Microsoft": "Warning", "Microsoft.EntityFrameworkCore": "Warning", + "LINGYUN.Abp.BlobManagement": "Debug", "DotNetCore": "Warning" } }, diff --git a/aspnet-core/services/LY.MicroService.BackendAdmin.HttpApi.Host/Settings/SystemGroupSettingDefinitionProvider.cs b/aspnet-core/services/LY.MicroService.BackendAdmin.HttpApi.Host/Settings/SystemGroupSettingDefinitionProvider.cs new file mode 100644 index 000000000..ba6bfab92 --- /dev/null +++ b/aspnet-core/services/LY.MicroService.BackendAdmin.HttpApi.Host/Settings/SystemGroupSettingDefinitionProvider.cs @@ -0,0 +1,260 @@ +using LINGYUN.Abp.SettingManagement; +using Microsoft.Extensions.Localization; +using Microsoft.Extensions.Options; +using System.Linq; +using Volo.Abp; +using Volo.Abp.Emailing; +using Volo.Abp.Localization; +using Volo.Abp.SettingManagement; +using Volo.Abp.SettingManagement.Localization; +using Volo.Abp.Settings; +using Volo.Abp.Timing; +using ValueType = Volo.Abp.Settings.ValueType; + +namespace LY.MicroService.BackendAdmin.Settings; + +public class SystemGroupSettingDefinitionProvider : SettingDefinitionProvider +{ + private const string GroupName = "System"; + + protected ITimezoneProvider TimezoneProvider { get; } + protected AbpLocalizationOptions LocalizationOptions { get; } + protected IStringLocalizerFactory StringLocalizerFactory { get; } + + public SystemGroupSettingDefinitionProvider( + ITimezoneProvider timezoneProvider, + IStringLocalizerFactory stringLocalizerFactory, + IOptions localizationOptions) + { + TimezoneProvider = timezoneProvider; + StringLocalizerFactory = stringLocalizerFactory; + LocalizationOptions = localizationOptions.Value; + } + + public override void Define(ISettingDefinitionContext context) + { + SetSystemSettingGroup(context); + SetEmailSettingGroup(context); + } + + private void SetSystemSettingGroup(ISettingDefinitionContext context) + { + context.GetOrNull(LocalizationSettingNames.DefaultLanguage) + ?.WithGroup(GroupName, L("Settings:System"), order: 0) + ?.WithParent("Language", L("Settings:System.Language"), order: 0) + ?.WithOrder(0) + ?.WithOptions(LocalizationOptions.Languages.Select(l => new NameValue(l.DisplayName, l.CultureName))) + ?.ReplaceProviders( + DefaultValueSettingValueProvider.ProviderName, + ConfigurationSettingValueProvider.ProviderName, + GlobalSettingValueProvider.ProviderName, + TenantSettingValueProvider.ProviderName); + + var timezoneSetting = context.GetOrNull(TimingSettingNames.TimeZone); + if (timezoneSetting != null) + { + var stringLocalizer = StringLocalizerFactory.Create(); + var timezones = TimeZoneHelper.GetTimezones(TimezoneProvider.GetIanaTimezones()); + timezones.Insert(0, new NameValue + { + Name = stringLocalizer["DefaultTimeZone"], + Value = "Unspecified" + }); + + timezoneSetting + .WithGroup( + GroupName, + L("Settings:System"), + order: 0, + requiredPermissions: [Volo.Abp.SettingManagement.SettingManagementPermissions.TimeZone]) + .WithParent("Timing", L("Settings:System.Timing"), order: 0) + .WithOrder(1) + .WithOptions(timezones) + .ReplaceProviders( + DefaultValueSettingValueProvider.ProviderName, + ConfigurationSettingValueProvider.ProviderName, + GlobalSettingValueProvider.ProviderName, + TenantSettingValueProvider.ProviderName); + } + } + + private static void SetEmailSettingGroup(ISettingDefinitionContext context) + { + context.GetOrNull(EmailSettingNames.DefaultFromAddress) + ?.WithGroup( + "Emailing", + L("Settings:Emailing"), + order: 1, + requiredFeatures: [SettingManagementFeatures.Enable, SettingManagementFeatures.AllowChangingEmailSettings], + requiredPermissions: [Volo.Abp.SettingManagement.SettingManagementPermissions.Emailing]) + ?.WithParent( + "Default", + L("Settings:Emailing.Default"), + order: 0) + ?.WithOrder(0) + ?.WithValueType(ValueType.String) + ?.ReplaceProviders( + DefaultValueSettingValueProvider.ProviderName, + ConfigurationSettingValueProvider.ProviderName, + GlobalSettingValueProvider.ProviderName, + TenantSettingValueProvider.ProviderName); + context.GetOrNull(EmailSettingNames.DefaultFromDisplayName) + ?.WithGroup( + "Emailing", + L("Settings:Emailing"), + order: 1, + requiredFeatures: [SettingManagementFeatures.Enable, SettingManagementFeatures.AllowChangingEmailSettings], + requiredPermissions: [Volo.Abp.SettingManagement.SettingManagementPermissions.Emailing]) + ?.WithParent( + "Default", + L("Settings:Emailing.Default"), + order: 0) + ?.WithOrder(1) + ?.WithValueType(ValueType.String) + ?.ReplaceProviders( + DefaultValueSettingValueProvider.ProviderName, + ConfigurationSettingValueProvider.ProviderName, + GlobalSettingValueProvider.ProviderName, + TenantSettingValueProvider.ProviderName); + + context.GetOrNull(EmailSettingNames.Smtp.Domain) + ?.WithGroup( + "Emailing", + L("Settings:Emailing"), + order: 1, + requiredFeatures: [SettingManagementFeatures.Enable, SettingManagementFeatures.AllowChangingEmailSettings], + requiredPermissions: [Volo.Abp.SettingManagement.SettingManagementPermissions.Emailing]) + ?.WithParent( + "Smtp", + L("Settings:Emailing.Smtp"), + order: 1, + requiredPermissions: [AbpSettingManagementPermissions.Settings.Manager]) + ?.WithOrder(0) + ?.WithValueType(ValueType.String) + ?.ReplaceProviders( + DefaultValueSettingValueProvider.ProviderName, + ConfigurationSettingValueProvider.ProviderName, + GlobalSettingValueProvider.ProviderName, + TenantSettingValueProvider.ProviderName); + context.GetOrNull(EmailSettingNames.Smtp.Host) + ?.WithGroup( + "Emailing", + L("Settings:Emailing"), + order: 1, + requiredFeatures: [SettingManagementFeatures.Enable, SettingManagementFeatures.AllowChangingEmailSettings], + requiredPermissions: [Volo.Abp.SettingManagement.SettingManagementPermissions.Emailing]) + ?.WithParent( + "Smtp", + L("Settings:Emailing.Smtp"), + order: 1, + requiredPermissions: [AbpSettingManagementPermissions.Settings.Manager]) + ?.WithOrder(1) + ?.WithValueType(ValueType.String) + ?.ReplaceProviders( + DefaultValueSettingValueProvider.ProviderName, + ConfigurationSettingValueProvider.ProviderName, + GlobalSettingValueProvider.ProviderName, + TenantSettingValueProvider.ProviderName); + context.GetOrNull(EmailSettingNames.Smtp.Port) + ?.WithGroup( + "Emailing", + L("Settings:Emailing"), + order: 1, + requiredFeatures: [SettingManagementFeatures.Enable, SettingManagementFeatures.AllowChangingEmailSettings], + requiredPermissions: [Volo.Abp.SettingManagement.SettingManagementPermissions.Emailing]) + ?.WithParent( + "Smtp", + L("Settings:Emailing.Smtp"), + order: 1, + requiredPermissions: [AbpSettingManagementPermissions.Settings.Manager]) + ?.WithOrder(2) + ?.WithValueType(ValueType.Number) + ?.ReplaceProviders( + DefaultValueSettingValueProvider.ProviderName, + ConfigurationSettingValueProvider.ProviderName, + GlobalSettingValueProvider.ProviderName, + TenantSettingValueProvider.ProviderName); + context.GetOrNull(EmailSettingNames.Smtp.UserName) + ?.WithGroup( + "Emailing", + L("Settings:Emailing"), + order: 1, + requiredFeatures: [SettingManagementFeatures.Enable, SettingManagementFeatures.AllowChangingEmailSettings], + requiredPermissions: [Volo.Abp.SettingManagement.SettingManagementPermissions.Emailing]) + ?.WithParent( + "Smtp", + L("Settings:Emailing.Smtp"), + order: 1, + requiredPermissions: [AbpSettingManagementPermissions.Settings.Manager]) + ?.WithOrder(3) + ?.WithValueType(ValueType.String) + ?.ReplaceProviders( + DefaultValueSettingValueProvider.ProviderName, + ConfigurationSettingValueProvider.ProviderName, + GlobalSettingValueProvider.ProviderName, + TenantSettingValueProvider.ProviderName); + context.GetOrNull(EmailSettingNames.Smtp.Password) + ?.WithGroup( + "Emailing", + L("Settings:Emailing"), + order: 1, + requiredFeatures: [SettingManagementFeatures.Enable, SettingManagementFeatures.AllowChangingEmailSettings], + requiredPermissions: [Volo.Abp.SettingManagement.SettingManagementPermissions.Emailing]) + ?.WithParent( + "Smtp", + L("Settings:Emailing.Smtp"), + order: 1, + requiredPermissions: [AbpSettingManagementPermissions.Settings.Manager]) + ?.WithOrder(4) + ?.WithValueType(ValueType.String) + ?.ReplaceProviders( + DefaultValueSettingValueProvider.ProviderName, + ConfigurationSettingValueProvider.ProviderName, + GlobalSettingValueProvider.ProviderName, + TenantSettingValueProvider.ProviderName); + context.GetOrNull(EmailSettingNames.Smtp.EnableSsl) + ?.WithGroup( + "Emailing", + L("Settings:Emailing"), + order: 1, + requiredFeatures: [SettingManagementFeatures.Enable, SettingManagementFeatures.AllowChangingEmailSettings], + requiredPermissions: [Volo.Abp.SettingManagement.SettingManagementPermissions.Emailing]) + ?.WithParent( + "Smtp", + L("Settings:Emailing.Smtp"), + order: 1, + requiredPermissions: [AbpSettingManagementPermissions.Settings.Manager]) + ?.WithOrder(5) + ?.WithValueType(ValueType.Boolean) + ?.ReplaceProviders( + DefaultValueSettingValueProvider.ProviderName, + ConfigurationSettingValueProvider.ProviderName, + GlobalSettingValueProvider.ProviderName, + TenantSettingValueProvider.ProviderName); + context.GetOrNull(EmailSettingNames.Smtp.UseDefaultCredentials) + ?.WithGroup( + "Emailing", + L("Settings:Emailing"), + order: 1, + requiredFeatures: [SettingManagementFeatures.Enable, SettingManagementFeatures.AllowChangingEmailSettings], + requiredPermissions: [Volo.Abp.SettingManagement.SettingManagementPermissions.Emailing]) + ?.WithParent( + "Smtp", + L("Settings:Emailing.Smtp"), + order: 1, + requiredPermissions: [AbpSettingManagementPermissions.Settings.Manager]) + ?.WithOrder(6) + ?.WithValueType(ValueType.Boolean) + ?.ReplaceProviders( + DefaultValueSettingValueProvider.ProviderName, + ConfigurationSettingValueProvider.ProviderName, + GlobalSettingValueProvider.ProviderName, + TenantSettingValueProvider.ProviderName); + } + + public static LocalizableString L(string name) + { + return LocalizableString.Create(name); + } +} + diff --git a/aspnet-core/tests/LINGYUN.Abp.BlobStoring.Aliyun.Tests/LINGYUN.Abp.BlobStoring.Aliyun.Tests.csproj b/aspnet-core/tests/LINGYUN.Abp.BlobStoring.Aliyun.Tests/LINGYUN.Abp.BlobStoring.Aliyun.Tests.csproj index 87e4211cf..7f6f1d3b9 100644 --- a/aspnet-core/tests/LINGYUN.Abp.BlobStoring.Aliyun.Tests/LINGYUN.Abp.BlobStoring.Aliyun.Tests.csproj +++ b/aspnet-core/tests/LINGYUN.Abp.BlobStoring.Aliyun.Tests/LINGYUN.Abp.BlobStoring.Aliyun.Tests.csproj @@ -4,7 +4,7 @@ net10.0 false - Debug;Release;PostgreSQL + Debug;Release AnyCPU diff --git a/aspnet-core/tests/LINGYUN.Abp.BlobStoring.Nexus.Tests/LINGYUN.Abp.BlobStoring.Nexus.Tests.csproj b/aspnet-core/tests/LINGYUN.Abp.BlobStoring.Nexus.Tests/LINGYUN.Abp.BlobStoring.Nexus.Tests.csproj index 7ed1cdaa9..a7fd2d6ce 100644 --- a/aspnet-core/tests/LINGYUN.Abp.BlobStoring.Nexus.Tests/LINGYUN.Abp.BlobStoring.Nexus.Tests.csproj +++ b/aspnet-core/tests/LINGYUN.Abp.BlobStoring.Nexus.Tests/LINGYUN.Abp.BlobStoring.Nexus.Tests.csproj @@ -4,7 +4,7 @@ net10.0 false - Debug;Release;PostgreSQL + Debug;Release AnyCPU diff --git a/aspnet-core/tests/LINGYUN.Abp.DataProtection.Tests/LINGYUN.Abp.DataProtection.Tests.csproj b/aspnet-core/tests/LINGYUN.Abp.DataProtection.Tests/LINGYUN.Abp.DataProtection.Tests.csproj index de79b7fb3..ca2d52d99 100644 --- a/aspnet-core/tests/LINGYUN.Abp.DataProtection.Tests/LINGYUN.Abp.DataProtection.Tests.csproj +++ b/aspnet-core/tests/LINGYUN.Abp.DataProtection.Tests/LINGYUN.Abp.DataProtection.Tests.csproj @@ -4,7 +4,7 @@ net10.0 false - Debug;Release;PostgreSQL + Debug;Release AnyCPU diff --git a/aspnet-core/tests/LINGYUN.Abp.EntityFrameworkCore.Tests/LINGYUN.Abp.EntityFrameworkCore.Tests.csproj b/aspnet-core/tests/LINGYUN.Abp.EntityFrameworkCore.Tests/LINGYUN.Abp.EntityFrameworkCore.Tests.csproj index cb4e39eb6..2b313eb3f 100644 --- a/aspnet-core/tests/LINGYUN.Abp.EntityFrameworkCore.Tests/LINGYUN.Abp.EntityFrameworkCore.Tests.csproj +++ b/aspnet-core/tests/LINGYUN.Abp.EntityFrameworkCore.Tests/LINGYUN.Abp.EntityFrameworkCore.Tests.csproj @@ -3,7 +3,7 @@ net10.0 - Debug;Release;PostgreSQL + Debug;Release AnyCPU diff --git a/aspnet-core/tests/LINGYUN.Abp.ExceptionHandling.Emailing.Tests/LINGYUN.Abp.ExceptionHandling.Emailing.Tests.csproj b/aspnet-core/tests/LINGYUN.Abp.ExceptionHandling.Emailing.Tests/LINGYUN.Abp.ExceptionHandling.Emailing.Tests.csproj index ee3b24784..4374a34da 100644 --- a/aspnet-core/tests/LINGYUN.Abp.ExceptionHandling.Emailing.Tests/LINGYUN.Abp.ExceptionHandling.Emailing.Tests.csproj +++ b/aspnet-core/tests/LINGYUN.Abp.ExceptionHandling.Emailing.Tests/LINGYUN.Abp.ExceptionHandling.Emailing.Tests.csproj @@ -4,7 +4,7 @@ net10.0 false - Debug;Release;PostgreSQL + Debug;Release AnyCPU diff --git a/aspnet-core/tests/LINGYUN.Abp.Features.LimitValidation.Redis.Tests/LINGYUN.Abp.Features.LimitValidation.Redis.Tests.csproj b/aspnet-core/tests/LINGYUN.Abp.Features.LimitValidation.Redis.Tests/LINGYUN.Abp.Features.LimitValidation.Redis.Tests.csproj index c8d61b8dc..566449afa 100644 --- a/aspnet-core/tests/LINGYUN.Abp.Features.LimitValidation.Redis.Tests/LINGYUN.Abp.Features.LimitValidation.Redis.Tests.csproj +++ b/aspnet-core/tests/LINGYUN.Abp.Features.LimitValidation.Redis.Tests/LINGYUN.Abp.Features.LimitValidation.Redis.Tests.csproj @@ -6,7 +6,7 @@ false - Debug;Release;PostgreSQL + Debug;Release AnyCPU diff --git a/aspnet-core/tests/LINGYUN.Abp.Features.LimitValidation.Tests/LINGYUN.Abp.Features.LimitValidation.Tests.csproj b/aspnet-core/tests/LINGYUN.Abp.Features.LimitValidation.Tests/LINGYUN.Abp.Features.LimitValidation.Tests.csproj index 3f1612d01..4af991b47 100644 --- a/aspnet-core/tests/LINGYUN.Abp.Features.LimitValidation.Tests/LINGYUN.Abp.Features.LimitValidation.Tests.csproj +++ b/aspnet-core/tests/LINGYUN.Abp.Features.LimitValidation.Tests/LINGYUN.Abp.Features.LimitValidation.Tests.csproj @@ -4,7 +4,7 @@ net10.0 false - Debug;Release;PostgreSQL + Debug;Release AnyCPU diff --git a/aspnet-core/tests/LINGYUN.Abp.IdGenerator.Tests/LINGYUN.Abp.IdGenerator.Tests.csproj b/aspnet-core/tests/LINGYUN.Abp.IdGenerator.Tests/LINGYUN.Abp.IdGenerator.Tests.csproj index e7f696469..5232b9772 100644 --- a/aspnet-core/tests/LINGYUN.Abp.IdGenerator.Tests/LINGYUN.Abp.IdGenerator.Tests.csproj +++ b/aspnet-core/tests/LINGYUN.Abp.IdGenerator.Tests/LINGYUN.Abp.IdGenerator.Tests.csproj @@ -4,7 +4,7 @@ net10.0 false - Debug;Release;PostgreSQL + Debug;Release AnyCPU diff --git a/aspnet-core/tests/LINGYUN.Abp.Localization.Xml.Tests/LINGYUN.Abp.Localization.Xml.Tests.csproj b/aspnet-core/tests/LINGYUN.Abp.Localization.Xml.Tests/LINGYUN.Abp.Localization.Xml.Tests.csproj index a6485cd0e..bf3e76df7 100644 --- a/aspnet-core/tests/LINGYUN.Abp.Localization.Xml.Tests/LINGYUN.Abp.Localization.Xml.Tests.csproj +++ b/aspnet-core/tests/LINGYUN.Abp.Localization.Xml.Tests/LINGYUN.Abp.Localization.Xml.Tests.csproj @@ -4,7 +4,7 @@ net10.0 false - Debug;Release;PostgreSQL + Debug;Release AnyCPU diff --git a/aspnet-core/tests/LINGYUN.Abp.Location.Baidu.Tests/LINGYUN.Abp.Location.Baidu.Tests.csproj b/aspnet-core/tests/LINGYUN.Abp.Location.Baidu.Tests/LINGYUN.Abp.Location.Baidu.Tests.csproj index 5403728ef..78b34d343 100644 --- a/aspnet-core/tests/LINGYUN.Abp.Location.Baidu.Tests/LINGYUN.Abp.Location.Baidu.Tests.csproj +++ b/aspnet-core/tests/LINGYUN.Abp.Location.Baidu.Tests/LINGYUN.Abp.Location.Baidu.Tests.csproj @@ -4,7 +4,7 @@ net10.0 false - Debug;Release;PostgreSQL + Debug;Release AnyCPU diff --git a/aspnet-core/tests/LINGYUN.Abp.Location.Tencent.Tests/LINGYUN.Abp.Location.Tencent.Tests.csproj b/aspnet-core/tests/LINGYUN.Abp.Location.Tencent.Tests/LINGYUN.Abp.Location.Tencent.Tests.csproj index f3ded9292..b834e1b6e 100644 --- a/aspnet-core/tests/LINGYUN.Abp.Location.Tencent.Tests/LINGYUN.Abp.Location.Tencent.Tests.csproj +++ b/aspnet-core/tests/LINGYUN.Abp.Location.Tencent.Tests/LINGYUN.Abp.Location.Tencent.Tests.csproj @@ -4,7 +4,7 @@ net10.0 false - Debug;Release;PostgreSQL + Debug;Release AnyCPU diff --git a/aspnet-core/tests/LINGYUN.Abp.Rules.RulesEngine.Tests/LINGYUN.Abp.Rules.RulesEngine.Tests.csproj b/aspnet-core/tests/LINGYUN.Abp.Rules.RulesEngine.Tests/LINGYUN.Abp.Rules.RulesEngine.Tests.csproj index 5cab4d768..86f87f2a3 100644 --- a/aspnet-core/tests/LINGYUN.Abp.Rules.RulesEngine.Tests/LINGYUN.Abp.Rules.RulesEngine.Tests.csproj +++ b/aspnet-core/tests/LINGYUN.Abp.Rules.RulesEngine.Tests/LINGYUN.Abp.Rules.RulesEngine.Tests.csproj @@ -4,7 +4,7 @@ net10.0 false - Debug;Release;PostgreSQL + Debug;Release AnyCPU diff --git a/aspnet-core/tests/LINGYUN.Abp.WeChat.Work.Tests/LINGYUN.Abp.WeChat.Work.Tests.csproj b/aspnet-core/tests/LINGYUN.Abp.WeChat.Work.Tests/LINGYUN.Abp.WeChat.Work.Tests.csproj index 4996893e6..7b19b6a03 100644 --- a/aspnet-core/tests/LINGYUN.Abp.WeChat.Work.Tests/LINGYUN.Abp.WeChat.Work.Tests.csproj +++ b/aspnet-core/tests/LINGYUN.Abp.WeChat.Work.Tests/LINGYUN.Abp.WeChat.Work.Tests.csproj @@ -4,7 +4,7 @@ net10.0 false - Debug;Release;PostgreSQL + Debug;Release AnyCPU