diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 2aba71e24..26a39ee8d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -2,7 +2,7 @@ name: "Tagged Release" on: push: - branches: [ master ] + branches: [ rel-7.0.2 ] jobs: tagged-release: diff --git a/apps/vue/src/api/text-templating/contents/index.ts b/apps/vue/src/api/text-templating/contents/index.ts new file mode 100644 index 000000000..ebd2632fa --- /dev/null +++ b/apps/vue/src/api/text-templating/contents/index.ts @@ -0,0 +1,46 @@ +import { defAbpHttp } from '/@/utils/http/abp'; +import { + TextTemplateContentDto, + TextTemplateContentGetInput, + TextTemplateRestoreInput, + TextTemplateContentUpdateDto +} from './model'; + +const remoteServiceName = 'AbpTextTemplating'; +const controllerName = 'TextTemplate'; + +export const GetAsyncByInput = (input: TextTemplateContentGetInput) => { + return defAbpHttp.request({ + service: remoteServiceName, + controller: controllerName, + action: 'GetAsync', + uniqueName: 'GetAsyncByInput', + params: input, + }); +}; + +export const RestoreToDefaultAsyncByNameAndInput = (name: string, input: TextTemplateRestoreInput) => { + return defAbpHttp.request({ + service: remoteServiceName, + controller: controllerName, + action: 'RestoreToDefaultAsync', + uniqueName: 'RestoreToDefaultAsyncByNameAndInput', + params: { + name: name, + }, + data: input, + }); +}; + +export const UpdateAsyncByNameAndInput = (name: string, input: TextTemplateContentUpdateDto) => { + return defAbpHttp.request({ + service: remoteServiceName, + controller: controllerName, + action: 'UpdateAsync', + uniqueName: 'UpdateAsyncByNameAndInput', + params: { + name: name, + }, + data: input, + }); +}; diff --git a/apps/vue/src/api/text-templating/contents/model/index.ts b/apps/vue/src/api/text-templating/contents/model/index.ts new file mode 100644 index 000000000..3e47dc069 --- /dev/null +++ b/apps/vue/src/api/text-templating/contents/model/index.ts @@ -0,0 +1,19 @@ +export interface TextTemplateContentDto { + name: string; + content?: string; + culture?: string; +} + +export interface TextTemplateContentGetInput { + name: string; + culture?: string; +} + +export interface TextTemplateRestoreInput { + culture?: string; +} + +export interface TextTemplateContentUpdateDto { + culture?: string; + content: string; +} diff --git a/apps/vue/src/api/text-templating/definitions/index.ts b/apps/vue/src/api/text-templating/definitions/index.ts new file mode 100644 index 000000000..86c3b6352 --- /dev/null +++ b/apps/vue/src/api/text-templating/definitions/index.ts @@ -0,0 +1,67 @@ +import { defAbpHttp } from '/@/utils/http/abp'; +import { + TextTemplateDefinitionDto, + TextTemplateDefinitionCreateDto, + TextTemplateDefinitionUpdateDto, + TextTemplateDefinitionGetListInput +} from './model'; + +const remoteServiceName = 'AbpTextTemplating'; +const controllerName = 'TextTemplateDefinition'; + +export const CreateAsyncByInput = (input: TextTemplateDefinitionCreateDto) => { + return defAbpHttp.request({ + service: remoteServiceName, + controller: controllerName, + action: 'CreateAsync', + uniqueName: 'CreateAsyncByInput', + params: input, + }); +}; + +export const DeleteAsyncByName = (name: string) => { + return defAbpHttp.request({ + service: remoteServiceName, + controller: controllerName, + action: 'DeleteAsync', + uniqueName: 'DeleteAsyncByName', + params: { + name: name, + }, + }); +}; + +export const GetByNameAsyncByName = (name: string) => { + return defAbpHttp.request({ + service: remoteServiceName, + controller: controllerName, + action: 'GetByNameAsync', + uniqueName: 'GetByNameAsyncByName', + params: { + name: name, + }, + }); +}; + +export const GetListAsyncByInput = (input: TextTemplateDefinitionGetListInput) => { + return defAbpHttp.request>({ + service: remoteServiceName, + controller: controllerName, + action: 'GetListAsync', + uniqueName: 'GetListAsyncByInput', + params: input, + }); +}; + +export const UpdateAsyncByNameAndInput = (name: string, input: TextTemplateDefinitionUpdateDto) => { + return defAbpHttp.request({ + service: remoteServiceName, + controller: controllerName, + action: 'UpdateAsync', + uniqueName: 'UpdateAsyncByNameAndInput', + params: { + name: name, + }, + data: input, + }); +}; diff --git a/apps/vue/src/api/text-templating/definitions/model/index.ts b/apps/vue/src/api/text-templating/definitions/model/index.ts new file mode 100644 index 000000000..afd0aba0d --- /dev/null +++ b/apps/vue/src/api/text-templating/definitions/model/index.ts @@ -0,0 +1,30 @@ +export interface TextTemplateDefinitionDto { + name: string; + displayName: string; + defaultCultureName?: string; + isInlineLocalized: boolean; + isLayout: boolean; + layout: string; + isStatic: boolean; + renderEngine?: string; +} + +interface TextTemplateDefinitionCreateOrUpdateDto { + displayName: string; + defaultCultureName?: string; + isInlineLocalized: boolean; + isLayout: boolean; + layout: string; + isStatic: boolean; + renderEngine?: string; +} + +export interface TextTemplateDefinitionCreateDto extends TextTemplateDefinitionCreateOrUpdateDto { + name: string; +} + +export interface TextTemplateDefinitionUpdateDto extends TextTemplateDefinitionCreateOrUpdateDto, IHasConcurrencyStamp { } + +export interface TextTemplateDefinitionGetListInput extends PagedAndSortedResultRequestDto { + filter?: string; +} \ No newline at end of file diff --git a/apps/vue/src/api/text-templating/templates/index.ts b/apps/vue/src/api/text-templating/templates/index.ts deleted file mode 100644 index c4e1a0065..000000000 --- a/apps/vue/src/api/text-templating/templates/index.ts +++ /dev/null @@ -1,63 +0,0 @@ -import { defAbpHttp } from '/@/utils/http/abp'; -import { - TextTemplateDefinition, - TextTemplateContent, - TextTemplateContentGetInput, - TextTemplateUpdateInput, - TextTemplateRestoreInput, - TextTemplateDefinitionGetListInput, -} from './model'; - -const remoteServiceName = 'AbpTextTemplating'; -const controllerName = 'TextTemplate'; - -export const get = (name: string) => { - return defAbpHttp.request({ - service: remoteServiceName, - controller: controllerName, - action: 'GetAsync', - params: { - name: name, - }, - }); -}; - -export const getContent = (input: TextTemplateContentGetInput) => { - return defAbpHttp.request({ - service: remoteServiceName, - controller: controllerName, - action: 'GetContentAsync', - params: { - input: input, - }, - }); -} - -export const getList = (input: TextTemplateDefinitionGetListInput) => { - return defAbpHttp.request>({ - service: remoteServiceName, - controller: controllerName, - action: 'GetListAsync', - params: { - input: input, - }, - }); -}; - -export const restoreToDefault = (input: TextTemplateRestoreInput) => { - return defAbpHttp.request({ - service: remoteServiceName, - controller: controllerName, - action: 'RestoreToDefaultAsync', - data: input, - }); -}; - -export const update = (input: TextTemplateUpdateInput) => { - return defAbpHttp.request({ - service: remoteServiceName, - controller: controllerName, - action: 'UpdateAsync', - data: input, - }); -}; diff --git a/apps/vue/src/api/text-templating/templates/model/index.ts b/apps/vue/src/api/text-templating/templates/model/index.ts deleted file mode 100644 index 87b512f4d..000000000 --- a/apps/vue/src/api/text-templating/templates/model/index.ts +++ /dev/null @@ -1,34 +0,0 @@ -export interface TextTemplateDefinition { - name: string; - displayName: string; - defaultCultureName?: string; - isInlineLocalized: boolean; - isLayout: boolean; - layout?: string; -} - -export interface TextTemplateContent { - name: string; - content?: string; - culture?: string; -} - -export interface TextTemplateContentGetInput { - name: string; - culture?: string; -} - -export interface TextTemplateRestoreInput { - name: string; - culture?: string; -} - -export interface TextTemplateUpdateInput { - name: string; - culture?: string; - content: string; -} - -export interface TextTemplateDefinitionGetListInput extends PagedAndSortedResultRequestDto { - filter?: string; -} diff --git a/apps/vue/src/views/text-templating/templates/components/TemplateContentCultureModal.vue b/apps/vue/src/views/text-templating/templates/components/TemplateContentCultureModal.vue index 1153f947c..32b941767 100644 --- a/apps/vue/src/views/text-templating/templates/components/TemplateContentCultureModal.vue +++ b/apps/vue/src/views/text-templating/templates/components/TemplateContentCultureModal.vue @@ -23,15 +23,15 @@ import { BasicModal, useModalInner } from '/@/components/Modal'; import { useMessage } from '/@/hooks/web/useMessage'; import { useLocalization } from '/@/hooks/abp/useLocalization'; - import { TextTemplateDefinition } from '/@/api/text-templating/templates/model'; - import { getContent, restoreToDefault, update } from '/@/api/text-templating/templates'; + import { TextTemplateDefinitionDto } from '/@/api/text-templating/definitions/model'; + import { GetAsyncByInput, RestoreToDefaultAsyncByNameAndInput, UpdateAsyncByNameAndInput } from '/@/api/text-templating/contents'; import { useAbpStoreWithOut } from '/@/store/modules/abp'; const abpStore = useAbpStoreWithOut(); const { L } = useLocalization('AbpTextTemplating'); const { createConfirm, createMessage } = useMessage(); const { localization } = abpStore.getApplication; - const textTemplateRef = ref(); + const textTemplateRef = ref(); const buttonEnabled = computed(() => { const textTemplate = unref(textTemplateRef); if (textTemplate && textTemplate.name) { @@ -118,7 +118,7 @@ }); function fetchDefaultContent(name: string) { - getContent({ + GetAsyncByInput({ name: name, culture: localization.currentCulture.name, }).then((res) => { @@ -130,7 +130,7 @@ } function handleCultureChange(setField: string, selectedValue: string) { - getContent({ + GetAsyncByInput({ name: textTemplateRef.value!.name, culture: selectedValue, }).then((res) => { @@ -150,8 +150,7 @@ onOk: () => { return new Promise((resolve, reject) => { const textTemplate = unref(textTemplateRef); - restoreToDefault({ - name: textTemplate!.name, + RestoreToDefaultAsyncByNameAndInput(textTemplate!.name, { culture: input.baseCultureName, }).then(() => { createMessage.success(L('TemplateContentRestoredToDefault')); @@ -170,8 +169,7 @@ validateFields(['targetCultureName', 'targetContent']).then((input) => { changeOkLoading(true); const textTemplate = unref(textTemplateRef); - update({ - name: textTemplate!.name, + UpdateAsyncByNameAndInput(textTemplate!.name, { culture: input.targetCultureName, content: input.targetContent, }).then(() => { diff --git a/apps/vue/src/views/text-templating/templates/components/TemplateContentModal.vue b/apps/vue/src/views/text-templating/templates/components/TemplateContentModal.vue index 5d99c1bcc..b077338f4 100644 --- a/apps/vue/src/views/text-templating/templates/components/TemplateContentModal.vue +++ b/apps/vue/src/views/text-templating/templates/components/TemplateContentModal.vue @@ -33,13 +33,13 @@ import { BasicModal, useModal, useModalInner } from '/@/components/Modal'; import { useMessage } from '/@/hooks/web/useMessage'; import { useLocalization } from '/@/hooks/abp/useLocalization'; - import { TextTemplateDefinition } from '/@/api/text-templating/templates/model'; - import { getContent, restoreToDefault, update } from '/@/api/text-templating/templates'; + import { TextTemplateDefinitionDto } from '/@/api/text-templating/definitions/model'; + import { GetAsyncByInput, RestoreToDefaultAsyncByNameAndInput, UpdateAsyncByNameAndInput } from '/@/api/text-templating/contents'; import TemplateContentCultureModal from './TemplateContentCultureModal.vue'; const { L } = useLocalization('AbpTextTemplating'); const { createConfirm, createMessage } = useMessage(); - const textTemplateRef = ref(); + const textTemplateRef = ref(); const buttonEnabled = computed(() => { const textTemplate = unref(textTemplateRef); if (textTemplate && textTemplate.name) { @@ -85,7 +85,7 @@ const [registerCultureModal, { openModal: openCultureModal }] = useModal(); function fetchContent(name: string) { - getContent({ + GetAsyncByInput({ name: name, }).then((res) => { setFieldsValue(res); @@ -104,7 +104,7 @@ onOk: () => { return new Promise((resolve, reject) => { const textTemplate = unref(textTemplateRef); - restoreToDefault({ name: textTemplate!.name }).then(() => { + RestoreToDefaultAsyncByNameAndInput(textTemplate!.name, { }).then(() => { createMessage.success(L('TemplateContentRestoredToDefault')); fetchContent(textTemplate!.name); return resolve(textTemplate!.name); @@ -120,8 +120,7 @@ validate().then((input) => { changeOkLoading(true); const textTemplate = unref(textTemplateRef); - update({ - name: textTemplate!.name, + UpdateAsyncByNameAndInput(textTemplate!.name, { content: input.content, }).then(() => { createMessage.success(L('TemplateContentUpdated')); diff --git a/apps/vue/src/views/text-templating/templates/components/TemplateDefinitionTable.vue b/apps/vue/src/views/text-templating/templates/components/TemplateDefinitionTable.vue new file mode 100644 index 000000000..03eb34b09 --- /dev/null +++ b/apps/vue/src/views/text-templating/templates/components/TemplateDefinitionTable.vue @@ -0,0 +1,111 @@ + + + diff --git a/apps/vue/src/views/text-templating/templates/components/TemplateTable.vue b/apps/vue/src/views/text-templating/templates/components/TemplateTable.vue deleted file mode 100644 index 5b94baa40..000000000 --- a/apps/vue/src/views/text-templating/templates/components/TemplateTable.vue +++ /dev/null @@ -1,71 +0,0 @@ - - - diff --git a/apps/vue/src/views/text-templating/templates/datas/ModalData.ts b/apps/vue/src/views/text-templating/templates/datas/ModalData.ts index 3856bd76e..20a241630 100644 --- a/apps/vue/src/views/text-templating/templates/datas/ModalData.ts +++ b/apps/vue/src/views/text-templating/templates/datas/ModalData.ts @@ -1,32 +1,30 @@ import { useLocalization } from '/@/hooks/abp/useLocalization'; -import { FormProps } from '/@/components/Form'; -import { NotificationReadState } from '/@/api/messages/model/notificationsModel'; +import { FormProps, FormSchema } from '/@/components/Form'; -const { L } = useLocalization(['AbpMessageService', 'AbpUi']); +const { L } = useLocalization(['AbpTextTemplating', 'AbpUi']); export function getSearchFormSchemas(): Partial { return { labelWidth: 100, schemas: [ - { - field: 'readState', - component: 'Select', - label: L('Notifications:State'), - colProps: { span: 8 }, - defaultValue: NotificationReadState.UnRead, - componentProps: { - options: [ - { label: L('Read'), value: NotificationReadState.Read, }, - { label: L('UnRead'), value: NotificationReadState.UnRead, }, - ], - }, - }, { field: 'filter', component: 'Input', label: L('Search'), - colProps: { span: 16 }, + colProps: { span: 24 }, }, ], }; } + +export function getModalFormSchemas(): FormSchema[] { + return [ + { + field: 'name', + component: 'Input', + label: L('DisplayName:Name'), + colProps: { span: 24 }, + required: true, + }, + ]; +} diff --git a/apps/vue/src/views/text-templating/templates/datas/TableData.ts b/apps/vue/src/views/text-templating/templates/datas/TableData.ts index fad5c6ecb..595ef383f 100644 --- a/apps/vue/src/views/text-templating/templates/datas/TableData.ts +++ b/apps/vue/src/views/text-templating/templates/datas/TableData.ts @@ -1,17 +1,37 @@ import { useLocalization } from '/@/hooks/abp/useLocalization'; import { BasicColumn } from '/@/components/Table'; -const { L } = useLocalization('AbpTextTemplating'); +const { L } = useLocalization(['AbpTextTemplating']); export function getDataColumns(): BasicColumn[] { return [ { title: L('DisplayName:Name'), + dataIndex: 'name', + align: 'left', + width: 100, + sorter: true, + ellipsis: true, + defaultHidden: true, + resizable: true, + }, + { + title: L('DisplayName:DisplayName'), dataIndex: 'displayName', align: 'left', width: 200, sorter: true, ellipsis: true, + resizable: true, + }, + { + title: L('DisplayName:IsStatic'), + dataIndex: 'isStatic', + align: 'center', + width: 150, + sorter: true, + ellipsis: true, + resizable: true, }, { title: L('DisplayName:IsInlineLocalized'), @@ -20,6 +40,7 @@ export function getDataColumns(): BasicColumn[] { width: 150, sorter: true, ellipsis: true, + resizable: true, }, { title: L('DisplayName:IsLayout'), @@ -28,6 +49,7 @@ export function getDataColumns(): BasicColumn[] { width: 150, sorter: true, ellipsis: true, + resizable: true, }, { title: L('Layout'), @@ -36,6 +58,7 @@ export function getDataColumns(): BasicColumn[] { width: 200, sorter: true, ellipsis: true, + resizable: true, }, { title: L('DisplayName:DefaultCultureName'), @@ -44,6 +67,17 @@ export function getDataColumns(): BasicColumn[] { width: 200, sorter: true, ellipsis: true, + resizable: true, + }, + { + title: L('DisplayName:RenderEngine'), + dataIndex: 'renderEngine', + align: 'left', + width: 150, + sorter: true, + ellipsis: true, + resizable: true, + defaultHidden: true, }, ]; } diff --git a/apps/vue/src/views/text-templating/templates/index.vue b/apps/vue/src/views/text-templating/templates/index.vue index 39f9f26d2..7fddb1e89 100644 --- a/apps/vue/src/views/text-templating/templates/index.vue +++ b/apps/vue/src/views/text-templating/templates/index.vue @@ -1,13 +1,13 @@ diff --git a/aspnet-core/Directory.Build.props b/aspnet-core/Directory.Build.props index d7f47836a..a65ea83ac 100644 --- a/aspnet-core/Directory.Build.props +++ b/aspnet-core/Directory.Build.props @@ -1,9 +1,9 @@  - 7.0.1 + 7.0.2 2.0.1 - 7.0.1 - 1.9.0 + 7.0.2 + 1.10.0 1.0.2 7.0.2 2.10.1 @@ -36,6 +36,7 @@ 6.1.5 7.2.3 7.0.* + 7.0.2 2.4.1 3.0.2 4.2.1 diff --git a/aspnet-core/LINGYUN.MicroService.All.sln b/aspnet-core/LINGYUN.MicroService.All.sln index b83d054c6..598a3a223 100644 --- a/aspnet-core/LINGYUN.MicroService.All.sln +++ b/aspnet-core/LINGYUN.MicroService.All.sln @@ -562,11 +562,15 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LY.MicroService.AuthServer. EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LY.MicroService.IdentityServer.EntityFrameworkCore", "migrations\LY.MicroService.IdentityServer.EntityFrameworkCore\LY.MicroService.IdentityServer.EntityFrameworkCore.csproj", "{F74D8A4E-737F-4144-94BF-9EE80AFC8E9B}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LY.MicroService.LocalizationManagement.EntityFrameworkCore", "migrations\LY.MicroService.LocalizationManagement.EntityFrameworkCore\LY.MicroService.LocalizationManagement.EntityFrameworkCore.csproj", "{7DBC2821-22B2-497F-A594-18CF3EE79940}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LY.MicroService.LocalizationManagement.EntityFrameworkCore", "migrations\LY.MicroService.LocalizationManagement.EntityFrameworkCore\LY.MicroService.LocalizationManagement.EntityFrameworkCore.csproj", "{7DBC2821-22B2-497F-A594-18CF3EE79940}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LY.MicroService.Platform.EntityFrameworkCore", "migrations\LY.MicroService.Platform.EntityFrameworkCore\LY.MicroService.Platform.EntityFrameworkCore.csproj", "{B9421FC5-47EB-428D-92C6-F688D02ABE06}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LY.MicroService.Platform.EntityFrameworkCore", "migrations\LY.MicroService.Platform.EntityFrameworkCore\LY.MicroService.Platform.EntityFrameworkCore.csproj", "{B9421FC5-47EB-428D-92C6-F688D02ABE06}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LY.MicroService.RealtimeMessage.EntityFrameworkCore", "migrations\LY.MicroService.RealtimeMessage.EntityFrameworkCore\LY.MicroService.RealtimeMessage.EntityFrameworkCore.csproj", "{6AC6AC37-0163-4EF2-A49C-2E0B87F73AE9}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LY.MicroService.RealtimeMessage.EntityFrameworkCore", "migrations\LY.MicroService.RealtimeMessage.EntityFrameworkCore\LY.MicroService.RealtimeMessage.EntityFrameworkCore.csproj", "{6AC6AC37-0163-4EF2-A49C-2E0B87F73AE9}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.TextTemplating.Scriban", "modules\text-templating\LINGYUN.Abp.TextTemplating.Scriban\LINGYUN.Abp.TextTemplating.Scriban.csproj", "{E2019836-1C67-47E4-B3AF-D62F4AFC7679}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.TextTemplating.Razor", "modules\text-templating\LINGYUN.Abp.TextTemplating.Razor\LINGYUN.Abp.TextTemplating.Razor.csproj", "{5F83F8D0-822B-4316-B7DD-85DAFDFAA0E2}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -1446,6 +1450,14 @@ Global {6AC6AC37-0163-4EF2-A49C-2E0B87F73AE9}.Debug|Any CPU.Build.0 = Debug|Any CPU {6AC6AC37-0163-4EF2-A49C-2E0B87F73AE9}.Release|Any CPU.ActiveCfg = Release|Any CPU {6AC6AC37-0163-4EF2-A49C-2E0B87F73AE9}.Release|Any CPU.Build.0 = Release|Any CPU + {E2019836-1C67-47E4-B3AF-D62F4AFC7679}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E2019836-1C67-47E4-B3AF-D62F4AFC7679}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E2019836-1C67-47E4-B3AF-D62F4AFC7679}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E2019836-1C67-47E4-B3AF-D62F4AFC7679}.Release|Any CPU.Build.0 = Release|Any CPU + {5F83F8D0-822B-4316-B7DD-85DAFDFAA0E2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5F83F8D0-822B-4316-B7DD-85DAFDFAA0E2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5F83F8D0-822B-4316-B7DD-85DAFDFAA0E2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5F83F8D0-822B-4316-B7DD-85DAFDFAA0E2}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -1720,6 +1732,8 @@ Global {7DBC2821-22B2-497F-A594-18CF3EE79940} = {B18CF0D3-3D01-4A64-A9C4-DC0C214BEE42} {B9421FC5-47EB-428D-92C6-F688D02ABE06} = {F260FB5F-C6C7-4948-B638-E4D6986D07ED} {6AC6AC37-0163-4EF2-A49C-2E0B87F73AE9} = {B1AC656F-8F4C-43D5-B5A0-CCF5F119EA44} + {E2019836-1C67-47E4-B3AF-D62F4AFC7679} = {ABD89F39-62D9-439E-8662-BE4F36BFA04F} + {5F83F8D0-822B-4316-B7DD-85DAFDFAA0E2} = {ABD89F39-62D9-439E-8662-BE4F36BFA04F} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {C95FDF91-16F2-4A8B-A4BE-0E62D1B66718} diff --git a/aspnet-core/common.props b/aspnet-core/common.props index 217d8cf72..f4964beb5 100644 --- a/aspnet-core/common.props +++ b/aspnet-core/common.props @@ -1,7 +1,7 @@ latest - 7.0.1 + 7.0.2 colin $(NoWarn);CS1591;CS0436;CS8618;NU1803 https://github.com/colinin/abp-next-admin diff --git a/aspnet-core/migrations/LY.MicroService.AuthServer.EntityFrameworkCore/LY.MicroService.AuthServer.EntityFrameworkCore.csproj b/aspnet-core/migrations/LY.MicroService.AuthServer.EntityFrameworkCore/LY.MicroService.AuthServer.EntityFrameworkCore.csproj index 87b3b42c2..e56965cff 100644 --- a/aspnet-core/migrations/LY.MicroService.AuthServer.EntityFrameworkCore/LY.MicroService.AuthServer.EntityFrameworkCore.csproj +++ b/aspnet-core/migrations/LY.MicroService.AuthServer.EntityFrameworkCore/LY.MicroService.AuthServer.EntityFrameworkCore.csproj @@ -9,7 +9,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/aspnet-core/migrations/LY.MicroService.BackendAdmin.EntityFrameworkCore/LY.MicroService.BackendAdmin.EntityFrameworkCore.csproj b/aspnet-core/migrations/LY.MicroService.BackendAdmin.EntityFrameworkCore/LY.MicroService.BackendAdmin.EntityFrameworkCore.csproj index dbedf316f..1a5c4dfbb 100644 --- a/aspnet-core/migrations/LY.MicroService.BackendAdmin.EntityFrameworkCore/LY.MicroService.BackendAdmin.EntityFrameworkCore.csproj +++ b/aspnet-core/migrations/LY.MicroService.BackendAdmin.EntityFrameworkCore/LY.MicroService.BackendAdmin.EntityFrameworkCore.csproj @@ -9,7 +9,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/aspnet-core/migrations/LY.MicroService.BackendAdmin.EntityFrameworkCore/Migrations/20230304062910_Add-Text-Template-Definition.Designer.cs b/aspnet-core/migrations/LY.MicroService.BackendAdmin.EntityFrameworkCore/Migrations/20230304062910_Add-Text-Template-Definition.Designer.cs new file mode 100644 index 000000000..a71957bf8 --- /dev/null +++ b/aspnet-core/migrations/LY.MicroService.BackendAdmin.EntityFrameworkCore/Migrations/20230304062910_Add-Text-Template-Definition.Designer.cs @@ -0,0 +1,578 @@ +// +using System; +using LY.MicroService.BackendAdmin.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Volo.Abp.EntityFrameworkCore; + +#nullable disable + +namespace LY.MicroService.BackendAdmin.EntityFrameworkCore.Migrations +{ + [DbContext(typeof(BackendAdminMigrationsDbContext))] + [Migration("20230304062910_Add-Text-Template-Definition")] + partial class AddTextTemplateDefinition + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.MySql) + .HasAnnotation("ProductVersion", "7.0.2") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + modelBuilder.Entity("LINGYUN.Abp.Saas.Editions.Edition", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasMaxLength(40) + .HasColumnType("varchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("datetime(6)") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("char(36)") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("char(36)") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime(6)") + .HasColumnName("DeletionTime"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("ExtraProperties") + .HasColumnType("longtext") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("datetime(6)") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("char(36)") + .HasColumnName("LastModifierId"); + + b.HasKey("Id"); + + b.HasIndex("DisplayName"); + + b.ToTable("AbpEditions", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Abp.Saas.Tenants.Tenant", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasMaxLength(40) + .HasColumnType("varchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("datetime(6)") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("char(36)") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("char(36)") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime(6)") + .HasColumnName("DeletionTime"); + + b.Property("DisableTime") + .HasColumnType("datetime(6)"); + + b.Property("EditionId") + .HasColumnType("char(36)"); + + b.Property("EnableTime") + .HasColumnType("datetime(6)"); + + b.Property("ExtraProperties") + .HasColumnType("longtext") + .HasColumnName("ExtraProperties"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("datetime(6)") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("char(36)") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.HasKey("Id"); + + b.HasIndex("EditionId"); + + b.HasIndex("Name"); + + b.ToTable("AbpTenants", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Abp.Saas.Tenants.TenantConnectionString", b => + { + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.Property("Name") + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("Value") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("varchar(1024)"); + + b.HasKey("TenantId", "Name"); + + b.ToTable("AbpTenantConnectionStrings", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Abp.TextTemplating.TextTemplate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Content") + .HasMaxLength(1048576) + .HasColumnType("longtext") + .HasColumnName("Content"); + + b.Property("CreationTime") + .HasColumnType("datetime(6)") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("char(36)") + .HasColumnName("CreatorId"); + + b.Property("Culture") + .HasMaxLength(30) + .HasColumnType("varchar(30)") + .HasColumnName("Culture"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)") + .HasColumnName("DisplayName"); + + b.Property("LastModificationTime") + .HasColumnType("datetime(6)") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("char(36)") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)") + .HasColumnName("Name"); + + b.Property("TenantId") + .HasColumnType("char(36)") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "Name") + .HasDatabaseName("IX_Tenant_Text_Template_Name"); + + b.ToTable("AbpTextTemplates", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Abp.TextTemplating.TextTemplateDefinition", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasMaxLength(40) + .HasColumnType("varchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("DefaultCultureName") + .HasMaxLength(30) + .HasColumnType("varchar(30)") + .HasColumnName("DefaultCultureName"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(512) + .HasColumnType("varchar(512)") + .HasColumnName("DisplayName"); + + b.Property("ExtraProperties") + .HasColumnType("longtext") + .HasColumnName("ExtraProperties"); + + b.Property("IsInlineLocalized") + .HasColumnType("tinyint(1)"); + + b.Property("IsLayout") + .HasColumnType("tinyint(1)"); + + b.Property("Layout") + .HasMaxLength(60) + .HasColumnType("varchar(60)") + .HasColumnName("Layout"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)") + .HasColumnName("Name"); + + b.Property("RenderEngine") + .HasMaxLength(30) + .HasColumnType("varchar(30)") + .HasColumnName("RenderEngine"); + + b.HasKey("Id"); + + b.ToTable("AbpTextTemplateDefinitions", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.FeatureManagement.FeatureDefinitionRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("AllowedProviders") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("DefaultValue") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("Description") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("ExtraProperties") + .HasColumnType("longtext") + .HasColumnName("ExtraProperties"); + + b.Property("GroupName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("IsAvailableToHost") + .HasColumnType("tinyint(1)"); + + b.Property("IsVisibleToClients") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("ParentName") + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("ValueType") + .HasMaxLength(2048) + .HasColumnType("varchar(2048)"); + + b.HasKey("Id"); + + b.HasIndex("GroupName"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("AbpFeatures", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.FeatureManagement.FeatureGroupDefinitionRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("ExtraProperties") + .HasColumnType("longtext") + .HasColumnName("ExtraProperties"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("AbpFeatureGroups", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.FeatureManagement.FeatureValue", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("ProviderKey") + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("ProviderName") + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("Value") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.HasKey("Id"); + + b.HasIndex("Name", "ProviderName", "ProviderKey") + .IsUnique(); + + b.ToTable("AbpFeatureValues", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionDefinitionRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("ExtraProperties") + .HasColumnType("longtext") + .HasColumnName("ExtraProperties"); + + b.Property("GroupName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("IsEnabled") + .HasColumnType("tinyint(1)"); + + b.Property("MultiTenancySide") + .HasColumnType("tinyint unsigned"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("ParentName") + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("Providers") + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("StateCheckers") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("GroupName"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("AbpPermissions", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionGrant", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("ProviderKey") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("ProviderName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("TenantId") + .HasColumnType("char(36)") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "Name", "ProviderName", "ProviderKey") + .IsUnique(); + + b.ToTable("AbpPermissionGrants", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionGroupDefinitionRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("ExtraProperties") + .HasColumnType("longtext") + .HasColumnName("ExtraProperties"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("AbpPermissionGroups", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.SettingManagement.Setting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("ProviderKey") + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("ProviderName") + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("Value") + .IsRequired() + .HasMaxLength(2048) + .HasColumnType("varchar(2048)"); + + b.HasKey("Id"); + + b.HasIndex("Name", "ProviderName", "ProviderKey") + .IsUnique(); + + b.ToTable("AbpSettings", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Abp.Saas.Tenants.Tenant", b => + { + b.HasOne("LINGYUN.Abp.Saas.Editions.Edition", "Edition") + .WithMany() + .HasForeignKey("EditionId"); + + b.Navigation("Edition"); + }); + + modelBuilder.Entity("LINGYUN.Abp.Saas.Tenants.TenantConnectionString", b => + { + b.HasOne("LINGYUN.Abp.Saas.Tenants.Tenant", null) + .WithMany("ConnectionStrings") + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("LINGYUN.Abp.Saas.Tenants.Tenant", b => + { + b.Navigation("ConnectionStrings"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/aspnet-core/migrations/LY.MicroService.BackendAdmin.EntityFrameworkCore/Migrations/20230304062910_Add-Text-Template-Definition.cs b/aspnet-core/migrations/LY.MicroService.BackendAdmin.EntityFrameworkCore/Migrations/20230304062910_Add-Text-Template-Definition.cs new file mode 100644 index 000000000..e79e1d89d --- /dev/null +++ b/aspnet-core/migrations/LY.MicroService.BackendAdmin.EntityFrameworkCore/Migrations/20230304062910_Add-Text-Template-Definition.cs @@ -0,0 +1,50 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace LY.MicroService.BackendAdmin.EntityFrameworkCore.Migrations +{ + /// + public partial class AddTextTemplateDefinition : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "AbpTextTemplateDefinitions", + columns: table => new + { + Id = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + Name = table.Column(type: "varchar(128)", maxLength: 128, nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + DisplayName = table.Column(type: "varchar(512)", maxLength: 512, nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + IsLayout = table.Column(type: "tinyint(1)", nullable: false), + Layout = table.Column(type: "varchar(60)", maxLength: 60, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + IsInlineLocalized = table.Column(type: "tinyint(1)", nullable: false), + DefaultCultureName = table.Column(type: "varchar(30)", maxLength: 30, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + RenderEngine = table.Column(type: "varchar(30)", maxLength: 30, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + ExtraProperties = table.Column(type: "longtext", nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + ConcurrencyStamp = table.Column(type: "varchar(40)", maxLength: 40, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4") + }, + constraints: table => + { + table.PrimaryKey("PK_AbpTextTemplateDefinitions", x => x.Id); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "AbpTextTemplateDefinitions"); + } + } +} diff --git a/aspnet-core/migrations/LY.MicroService.BackendAdmin.EntityFrameworkCore/Migrations/20230304083526_Add-IsStatic-Field.Designer.cs b/aspnet-core/migrations/LY.MicroService.BackendAdmin.EntityFrameworkCore/Migrations/20230304083526_Add-IsStatic-Field.Designer.cs new file mode 100644 index 000000000..a3262f61b --- /dev/null +++ b/aspnet-core/migrations/LY.MicroService.BackendAdmin.EntityFrameworkCore/Migrations/20230304083526_Add-IsStatic-Field.Designer.cs @@ -0,0 +1,581 @@ +// +using System; +using LY.MicroService.BackendAdmin.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Volo.Abp.EntityFrameworkCore; + +#nullable disable + +namespace LY.MicroService.BackendAdmin.EntityFrameworkCore.Migrations +{ + [DbContext(typeof(BackendAdminMigrationsDbContext))] + [Migration("20230304083526_Add-IsStatic-Field")] + partial class AddIsStaticField + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.MySql) + .HasAnnotation("ProductVersion", "7.0.2") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + modelBuilder.Entity("LINGYUN.Abp.Saas.Editions.Edition", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasMaxLength(40) + .HasColumnType("varchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("datetime(6)") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("char(36)") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("char(36)") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime(6)") + .HasColumnName("DeletionTime"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("ExtraProperties") + .HasColumnType("longtext") + .HasColumnName("ExtraProperties"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("datetime(6)") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("char(36)") + .HasColumnName("LastModifierId"); + + b.HasKey("Id"); + + b.HasIndex("DisplayName"); + + b.ToTable("AbpEditions", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Abp.Saas.Tenants.Tenant", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasMaxLength(40) + .HasColumnType("varchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("CreationTime") + .HasColumnType("datetime(6)") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("char(36)") + .HasColumnName("CreatorId"); + + b.Property("DeleterId") + .HasColumnType("char(36)") + .HasColumnName("DeleterId"); + + b.Property("DeletionTime") + .HasColumnType("datetime(6)") + .HasColumnName("DeletionTime"); + + b.Property("DisableTime") + .HasColumnType("datetime(6)"); + + b.Property("EditionId") + .HasColumnType("char(36)"); + + b.Property("EnableTime") + .HasColumnType("datetime(6)"); + + b.Property("ExtraProperties") + .HasColumnType("longtext") + .HasColumnName("ExtraProperties"); + + b.Property("IsActive") + .HasColumnType("tinyint(1)"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint(1)") + .HasDefaultValue(false) + .HasColumnName("IsDeleted"); + + b.Property("LastModificationTime") + .HasColumnType("datetime(6)") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("char(36)") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.HasKey("Id"); + + b.HasIndex("EditionId"); + + b.HasIndex("Name"); + + b.ToTable("AbpTenants", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Abp.Saas.Tenants.TenantConnectionString", b => + { + b.Property("TenantId") + .HasColumnType("char(36)"); + + b.Property("Name") + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("Value") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("varchar(1024)"); + + b.HasKey("TenantId", "Name"); + + b.ToTable("AbpTenantConnectionStrings", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Abp.TextTemplating.TextTemplate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Content") + .HasMaxLength(1048576) + .HasColumnType("longtext") + .HasColumnName("Content"); + + b.Property("CreationTime") + .HasColumnType("datetime(6)") + .HasColumnName("CreationTime"); + + b.Property("CreatorId") + .HasColumnType("char(36)") + .HasColumnName("CreatorId"); + + b.Property("Culture") + .HasMaxLength(30) + .HasColumnType("varchar(30)") + .HasColumnName("Culture"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)") + .HasColumnName("DisplayName"); + + b.Property("LastModificationTime") + .HasColumnType("datetime(6)") + .HasColumnName("LastModificationTime"); + + b.Property("LastModifierId") + .HasColumnType("char(36)") + .HasColumnName("LastModifierId"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("varchar(100)") + .HasColumnName("Name"); + + b.Property("TenantId") + .HasColumnType("char(36)") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "Name") + .HasDatabaseName("IX_Tenant_Text_Template_Name"); + + b.ToTable("AbpTextTemplates", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Abp.TextTemplating.TextTemplateDefinition", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasMaxLength(40) + .HasColumnType("varchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("DefaultCultureName") + .HasMaxLength(30) + .HasColumnType("varchar(30)") + .HasColumnName("DefaultCultureName"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(512) + .HasColumnType("varchar(512)") + .HasColumnName("DisplayName"); + + b.Property("ExtraProperties") + .HasColumnType("longtext") + .HasColumnName("ExtraProperties"); + + b.Property("IsInlineLocalized") + .HasColumnType("tinyint(1)"); + + b.Property("IsLayout") + .HasColumnType("tinyint(1)"); + + b.Property("IsStatic") + .HasColumnType("tinyint(1)"); + + b.Property("Layout") + .HasMaxLength(60) + .HasColumnType("varchar(60)") + .HasColumnName("Layout"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)") + .HasColumnName("Name"); + + b.Property("RenderEngine") + .HasMaxLength(30) + .HasColumnType("varchar(30)") + .HasColumnName("RenderEngine"); + + b.HasKey("Id"); + + b.ToTable("AbpTextTemplateDefinitions", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.FeatureManagement.FeatureDefinitionRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("AllowedProviders") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("DefaultValue") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("Description") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("ExtraProperties") + .HasColumnType("longtext") + .HasColumnName("ExtraProperties"); + + b.Property("GroupName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("IsAvailableToHost") + .HasColumnType("tinyint(1)"); + + b.Property("IsVisibleToClients") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("ParentName") + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("ValueType") + .HasMaxLength(2048) + .HasColumnType("varchar(2048)"); + + b.HasKey("Id"); + + b.HasIndex("GroupName"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("AbpFeatures", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.FeatureManagement.FeatureGroupDefinitionRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("ExtraProperties") + .HasColumnType("longtext") + .HasColumnName("ExtraProperties"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("AbpFeatureGroups", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.FeatureManagement.FeatureValue", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("ProviderKey") + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("ProviderName") + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("Value") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.HasKey("Id"); + + b.HasIndex("Name", "ProviderName", "ProviderKey") + .IsUnique(); + + b.ToTable("AbpFeatureValues", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionDefinitionRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("ExtraProperties") + .HasColumnType("longtext") + .HasColumnName("ExtraProperties"); + + b.Property("GroupName") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("IsEnabled") + .HasColumnType("tinyint(1)"); + + b.Property("MultiTenancySide") + .HasColumnType("tinyint unsigned"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("ParentName") + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("Providers") + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("StateCheckers") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.HasKey("Id"); + + b.HasIndex("GroupName"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("AbpPermissions", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionGrant", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("ProviderKey") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("ProviderName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("TenantId") + .HasColumnType("char(36)") + .HasColumnName("TenantId"); + + b.HasKey("Id"); + + b.HasIndex("TenantId", "Name", "ProviderName", "ProviderKey") + .IsUnique(); + + b.ToTable("AbpPermissionGrants", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.PermissionManagement.PermissionGroupDefinitionRecord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("ExtraProperties") + .HasColumnType("longtext") + .HasColumnName("ExtraProperties"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("AbpPermissionGroups", (string)null); + }); + + modelBuilder.Entity("Volo.Abp.SettingManagement.Setting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("ProviderKey") + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("ProviderName") + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("Value") + .IsRequired() + .HasMaxLength(2048) + .HasColumnType("varchar(2048)"); + + b.HasKey("Id"); + + b.HasIndex("Name", "ProviderName", "ProviderKey") + .IsUnique(); + + b.ToTable("AbpSettings", (string)null); + }); + + modelBuilder.Entity("LINGYUN.Abp.Saas.Tenants.Tenant", b => + { + b.HasOne("LINGYUN.Abp.Saas.Editions.Edition", "Edition") + .WithMany() + .HasForeignKey("EditionId"); + + b.Navigation("Edition"); + }); + + modelBuilder.Entity("LINGYUN.Abp.Saas.Tenants.TenantConnectionString", b => + { + b.HasOne("LINGYUN.Abp.Saas.Tenants.Tenant", null) + .WithMany("ConnectionStrings") + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("LINGYUN.Abp.Saas.Tenants.Tenant", b => + { + b.Navigation("ConnectionStrings"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/aspnet-core/migrations/LY.MicroService.BackendAdmin.EntityFrameworkCore/Migrations/20230304083526_Add-IsStatic-Field.cs b/aspnet-core/migrations/LY.MicroService.BackendAdmin.EntityFrameworkCore/Migrations/20230304083526_Add-IsStatic-Field.cs new file mode 100644 index 000000000..e0e6e8290 --- /dev/null +++ b/aspnet-core/migrations/LY.MicroService.BackendAdmin.EntityFrameworkCore/Migrations/20230304083526_Add-IsStatic-Field.cs @@ -0,0 +1,29 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace LY.MicroService.BackendAdmin.EntityFrameworkCore.Migrations +{ + /// + public partial class AddIsStaticField : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "IsStatic", + table: "AbpTextTemplateDefinitions", + type: "tinyint(1)", + nullable: false, + defaultValue: false); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "IsStatic", + table: "AbpTextTemplateDefinitions"); + } + } +} diff --git a/aspnet-core/migrations/LY.MicroService.BackendAdmin.EntityFrameworkCore/Migrations/BackendAdminMigrationsDbContextModelSnapshot.cs b/aspnet-core/migrations/LY.MicroService.BackendAdmin.EntityFrameworkCore/Migrations/BackendAdminMigrationsDbContextModelSnapshot.cs index 79aefffef..c30b458cc 100644 --- a/aspnet-core/migrations/LY.MicroService.BackendAdmin.EntityFrameworkCore/Migrations/BackendAdminMigrationsDbContextModelSnapshot.cs +++ b/aspnet-core/migrations/LY.MicroService.BackendAdmin.EntityFrameworkCore/Migrations/BackendAdminMigrationsDbContextModelSnapshot.cs @@ -18,7 +18,7 @@ namespace LY.MicroService.BackendAdmin.EntityFrameworkCore.Migrations #pragma warning disable 612, 618 modelBuilder .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.MySql) - .HasAnnotation("ProductVersion", "7.0.1") + .HasAnnotation("ProductVersion", "7.0.2") .HasAnnotation("Relational:MaxIdentifierLength", 64); modelBuilder.Entity("LINGYUN.Abp.Saas.Editions.Edition", b => @@ -226,6 +226,63 @@ namespace LY.MicroService.BackendAdmin.EntityFrameworkCore.Migrations b.ToTable("AbpTextTemplates", (string)null); }); + modelBuilder.Entity("LINGYUN.Abp.TextTemplating.TextTemplateDefinition", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasMaxLength(40) + .HasColumnType("varchar(40)") + .HasColumnName("ConcurrencyStamp"); + + b.Property("DefaultCultureName") + .HasMaxLength(30) + .HasColumnType("varchar(30)") + .HasColumnName("DefaultCultureName"); + + b.Property("DisplayName") + .IsRequired() + .HasMaxLength(512) + .HasColumnType("varchar(512)") + .HasColumnName("DisplayName"); + + b.Property("ExtraProperties") + .HasColumnType("longtext") + .HasColumnName("ExtraProperties"); + + b.Property("IsInlineLocalized") + .HasColumnType("tinyint(1)"); + + b.Property("IsLayout") + .HasColumnType("tinyint(1)"); + + b.Property("IsStatic") + .HasColumnType("tinyint(1)"); + + b.Property("Layout") + .HasMaxLength(60) + .HasColumnType("varchar(60)") + .HasColumnName("Layout"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)") + .HasColumnName("Name"); + + b.Property("RenderEngine") + .HasMaxLength(30) + .HasColumnType("varchar(30)") + .HasColumnName("RenderEngine"); + + b.HasKey("Id"); + + b.ToTable("AbpTextTemplateDefinitions", (string)null); + }); + modelBuilder.Entity("Volo.Abp.FeatureManagement.FeatureDefinitionRecord", b => { b.Property("Id") diff --git a/aspnet-core/migrations/LY.MicroService.IdentityServer.EntityFrameworkCore/LY.MicroService.IdentityServer.EntityFrameworkCore.csproj b/aspnet-core/migrations/LY.MicroService.IdentityServer.EntityFrameworkCore/LY.MicroService.IdentityServer.EntityFrameworkCore.csproj index 594b68ca7..dfcdbaee4 100644 --- a/aspnet-core/migrations/LY.MicroService.IdentityServer.EntityFrameworkCore/LY.MicroService.IdentityServer.EntityFrameworkCore.csproj +++ b/aspnet-core/migrations/LY.MicroService.IdentityServer.EntityFrameworkCore/LY.MicroService.IdentityServer.EntityFrameworkCore.csproj @@ -9,7 +9,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/aspnet-core/migrations/LY.MicroService.LocalizationManagement.EntityFrameworkCore/FodyWeavers.xsd b/aspnet-core/migrations/LY.MicroService.LocalizationManagement.EntityFrameworkCore/FodyWeavers.xsd new file mode 100644 index 000000000..11da52550 --- /dev/null +++ b/aspnet-core/migrations/LY.MicroService.LocalizationManagement.EntityFrameworkCore/FodyWeavers.xsd @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed. + + + + + A comma-separated list of error codes that can be safely ignored in assembly verification. + + + + + 'false' to turn off automatic generation of the XML Schema file. + + + + + \ No newline at end of file diff --git a/aspnet-core/migrations/LY.MicroService.LocalizationManagement.EntityFrameworkCore/LY.MicroService.LocalizationManagement.EntityFrameworkCore.csproj b/aspnet-core/migrations/LY.MicroService.LocalizationManagement.EntityFrameworkCore/LY.MicroService.LocalizationManagement.EntityFrameworkCore.csproj index c7481de61..970df46b1 100644 --- a/aspnet-core/migrations/LY.MicroService.LocalizationManagement.EntityFrameworkCore/LY.MicroService.LocalizationManagement.EntityFrameworkCore.csproj +++ b/aspnet-core/migrations/LY.MicroService.LocalizationManagement.EntityFrameworkCore/LY.MicroService.LocalizationManagement.EntityFrameworkCore.csproj @@ -1,12 +1,15 @@  + + + net7.0 LY.MicroService.LocalizationManagement.EntityFrameworkCore - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/aspnet-core/migrations/LY.MicroService.Platform.EntityFrameworkCore/FodyWeavers.xsd b/aspnet-core/migrations/LY.MicroService.Platform.EntityFrameworkCore/FodyWeavers.xsd new file mode 100644 index 000000000..11da52550 --- /dev/null +++ b/aspnet-core/migrations/LY.MicroService.Platform.EntityFrameworkCore/FodyWeavers.xsd @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed. + + + + + A comma-separated list of error codes that can be safely ignored in assembly verification. + + + + + 'false' to turn off automatic generation of the XML Schema file. + + + + + \ No newline at end of file diff --git a/aspnet-core/migrations/LY.MicroService.Platform.EntityFrameworkCore/LY.MicroService.Platform.EntityFrameworkCore.csproj b/aspnet-core/migrations/LY.MicroService.Platform.EntityFrameworkCore/LY.MicroService.Platform.EntityFrameworkCore.csproj index 3695fbed9..5c47cb3e5 100644 --- a/aspnet-core/migrations/LY.MicroService.Platform.EntityFrameworkCore/LY.MicroService.Platform.EntityFrameworkCore.csproj +++ b/aspnet-core/migrations/LY.MicroService.Platform.EntityFrameworkCore/LY.MicroService.Platform.EntityFrameworkCore.csproj @@ -1,12 +1,15 @@  + + + net7.0 LY.MicroService.Platform.EntityFrameworkCore - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/aspnet-core/migrations/LY.MicroService.RealtimeMessage.EntityFrameworkCore/FodyWeavers.xsd b/aspnet-core/migrations/LY.MicroService.RealtimeMessage.EntityFrameworkCore/FodyWeavers.xsd new file mode 100644 index 000000000..11da52550 --- /dev/null +++ b/aspnet-core/migrations/LY.MicroService.RealtimeMessage.EntityFrameworkCore/FodyWeavers.xsd @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed. + + + + + A comma-separated list of error codes that can be safely ignored in assembly verification. + + + + + 'false' to turn off automatic generation of the XML Schema file. + + + + + \ No newline at end of file diff --git a/aspnet-core/migrations/LY.MicroService.RealtimeMessage.EntityFrameworkCore/LY.MicroService.RealtimeMessage.EntityFrameworkCore.csproj b/aspnet-core/migrations/LY.MicroService.RealtimeMessage.EntityFrameworkCore/LY.MicroService.RealtimeMessage.EntityFrameworkCore.csproj index 8455c65ad..c5beceb67 100644 --- a/aspnet-core/migrations/LY.MicroService.RealtimeMessage.EntityFrameworkCore/LY.MicroService.RealtimeMessage.EntityFrameworkCore.csproj +++ b/aspnet-core/migrations/LY.MicroService.RealtimeMessage.EntityFrameworkCore/LY.MicroService.RealtimeMessage.EntityFrameworkCore.csproj @@ -1,12 +1,15 @@ + + + net7.0 LY.MicroService.RealtimeMessage.EntityFrameworkCore - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/aspnet-core/migrations/LY.MicroService.TaskManagement.EntityFrameworkCore/LY.MicroService.TaskManagement.EntityFrameworkCore.csproj b/aspnet-core/migrations/LY.MicroService.TaskManagement.EntityFrameworkCore/LY.MicroService.TaskManagement.EntityFrameworkCore.csproj index 3d34b4866..71384d16b 100644 --- a/aspnet-core/migrations/LY.MicroService.TaskManagement.EntityFrameworkCore/LY.MicroService.TaskManagement.EntityFrameworkCore.csproj +++ b/aspnet-core/migrations/LY.MicroService.TaskManagement.EntityFrameworkCore/LY.MicroService.TaskManagement.EntityFrameworkCore.csproj @@ -9,7 +9,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/aspnet-core/migrations/LY.MicroService.WebhooksManagement.EntityFrameworkCore/LY.MicroService.WebhooksManagement.EntityFrameworkCore.csproj b/aspnet-core/migrations/LY.MicroService.WebhooksManagement.EntityFrameworkCore/LY.MicroService.WebhooksManagement.EntityFrameworkCore.csproj index e5a113dd0..46aad161f 100644 --- a/aspnet-core/migrations/LY.MicroService.WebhooksManagement.EntityFrameworkCore/LY.MicroService.WebhooksManagement.EntityFrameworkCore.csproj +++ b/aspnet-core/migrations/LY.MicroService.WebhooksManagement.EntityFrameworkCore/LY.MicroService.WebhooksManagement.EntityFrameworkCore.csproj @@ -9,7 +9,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/AuditLogInfoToAuditLogConverter.cs b/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/AuditLogInfoToAuditLogConverter.cs index 0a571c8c5..ed4385d38 100644 --- a/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/AuditLogInfoToAuditLogConverter.cs +++ b/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/AuditLogInfoToAuditLogConverter.cs @@ -99,7 +99,9 @@ namespace LINGYUN.Abp.AuditLogging auditLogInfo.Url, auditLogInfo.HttpStatusCode, auditLogInfo.ImpersonatorUserId, + auditLogInfo.ImpersonatorUserName, auditLogInfo.ImpersonatorTenantId, + auditLogInfo.ImpersonatorTenantName, extraProperties, entityChanges, actions, diff --git a/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/ElasticsearchAuditLogManager.cs b/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/ElasticsearchAuditLogManager.cs index 764636c76..3e81fc5af 100644 --- a/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/ElasticsearchAuditLogManager.cs +++ b/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/ElasticsearchAuditLogManager.cs @@ -184,6 +184,8 @@ namespace LINGYUN.Abp.AuditLogging.Elasticsearch cancellationToken); } + // 避免循环记录 + [DisableAuditing] public async virtual Task SaveAsync( AuditLogInfo auditInfo, CancellationToken cancellationToken = default(CancellationToken)) diff --git a/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging/LINGYUN/Abp/AuditLogging/AuditLog.cs b/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging/LINGYUN/Abp/AuditLogging/AuditLog.cs index cc6d36226..5f9d2d266 100644 --- a/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging/LINGYUN/Abp/AuditLogging/AuditLog.cs +++ b/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging/LINGYUN/Abp/AuditLogging/AuditLog.cs @@ -22,8 +22,12 @@ namespace LINGYUN.Abp.AuditLogging public Guid? ImpersonatorUserId { get; set; } + public string ImpersonatorUserName { get; set; } + public Guid? ImpersonatorTenantId { get; set; } + public string ImpersonatorTenantName { get; set; } + public DateTime ExecutionTime { get; set; } public int ExecutionDuration { get; set; } @@ -79,7 +83,9 @@ namespace LINGYUN.Abp.AuditLogging string url, int? httpStatusCode, Guid? impersonatorUserId, + string impersonatorUserName, Guid? impersonatorTenantId, + string impersonatorTenantName, ExtraPropertyDictionary extraPropertyDictionary, List entityChanges, List actions, @@ -103,7 +109,9 @@ namespace LINGYUN.Abp.AuditLogging Url = url; HttpStatusCode = httpStatusCode; ImpersonatorUserId = impersonatorUserId; + ImpersonatorUserName = impersonatorUserName; ImpersonatorTenantId = impersonatorTenantId; + ImpersonatorTenantName = impersonatorTenantName; ExtraProperties = extraPropertyDictionary; EntityChanges = entityChanges; diff --git a/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging/LINGYUN/Abp/AuditLogging/AuditingStore.cs b/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging/LINGYUN/Abp/AuditLogging/AuditingStore.cs index fc12263f9..a4e85cddc 100644 --- a/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging/LINGYUN/Abp/AuditLogging/AuditingStore.cs +++ b/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging/LINGYUN/Abp/AuditLogging/AuditingStore.cs @@ -15,6 +15,8 @@ namespace LINGYUN.Abp.AuditLogging _manager = manager; } + // 避免循环记录 + [DisableAuditing] public async virtual Task SaveAsync(AuditLogInfo auditInfo) { await _manager.SaveAsync(auditInfo); diff --git a/aspnet-core/modules/authorization/LINGYUN.Abp.Identity.OrganizaztionUnits/LINGYUN/Abp/Identity/OrganizaztionUnits/OrganizationUnitClaimsPrincipalContributor.cs b/aspnet-core/modules/authorization/LINGYUN.Abp.Identity.OrganizaztionUnits/LINGYUN/Abp/Identity/OrganizaztionUnits/OrganizationUnitClaimsPrincipalContributor.cs index 2418ecd6e..adffe7b74 100644 --- a/aspnet-core/modules/authorization/LINGYUN.Abp.Identity.OrganizaztionUnits/LINGYUN/Abp/Identity/OrganizaztionUnits/OrganizationUnitClaimsPrincipalContributor.cs +++ b/aspnet-core/modules/authorization/LINGYUN.Abp.Identity.OrganizaztionUnits/LINGYUN/Abp/Identity/OrganizaztionUnits/OrganizationUnitClaimsPrincipalContributor.cs @@ -10,7 +10,7 @@ namespace LINGYUN.Abp.Identity.OrganizationUnits; public class OrganizationUnitClaimsPrincipalContributor : IAbpClaimsPrincipalContributor, ITransientDependency { - // https://github.com/dotnet/aspnetcore/blob/v5.0.0/src/Identity/Extensions.Core/src/UserClaimsPrincipalFactory.cs#L79 + // https://github.com/dotnet/aspnetcore/blob/main/src/Identity/Extensions.Core/src/UserClaimsPrincipalFactory.cs#L74 private static string IdentityAuthenticationType => "Identity.Application"; private readonly IIdentityUserRepository _identityUserRepository; diff --git a/aspnet-core/modules/cli/LINGYUN.Abp.Cli/LINGYUN.Abp.Cli.csproj b/aspnet-core/modules/cli/LINGYUN.Abp.Cli/LINGYUN.Abp.Cli.csproj index 52a582fa5..b8b091587 100644 --- a/aspnet-core/modules/cli/LINGYUN.Abp.Cli/LINGYUN.Abp.Cli.csproj +++ b/aspnet-core/modules/cli/LINGYUN.Abp.Cli/LINGYUN.Abp.Cli.csproj @@ -5,7 +5,7 @@ Exe net7.0 - 7.0.1 + 7.0.2 colin Use LINGYUN.MicroService.Templates command line true diff --git a/aspnet-core/modules/common/LINGYUN.Abp.ExceptionHandling/LINGYUN/Abp/ExceptionHandling/AbpExceptionSubscriberBase.cs b/aspnet-core/modules/common/LINGYUN.Abp.ExceptionHandling/LINGYUN/Abp/ExceptionHandling/AbpExceptionSubscriberBase.cs index 73d3e3a4b..7f6475f1d 100644 --- a/aspnet-core/modules/common/LINGYUN.Abp.ExceptionHandling/LINGYUN/Abp/ExceptionHandling/AbpExceptionSubscriberBase.cs +++ b/aspnet-core/modules/common/LINGYUN.Abp.ExceptionHandling/LINGYUN/Abp/ExceptionHandling/AbpExceptionSubscriberBase.cs @@ -4,6 +4,7 @@ using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.Options; using System; using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; using Volo.Abp.ExceptionHandling; namespace LINGYUN.Abp.ExceptionHandling @@ -13,30 +14,9 @@ namespace LINGYUN.Abp.ExceptionHandling protected IServiceScopeFactory ServiceScopeFactory { get; } protected AbpExceptionHandlingOptions Options { get; } - public IServiceProvider ServiceProvider { get; set; } - protected readonly object ServiceProviderLock = new object(); + public IAbpLazyServiceProvider ServiceProvider { get; set; } - protected TService LazyGetRequiredService(ref TService reference) - => LazyGetRequiredService(typeof(TService), ref reference); - - protected TRef LazyGetRequiredService(Type serviceType, ref TRef reference) - { - if (reference == null) - { - lock (ServiceProviderLock) - { - if (reference == null) - { - reference = (TRef)ServiceProvider.GetRequiredService(serviceType); - } - } - } - - return reference; - } - - protected ILoggerFactory LoggerFactory => LazyGetRequiredService(ref _loggerFactory); - private ILoggerFactory _loggerFactory; + protected ILoggerFactory LoggerFactory => ServiceProvider.LazyGetService(); protected ILogger Logger => _lazyLogger.Value; private Lazy _lazyLogger => new Lazy(() => LoggerFactory?.CreateLogger(GetType().FullName) ?? NullLogger.Instance, true); diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Features.LimitValidation/LINGYUN/Abp/Features/LimitValidation/AbpFeaturesLimitValidationOptions.cs b/aspnet-core/modules/common/LINGYUN.Abp.Features.LimitValidation/LINGYUN/Abp/Features/LimitValidation/AbpFeaturesLimitValidationOptions.cs index 153841767..c851fd954 100644 --- a/aspnet-core/modules/common/LINGYUN.Abp.Features.LimitValidation/LINGYUN/Abp/Features/LimitValidation/AbpFeaturesLimitValidationOptions.cs +++ b/aspnet-core/modules/common/LINGYUN.Abp.Features.LimitValidation/LINGYUN/Abp/Features/LimitValidation/AbpFeaturesLimitValidationOptions.cs @@ -1,6 +1,7 @@ using JetBrains.Annotations; using System; using System.Collections.Generic; +using System.Globalization; using Volo.Abp; namespace LINGYUN.Abp.Features.LimitValidation @@ -36,12 +37,55 @@ namespace LINGYUN.Abp.Features.LimitValidation internal void MapDefaultEffectPolicys() { - MapEffectPolicy(LimitPolicy.Minute, (time) => { return (long)(DateTimeOffset.UtcNow.AddMinutes(time) - DateTimeOffset.UtcNow).TotalSeconds; }); - MapEffectPolicy(LimitPolicy.Hours, (time) => { return (long)(DateTimeOffset.UtcNow.AddHours(time) - DateTimeOffset.UtcNow).TotalSeconds; }); - MapEffectPolicy(LimitPolicy.Days, (time) => { return (long)(DateTimeOffset.UtcNow.AddDays(time) - DateTimeOffset.UtcNow).TotalSeconds; }); - MapEffectPolicy(LimitPolicy.Weeks, (time) => { return (long)(DateTimeOffset.UtcNow.AddDays(time * 7) - DateTimeOffset.UtcNow).TotalSeconds; }); - MapEffectPolicy(LimitPolicy.Month, (time) => { return (long)(DateTimeOffset.UtcNow.AddMonths(time) - DateTimeOffset.UtcNow).TotalSeconds; }); - MapEffectPolicy(LimitPolicy.Years, (time) => { return (long)(DateTimeOffset.UtcNow.AddYears(time) - DateTimeOffset.UtcNow).TotalSeconds; }); + MapEffectPolicy(LimitPolicy.Minute, (time) => + { + var utcNow = DateTime.UtcNow; + return (long)(utcNow.AddMinutes(time) - utcNow).TotalSeconds; + }); + + MapEffectPolicy(LimitPolicy.Hours, (time) => + { + var utcNow = DateTime.UtcNow; + return (long)(utcNow.AddHours(time) - utcNow).TotalSeconds; + }); + + MapEffectPolicy(LimitPolicy.Days, (time) => + { + // 按天计算应取当天 + return (long)(DateTime.UtcNow.Date.AddDays(time) - DateTime.UtcNow).TotalSeconds; + }); + + MapEffectPolicy(LimitPolicy.Weeks,(time) => + { + // 按周计算应取当周 + var utcNow = DateTime.UtcNow.Date; + var dayOfWeek = (int)utcNow.DayOfWeek - 1; + if (utcNow.DayOfWeek == DayOfWeek.Sunday) + { + dayOfWeek = 6; + } + var utcOnceDayOfWeek = utcNow.AddDays(-dayOfWeek); + + return (long)(utcOnceDayOfWeek.AddDays(time) - DateTime.UtcNow).TotalSeconds; + }); + + MapEffectPolicy(LimitPolicy.Month, (time) => + { + // 按月计算应取当月 + var utcNow = DateTime.UtcNow; + var utcOnceDayOfMonth = new DateTime(utcNow.Year, utcNow.Month, 1, 1, 0, 0, 0); + + return (long)(utcOnceDayOfMonth.AddMonths(time) - utcNow).TotalSeconds; + }); + + MapEffectPolicy(LimitPolicy.Years, (time) => + { + // 按年计算应取当年 + var utcNow = DateTime.UtcNow; + var utcOnceDayOfYear = new DateTime(utcNow.Year, 1, 1, 1, 0, 0, 0); + + return (long)(utcOnceDayOfYear.AddYears(time) - utcNow).TotalSeconds; + }); } } } diff --git a/aspnet-core/modules/common/LINGYUN.Abp.IM.SignalR/LINGYUN/Abp/IM/SignalR/Hubs/MessagesHub.cs b/aspnet-core/modules/common/LINGYUN.Abp.IM.SignalR/LINGYUN/Abp/IM/SignalR/Hubs/MessagesHub.cs index 638a53f76..b6efd868e 100644 --- a/aspnet-core/modules/common/LINGYUN.Abp.IM.SignalR/LINGYUN/Abp/IM/SignalR/Hubs/MessagesHub.cs +++ b/aspnet-core/modules/common/LINGYUN.Abp.IM.SignalR/LINGYUN/Abp/IM/SignalR/Hubs/MessagesHub.cs @@ -49,7 +49,12 @@ namespace LINGYUN.Abp.IM.SignalR.Hubs { await SendUserOnlineStateAsync(); } - catch(Exception ex) + catch (OperationCanceledException) + { + // Ignore + return; + } + catch (Exception ex) { Logger.LogWarning("An error occurred in the OnConnected method:{message}", ex.Message); } @@ -63,6 +68,11 @@ namespace LINGYUN.Abp.IM.SignalR.Hubs { await SendUserOnlineStateAsync(false); } + catch (OperationCanceledException) + { + // Ignore + return; + } catch (Exception ex) { Logger.LogWarning("An error occurred in the OnDisconnected method:{message}", ex.Message); @@ -183,6 +193,11 @@ namespace LINGYUN.Abp.IM.SignalR.Hubs { await Processor?.ReadAsync(chatMessage); } + catch (OperationCanceledException) + { + // Ignore + return; + } catch (Exception ex) { Logger.LogWarning("An error occurred in the Read method:{message}", ex.Message); diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Notifications.SignalR/LINGYUN/Abp/Notifications/SignalR/Hubs/NotificationsHub.cs b/aspnet-core/modules/common/LINGYUN.Abp.Notifications.SignalR/LINGYUN/Abp/Notifications/SignalR/Hubs/NotificationsHub.cs index 8d21833cd..0afe240a4 100644 --- a/aspnet-core/modules/common/LINGYUN.Abp.Notifications.SignalR/LINGYUN/Abp/Notifications/SignalR/Hubs/NotificationsHub.cs +++ b/aspnet-core/modules/common/LINGYUN.Abp.Notifications.SignalR/LINGYUN/Abp/Notifications/SignalR/Hubs/NotificationsHub.cs @@ -22,11 +22,11 @@ namespace LINGYUN.Abp.Notifications.SignalR.Hubs if (CurrentTenant.IsAvailable) { // 以租户为分组,将用户加入租户通讯组 - await Groups.AddToGroupAsync(Context.ConnectionId, CurrentTenant.GetId().ToString(), Context.ConnectionAborted); + await Groups.AddToGroupAsync(Context.ConnectionId, CurrentTenant.GetId().ToString()); } else { - await Groups.AddToGroupAsync(Context.ConnectionId, "Global", Context.ConnectionAborted); + await Groups.AddToGroupAsync(Context.ConnectionId, "Global"); } } @@ -38,11 +38,11 @@ namespace LINGYUN.Abp.Notifications.SignalR.Hubs if (CurrentTenant.IsAvailable) { // 以租户为分组,将移除租户通讯组 - await Groups.RemoveFromGroupAsync(Context.ConnectionId, CurrentTenant.GetId().ToString(), Context.ConnectionAborted); + await Groups.RemoveFromGroupAsync(Context.ConnectionId, CurrentTenant.GetId().ToString()); } else { - await Groups.RemoveFromGroupAsync(Context.ConnectionId, "Global", Context.ConnectionAborted); + await Groups.RemoveFromGroupAsync(Context.ConnectionId, "Global"); } } @@ -76,8 +76,7 @@ namespace LINGYUN.Abp.Notifications.SignalR.Hubs CurrentTenant.Id, CurrentUser.GetId(), long.Parse(id), - readState, - Context.ConnectionAborted); + readState); } } } diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/Localization/Resources/en.json b/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/Localization/Resources/en.json index d03b701a8..d7fc1608c 100644 --- a/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/Localization/Resources/en.json +++ b/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/Localization/Resources/en.json @@ -28,6 +28,10 @@ "Notifications:SystemNotice": "System", "Notifications:SystemNoticeDesc": "System global notification push", "MarkSelectedAsRead": "Mark selected as read", + "NotificationType:Application": "Platform", + "NotificationType:System": "System", + "NotificationType:User": "User", + "NotificationType:ServiceCallback": "Service Callback", "MarkAs": "Mark as", "Read": "Read", "UnRead": "Un Read" diff --git a/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/Localization/Resources/zh-Hans.json b/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/Localization/Resources/zh-Hans.json index 373e2ac64..04e92911b 100644 --- a/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/Localization/Resources/zh-Hans.json +++ b/aspnet-core/modules/common/LINGYUN.Abp.Notifications/LINGYUN/Abp/Notifications/Localization/Resources/zh-Hans.json @@ -28,6 +28,10 @@ "Notifications:SystemNotice": "系统通知", "Notifications:SystemNoticeDesc": "系统全局消息推送", "MarkSelectedAsRead": "标记选中已读", + "NotificationType:Application": "平台", + "NotificationType:System": "系统", + "NotificationType:User": "用户", + "NotificationType:ServiceCallback": "服务回调", "MarkAs": "标记为", "Read": "已读", "UnRead": "未读" diff --git a/aspnet-core/modules/elsa/LINGYUN.Abp.Elsa/LINGYUN/Abp/Elsa/Scripting/JavaScript/ConfigureJavaScriptEngine.cs b/aspnet-core/modules/elsa/LINGYUN.Abp.Elsa/LINGYUN/Abp/Elsa/Scripting/JavaScript/ConfigureJavaScriptEngine.cs index dbc37e0f9..692f6f556 100644 --- a/aspnet-core/modules/elsa/LINGYUN.Abp.Elsa/LINGYUN/Abp/Elsa/Scripting/JavaScript/ConfigureJavaScriptEngine.cs +++ b/aspnet-core/modules/elsa/LINGYUN.Abp.Elsa/LINGYUN/Abp/Elsa/Scripting/JavaScript/ConfigureJavaScriptEngine.cs @@ -8,6 +8,7 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using Volo.Abp.Authorization.Permissions; +using Volo.Abp.Features; using Volo.Abp.Guids; using Volo.Abp.Localization; using Volo.Abp.MultiTenancy; @@ -23,6 +24,7 @@ public class ConfigureJavaScriptEngine : INotificationHandler localizationOptions, IStringLocalizerFactory localizerFactory, IGuidGenerator guidGenerator, + IFeatureChecker featureChecker, ISettingProvider settingProvider, IPermissionChecker permissionChecker) { @@ -40,6 +43,7 @@ public class ConfigureJavaScriptEngine : INotificationHandler + { + ["get"] = (Func)((name) => _featureChecker.GetOrNullAsync(name).GetAwaiter().GetResult()), + ["isEnabled"] = (Func)((name) => _featureChecker.IsEnabledAsync(name).GetAwaiter().GetResult()), + }; + abpFunctions["feature"] = featureModel; + var authModel = new Dictionary { ["isGranted"] = (Func)((name) => _permissionChecker.IsGrantedAsync(name).GetAwaiter().GetResult()), diff --git a/aspnet-core/modules/localization/LINGYUN.Abp.Localization.Persistence/LINGYUN/Abp/Localization/Persistence/StaticLocalizationSaverHostService.cs b/aspnet-core/modules/localization/LINGYUN.Abp.Localization.Persistence/LINGYUN/Abp/Localization/Persistence/StaticLocalizationSaverHostService.cs index 32c74535d..62114d51a 100644 --- a/aspnet-core/modules/localization/LINGYUN.Abp.Localization.Persistence/LINGYUN/Abp/Localization/Persistence/StaticLocalizationSaverHostService.cs +++ b/aspnet-core/modules/localization/LINGYUN.Abp.Localization.Persistence/LINGYUN/Abp/Localization/Persistence/StaticLocalizationSaverHostService.cs @@ -1,5 +1,6 @@ using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Options; +using System; using System.Threading; using System.Threading.Tasks; @@ -22,7 +23,15 @@ public class StaticLocalizationSaverHostService : BackgroundService { if (_options.SaveStaticLocalizationsToPersistence) { - await _staticLocalizationSaver.SaveAsync(); + try + { + await _staticLocalizationSaver.SaveAsync(); + } + catch (OperationCanceledException) + { + // Ignore + return; + } } } } diff --git a/aspnet-core/modules/mvc/LINGYUN.Abp.AspNetCore.Mvc.Wrapper/LINGYUN/Abp/AspNetCore/Mvc/Wrapper/AbpAspNetCoreMvcWrapperModule.cs b/aspnet-core/modules/mvc/LINGYUN.Abp.AspNetCore.Mvc.Wrapper/LINGYUN/Abp/AspNetCore/Mvc/Wrapper/AbpAspNetCoreMvcWrapperModule.cs index e8946adf1..ec6d10e4d 100644 --- a/aspnet-core/modules/mvc/LINGYUN.Abp.AspNetCore.Mvc.Wrapper/LINGYUN/Abp/AspNetCore/Mvc/Wrapper/AbpAspNetCoreMvcWrapperModule.cs +++ b/aspnet-core/modules/mvc/LINGYUN.Abp.AspNetCore.Mvc.Wrapper/LINGYUN/Abp/AspNetCore/Mvc/Wrapper/AbpAspNetCoreMvcWrapperModule.cs @@ -2,6 +2,7 @@ using LINGYUN.Abp.AspNetCore.Mvc.Wrapper.Localization; using LINGYUN.Abp.Wrapper; using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.ViewEngines; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Localization; using Volo.Abp.AspNetCore.Mvc; @@ -48,10 +49,29 @@ namespace LINGYUN.Abp.AspNetCore.Mvc.Wrapper options.IgnoreReturnTypes.Add(); // api/abp/application-configuration options.IgnoreReturnTypes.Add(); - // + // api/abp/application-localization + options.IgnoreReturnTypes.Add(); + // 文件流 options.IgnoreReturnTypes.Add(); + options.IgnoreReturnTypes.Add(); + + //options.IgnoreReturnTypes.Add(); + //options.IgnoreReturnTypes.Add(); + //options.IgnoreReturnTypes.Add(); + + //options.IgnoreReturnTypes.Add(); + //options.IgnoreReturnTypes.Add(); + //options.IgnoreReturnTypes.Add(); + + //options.IgnoreReturnTypes.Add(); + //options.IgnoreReturnTypes.Add(); + //options.IgnoreReturnTypes.Add(); + // Abp/ServiceProxyScript options.IgnoreControllers.Add(); + options.IgnoreControllers.Add(); + options.IgnoreControllers.Add(); + options.IgnoreControllers.Add(); // 官方模块不包装结果 options.IgnoreNamespaces.Add("Volo.Abp"); diff --git a/aspnet-core/modules/mvc/LINGYUN.Abp.AspNetCore.Mvc.Wrapper/README.md b/aspnet-core/modules/mvc/LINGYUN.Abp.AspNetCore.Mvc.Wrapper/README.md index 8f4ed889c..a85f1af24 100644 --- a/aspnet-core/modules/mvc/LINGYUN.Abp.AspNetCore.Mvc.Wrapper/README.md +++ b/aspnet-core/modules/mvc/LINGYUN.Abp.AspNetCore.Mvc.Wrapper/README.md @@ -1,6 +1,6 @@ # LINGYUN.Abp.AspNetCore.Mvc.Wrapper -返回值包装器 +包装器 MVC 实现模块 ## 配置使用 @@ -10,7 +10,7 @@ public class YouProjectModule : AbpModule { public override void ConfigureServices(ServiceConfigurationContext context) { - Configure(options => + Configure(options => { // 启用包装器 options.IsEnabled = true; @@ -20,18 +20,5 @@ public class YouProjectModule : AbpModule ``` ## 配置项说明 -* AbpAspNetCoreMvcWrapperOptions.IsEnabled 是否包装返回结果,默认: false -* AbpAspNetCoreMvcWrapperOptions.CodeWithFound 响应成功代码,默认: 0 -* AbpAspNetCoreMvcWrapperOptions.HttpStatusCode 包装后的Http响应代码, 默认: 200 -* AbpAspNetCoreMvcWrapperOptions.CodeWithEmptyResult 当返回空对象时返回错误代码,默认: 404 -* AbpAspNetCoreMvcWrapperOptions.MessageWithEmptyResult 当返回空对象时返回错误消息, 默认: 本地化之后的 NotFound - -* AbpAspNetCoreMvcWrapperOptions.IgnorePrefixUrls 指定哪些Url开头的地址不需要处理 -* AbpAspNetCoreMvcWrapperOptions.IgnoreNamespaces 指定哪些命名空间开头不需要处理 -* AbpAspNetCoreMvcWrapperOptions.IgnoreControllers 指定哪些控制器不需要处理 -* AbpAspNetCoreMvcWrapperOptions.IgnoreReturnTypes 指定哪些返回结果类型不需要处理 -* AbpAspNetCoreMvcWrapperOptions.IgnoreExceptions 指定哪些异常类型不需要处理 - - ## 其他 diff --git a/aspnet-core/modules/notifications/LINGYUN.Abp.Notifications.Domain/LINGYUN/Abp/Notifications/AbpNotificationsDomainModule.cs b/aspnet-core/modules/notifications/LINGYUN.Abp.Notifications.Domain/LINGYUN/Abp/Notifications/AbpNotificationsDomainModule.cs index b8deb5543..f49b51eaf 100644 --- a/aspnet-core/modules/notifications/LINGYUN.Abp.Notifications.Domain/LINGYUN/Abp/Notifications/AbpNotificationsDomainModule.cs +++ b/aspnet-core/modules/notifications/LINGYUN.Abp.Notifications.Domain/LINGYUN/Abp/Notifications/AbpNotificationsDomainModule.cs @@ -1,16 +1,10 @@ using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Hosting; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; -using Polly; -using System; using System.Threading; using System.Threading.Tasks; using Volo.Abp; using Volo.Abp.AutoMapper; using Volo.Abp.Caching; using Volo.Abp.Data; -using Volo.Abp.DependencyInjection; using Volo.Abp.Modularity; using Volo.Abp.Threading; @@ -44,8 +38,9 @@ public class AbpNotificationsDomainModule : AbpModule public override Task OnApplicationInitializationAsync(ApplicationInitializationContext context) { - InitializeDynamicNotifications(context); - return Task.CompletedTask; + return context.ServiceProvider + .GetRequiredService() + .InitializeDynamicNotifications(_cancellationTokenSource.Token); } public override Task OnApplicationShutdownAsync(ApplicationShutdownContext context) @@ -53,111 +48,4 @@ public class AbpNotificationsDomainModule : AbpModule _cancellationTokenSource.Cancel(); return Task.CompletedTask; } - - private void InitializeDynamicNotifications(ApplicationInitializationContext context) - { - var options = context - .ServiceProvider - .GetRequiredService>() - .Value; - - if (!options.SaveStaticNotificationsToDatabase && !options.IsDynamicNotificationsStoreEnabled) - { - return; - } - - var rootServiceProvider = context.ServiceProvider.GetRequiredService(); - - Task.Run(async () => - { - using var scope = rootServiceProvider.CreateScope(); - var applicationLifetime = scope.ServiceProvider.GetService(); - var cancellationTokenProvider = scope.ServiceProvider.GetRequiredService(); - var cancellationToken = applicationLifetime?.ApplicationStopping ?? _cancellationTokenSource.Token; - - try - { - using (cancellationTokenProvider.Use(cancellationToken)) - { - if (cancellationTokenProvider.Token.IsCancellationRequested) - { - return; - } - - await SaveStaticNotificationsToDatabaseAsync(options, scope, cancellationTokenProvider); - - if (cancellationTokenProvider.Token.IsCancellationRequested) - { - return; - } - - await PreCacheDynamicNotificationsAsync(options, scope); - } - } - // ReSharper disable once EmptyGeneralCatchClause (No need to log since it is logged above) - catch { } - }); - } - - private async static Task SaveStaticNotificationsToDatabaseAsync( - AbpNotificationsManagementOptions options, - IServiceScope scope, - ICancellationTokenProvider cancellationTokenProvider) - { - if (!options.SaveStaticNotificationsToDatabase) - { - return; - } - - await Policy - .Handle() - .WaitAndRetryAsync(8, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt) * 10)) - .ExecuteAsync(async _ => - { - try - { - // ReSharper disable once AccessToDisposedClosure - await scope - .ServiceProvider - .GetRequiredService() - .SaveAsync(); - } - catch (Exception ex) - { - // ReSharper disable once AccessToDisposedClosure - scope.ServiceProvider - .GetService>()? - .LogException(ex); - - throw; // Polly will catch it - } - }, cancellationTokenProvider.Token); - } - - private async static Task PreCacheDynamicNotificationsAsync(AbpNotificationsManagementOptions options, IServiceScope scope) - { - if (!options.IsDynamicNotificationsStoreEnabled) - { - return; - } - - try - { - // Pre-cache Notifications, so first request doesn't wait - await scope - .ServiceProvider - .GetRequiredService() - .GetGroupsAsync(); - } - catch (Exception ex) - { - // ReSharper disable once AccessToDisposedClosure - scope - .ServiceProvider - .GetService>()? - .LogException(ex); - - throw; // It will be cached in InitializeDynamicNotifications - } - } } diff --git a/aspnet-core/modules/notifications/LINGYUN.Abp.Notifications.Domain/LINGYUN/Abp/Notifications/DynamicNotificationDefinitionInMemoryCache.cs b/aspnet-core/modules/notifications/LINGYUN.Abp.Notifications.Domain/LINGYUN/Abp/Notifications/DynamicNotificationDefinitionInMemoryCache.cs index 404a6c3c2..7acc75579 100644 --- a/aspnet-core/modules/notifications/LINGYUN.Abp.Notifications.Domain/LINGYUN/Abp/Notifications/DynamicNotificationDefinitionInMemoryCache.cs +++ b/aspnet-core/modules/notifications/LINGYUN.Abp.Notifications.Domain/LINGYUN/Abp/Notifications/DynamicNotificationDefinitionInMemoryCache.cs @@ -32,7 +32,7 @@ public class DynamicNotificationDefinitionInMemoryCache : IDynamicNotificationDe NotificationDefinitions = new Dictionary(); } - public Task FillAsync( + public virtual Task FillAsync( List notificationGroupRecords, List notificationRecords) { @@ -69,17 +69,17 @@ public class DynamicNotificationDefinitionInMemoryCache : IDynamicNotificationDe return Task.CompletedTask; } - public NotificationDefinition GetNotificationOrNull(string name) + public virtual NotificationDefinition GetNotificationOrNull(string name) { return NotificationDefinitions.GetOrDefault(name); } - public IReadOnlyList GetNotifications() + public virtual IReadOnlyList GetNotifications() { return NotificationDefinitions.Values.ToList(); } - public IReadOnlyList GetGroups() + public virtual IReadOnlyList GetGroups() { return NotificationGroupDefinitions.Values.ToList(); } diff --git a/aspnet-core/modules/notifications/LINGYUN.Abp.Notifications.Domain/LINGYUN/Abp/Notifications/NotificationDefinitionInitializer.cs b/aspnet-core/modules/notifications/LINGYUN.Abp.Notifications.Domain/LINGYUN/Abp/Notifications/NotificationDefinitionInitializer.cs new file mode 100644 index 000000000..4859fffc5 --- /dev/null +++ b/aspnet-core/modules/notifications/LINGYUN.Abp.Notifications.Domain/LINGYUN/Abp/Notifications/NotificationDefinitionInitializer.cs @@ -0,0 +1,93 @@ +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; +using System; +using System.Threading; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Threading; +using Volo.Abp.Uow; + +namespace LINGYUN.Abp.Notifications; +public class NotificationDefinitionInitializer : ITransientDependency +{ + protected IRootServiceProvider RootServiceProvider { get; } + protected ICancellationTokenProvider CancellationTokenProvider { get; } + protected AbpNotificationsManagementOptions NotificationsManagementOptions { get; } + public NotificationDefinitionInitializer( + IRootServiceProvider rootServiceProvider, + ICancellationTokenProvider cancellationTokenProvider, + IOptions notificationsManagementOptions) + { + RootServiceProvider = rootServiceProvider; + CancellationTokenProvider = cancellationTokenProvider; + NotificationsManagementOptions = notificationsManagementOptions.Value; + } + + [UnitOfWork] + public async virtual Task InitializeDynamicNotifications(CancellationToken cancellationToken) + { + if (!NotificationsManagementOptions.SaveStaticNotificationsToDatabase && !NotificationsManagementOptions.IsDynamicNotificationsStoreEnabled) + { + return; + } + + using var scope = RootServiceProvider.CreateScope(); + var applicationLifetime = scope.ServiceProvider.GetService(); + var token = applicationLifetime?.ApplicationStopping ?? cancellationToken; + try + { + using (CancellationTokenProvider.Use(cancellationToken)) + { + if (CancellationTokenProvider.Token.IsCancellationRequested) + { + return; + } + + await SaveStaticNotificationsToDatabaseAsync(scope); + + if (CancellationTokenProvider.Token.IsCancellationRequested) + { + return; + } + + await PreCacheDynamicNotificationsAsync(scope); + } + } + catch (OperationCanceledException) + { + // ignore + } + catch(Exception ex) + { + scope.ServiceProvider + .GetService>()? + .LogException(ex); + } + } + + private async Task SaveStaticNotificationsToDatabaseAsync(IServiceScope serviceScope) + { + if (!NotificationsManagementOptions.SaveStaticNotificationsToDatabase) + { + return; + } + + var saver = serviceScope.ServiceProvider.GetRequiredService(); + + await saver.SaveAsync(); + } + + private async Task PreCacheDynamicNotificationsAsync(IServiceScope serviceScope) + { + if (!NotificationsManagementOptions.IsDynamicNotificationsStoreEnabled) + { + return; + } + + var store = serviceScope.ServiceProvider.GetRequiredService(); + + await store.GetGroupsAsync(); + } +} diff --git a/aspnet-core/modules/notifications/LINGYUN.Abp.Notifications.Domain/LINGYUN/Abp/Notifications/NotificationTypeConverter.cs b/aspnet-core/modules/notifications/LINGYUN.Abp.Notifications.Domain/LINGYUN/Abp/Notifications/NotificationTypeConverter.cs deleted file mode 100644 index d401bfc05..000000000 --- a/aspnet-core/modules/notifications/LINGYUN.Abp.Notifications.Domain/LINGYUN/Abp/Notifications/NotificationTypeConverter.cs +++ /dev/null @@ -1,39 +0,0 @@ -using AutoMapper; -using System; -using Volo.Abp; -using Volo.Abp.DependencyInjection; - -namespace LINGYUN.Abp.Notifications -{ - public class NotificationTypeConverter : ITypeConverter, ISingletonDependency - { - public NotificationInfo Convert(Notification source, NotificationInfo destination, ResolutionContext context) - { - destination = new NotificationInfo - { - Name = source.NotificationName, - Type = source.Type, - ContentType = source.ContentType, - Severity = source.Severity, - CreationTime = source.CreationTime, - TenantId = source.TenantId - }; - destination.SetId(source.NotificationId); - - var dataType = Type.GetType(source.NotificationTypeName); - Check.NotNull(dataType, source.NotificationTypeName); - var data = Activator.CreateInstance(dataType); - if (data != null && data is NotificationData notificationData) - { - notificationData.ExtraProperties = source.ExtraProperties; - destination.Data = NotificationDataConverter.Convert(notificationData); - } - else - { - destination.Data = new NotificationData(); - destination.Data.ExtraProperties = source.ExtraProperties; - } - return destination; - } - } -} diff --git a/aspnet-core/modules/platform/LINGYUN.Platform.Domain/LINGYUN/Platform/Packages/FileSystemPackageBlobNormalizer.cs b/aspnet-core/modules/platform/LINGYUN.Platform.Domain/LINGYUN/Platform/Packages/FileSystemPackageBlobNormalizer.cs index b2f0fef6c..2c6bce0cb 100644 --- a/aspnet-core/modules/platform/LINGYUN.Platform.Domain/LINGYUN/Platform/Packages/FileSystemPackageBlobNormalizer.cs +++ b/aspnet-core/modules/platform/LINGYUN.Platform.Domain/LINGYUN/Platform/Packages/FileSystemPackageBlobNormalizer.cs @@ -1,4 +1,5 @@ using System.IO; +using System.Web; using Volo.Abp.DependencyInjection; namespace LINGYUN.Platform.Packages; @@ -15,6 +16,6 @@ public class FileSystemPackageBlobNormalizer : IPackageBlobNormalizer, ISingleto var pk = package.Name; var pv = package.Version; - return Path.Combine(pk, "v" + pv, "blobs", blob.Name); + return Path.Combine(pk, "v" + pv, "blobs", HttpUtility.HtmlDecode(blob.Name)); } } diff --git a/aspnet-core/modules/platform/LINGYUN.Platform.Domain/LINGYUN/Platform/Packages/PackageBlobManager.cs b/aspnet-core/modules/platform/LINGYUN.Platform.Domain/LINGYUN/Platform/Packages/PackageBlobManager.cs index 8fe7a2c54..2fdb7c4d3 100644 --- a/aspnet-core/modules/platform/LINGYUN.Platform.Domain/LINGYUN/Platform/Packages/PackageBlobManager.cs +++ b/aspnet-core/modules/platform/LINGYUN.Platform.Domain/LINGYUN/Platform/Packages/PackageBlobManager.cs @@ -3,6 +3,7 @@ using System.IO; using System.Security.Cryptography; using System.Threading; using System.Threading.Tasks; +using System.Web; using Volo.Abp.BlobStoring; using Volo.Abp.DependencyInjection; using Volo.Abp.Domain.Services; @@ -56,7 +57,7 @@ public class PackageBlobManager : DomainService, IPackageBlobManager, ITransient stream.Seek(0, SeekOrigin.Begin); packageBlob.SHA256 = ComputeHash(stream); - packageBlob.SetUrl($"api/platform/packages/{packageBlob.PackageId}/blob/{packageBlob.Name}"); + packageBlob.SetUrl($"api/platform/packages/{packageBlob.PackageId}/blob/{HttpUtility.HtmlEncode(packageBlob.Name)}"); } protected async virtual Task DownloadFromBlobAsync( diff --git a/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Application.Contracts/LINGYUN/Abp/TextTemplating/ITextTemplateAppService.cs b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Application.Contracts/LINGYUN/Abp/TextTemplating/ITextTemplateAppService.cs deleted file mode 100644 index d2cd91891..000000000 --- a/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Application.Contracts/LINGYUN/Abp/TextTemplating/ITextTemplateAppService.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System.Threading.Tasks; -using Volo.Abp.Application.Dtos; -using Volo.Abp.Application.Services; - -namespace LINGYUN.Abp.TextTemplating; - -public interface ITextTemplateAppService : IApplicationService -{ - Task GetAsync(string name); - - Task GetContentAsync(TextTemplateContentGetInput input); - - Task RestoreToDefaultAsync(TextTemplateRestoreInput input); - - Task UpdateAsync(TextTemplateUpdateInput input); - - Task> GetListAsync(TextTemplateDefinitionGetListInput input); -} diff --git a/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Application.Contracts/LINGYUN/Abp/TextTemplating/ITextTemplateContentAppService.cs b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Application.Contracts/LINGYUN/Abp/TextTemplating/ITextTemplateContentAppService.cs new file mode 100644 index 000000000..59b316a01 --- /dev/null +++ b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Application.Contracts/LINGYUN/Abp/TextTemplating/ITextTemplateContentAppService.cs @@ -0,0 +1,13 @@ +using System.Threading.Tasks; +using Volo.Abp.Application.Services; + +namespace LINGYUN.Abp.TextTemplating; + +public interface ITextTemplateContentAppService : IApplicationService +{ + Task GetAsync(TextTemplateContentGetInput input); + + Task RestoreToDefaultAsync(string name, TextTemplateRestoreInput input); + + Task UpdateAsync(string name, TextTemplateContentUpdateDto input); +} diff --git a/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Application.Contracts/LINGYUN/Abp/TextTemplating/ITextTemplateDefinitionAppService.cs b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Application.Contracts/LINGYUN/Abp/TextTemplating/ITextTemplateDefinitionAppService.cs new file mode 100644 index 000000000..95f0aeb47 --- /dev/null +++ b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Application.Contracts/LINGYUN/Abp/TextTemplating/ITextTemplateDefinitionAppService.cs @@ -0,0 +1,18 @@ +using System.Threading.Tasks; +using Volo.Abp.Application.Dtos; +using Volo.Abp.Application.Services; + +namespace LINGYUN.Abp.TextTemplating; + +public interface ITextTemplateDefinitionAppService : IApplicationService +{ + Task GetByNameAsync(string name); + + Task CreateAsync(TextTemplateDefinitionCreateDto input); + + Task UpdateAsync(string name, TextTemplateDefinitionUpdateDto input); + + Task DeleteAsync(string name); + + Task> GetListAsync(TextTemplateDefinitionGetListInput input); +} diff --git a/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Application.Contracts/LINGYUN/Abp/TextTemplating/Permissions/AbpTextTemplatingPermissionDefinitionProvider.cs b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Application.Contracts/LINGYUN/Abp/TextTemplating/Permissions/AbpTextTemplatingPermissionDefinitionProvider.cs index 2318bba52..80aa38cde 100644 --- a/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Application.Contracts/LINGYUN/Abp/TextTemplating/Permissions/AbpTextTemplatingPermissionDefinitionProvider.cs +++ b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Application.Contracts/LINGYUN/Abp/TextTemplating/Permissions/AbpTextTemplatingPermissionDefinitionProvider.cs @@ -10,10 +10,14 @@ public class AbpTextTemplatingPermissionDefinitionProvider : PermissionDefinitio { var textTemplatingGroup = context.AddGroup(AbpTextTemplatingPermissions.GroupName, L("Permission:TextTemplating")); - var textTemplatePermission = textTemplatingGroup.AddPermission(AbpTextTemplatingPermissions.TextTemplate.Default, L("Permission:TextTemplates")); - textTemplatePermission.AddChild(AbpTextTemplatingPermissions.TextTemplate.Create, L("Permission:Create")); - textTemplatePermission.AddChild(AbpTextTemplatingPermissions.TextTemplate.Update, L("Permission:Edit")); - textTemplatePermission.AddChild(AbpTextTemplatingPermissions.TextTemplate.Delete, L("Permission:Delete")); + var textTemplateDefinition = textTemplatingGroup.AddPermission(AbpTextTemplatingPermissions.TextTemplateDefinition.Default, L("Permission:TextTemplateDefinitions")); + textTemplateDefinition.AddChild(AbpTextTemplatingPermissions.TextTemplateDefinition.Create, L("Permission:Create")); + textTemplateDefinition.AddChild(AbpTextTemplatingPermissions.TextTemplateDefinition.Update, L("Permission:Edit")); + textTemplateDefinition.AddChild(AbpTextTemplatingPermissions.TextTemplateDefinition.Delete, L("Permission:Delete")); + + var textTemplateContent = textTemplatingGroup.AddPermission(AbpTextTemplatingPermissions.TextTemplateContent.Default, L("Permission:TextTemplateContents")); + textTemplateContent.AddChild(AbpTextTemplatingPermissions.TextTemplateContent.Update, L("Permission:Edit")); + textTemplateContent.AddChild(AbpTextTemplatingPermissions.TextTemplateContent.Delete, L("Permission:Delete")); } private static LocalizableString L(string name) diff --git a/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Application.Contracts/LINGYUN/Abp/TextTemplating/Permissions/AbpTextTemplatingPermissions.cs b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Application.Contracts/LINGYUN/Abp/TextTemplating/Permissions/AbpTextTemplatingPermissions.cs index db9dbfdbd..b8e43fe5b 100644 --- a/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Application.Contracts/LINGYUN/Abp/TextTemplating/Permissions/AbpTextTemplatingPermissions.cs +++ b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Application.Contracts/LINGYUN/Abp/TextTemplating/Permissions/AbpTextTemplatingPermissions.cs @@ -6,9 +6,16 @@ public static class AbpTextTemplatingPermissions { public const string GroupName = "AbpTextTemplating"; - public static class TextTemplate + public static class TextTemplateContent { - public const string Default = GroupName + ".TextTemplates"; + public const string Default = GroupName + ".TextTemplateContents"; + public const string Update = Default + ".Update"; + public const string Delete = Default + ".Delete"; + } + + public static class TextTemplateDefinition + { + public const string Default = GroupName + ".TextTemplateDefinitions"; public const string Create = Default + ".Create"; public const string Update = Default + ".Update"; public const string Delete = Default + ".Delete"; diff --git a/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Application.Contracts/LINGYUN/Abp/TextTemplating/TextTemplateUpdateInput.cs b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Application.Contracts/LINGYUN/Abp/TextTemplating/TextTemplateContentUpdateDto.cs similarity index 66% rename from aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Application.Contracts/LINGYUN/Abp/TextTemplating/TextTemplateUpdateInput.cs rename to aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Application.Contracts/LINGYUN/Abp/TextTemplating/TextTemplateContentUpdateDto.cs index 54fcfadbf..e9e086db9 100644 --- a/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Application.Contracts/LINGYUN/Abp/TextTemplating/TextTemplateUpdateInput.cs +++ b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Application.Contracts/LINGYUN/Abp/TextTemplating/TextTemplateContentUpdateDto.cs @@ -3,12 +3,8 @@ using Volo.Abp.Validation; namespace LINGYUN.Abp.TextTemplating; -public class TextTemplateUpdateInput +public class TextTemplateContentUpdateDto { - [Required] - [DynamicStringLength(typeof(TextTemplateConsts), nameof(TextTemplateConsts.MaxNameLength))] - public string Name { get; set; } - [DynamicStringLength(typeof(TextTemplateConsts), nameof(TextTemplateConsts.MaxCultureLength))] public string Culture { get; set; } diff --git a/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Application.Contracts/LINGYUN/Abp/TextTemplating/TextTemplateDefinitionCreateDto.cs b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Application.Contracts/LINGYUN/Abp/TextTemplating/TextTemplateDefinitionCreateDto.cs new file mode 100644 index 000000000..a1f4d90fa --- /dev/null +++ b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Application.Contracts/LINGYUN/Abp/TextTemplating/TextTemplateDefinitionCreateDto.cs @@ -0,0 +1,11 @@ +using System.ComponentModel.DataAnnotations; +using Volo.Abp.Validation; + +namespace LINGYUN.Abp.TextTemplating; + +public class TextTemplateDefinitionCreateDto : TextTemplateDefinitionCreateOrUpdateDto +{ + [Required] + [DynamicStringLength(typeof(TextTemplateDefinitionConsts), nameof(TextTemplateDefinitionConsts.MaxNameLength))] + public string Name { get; set; } +} diff --git a/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Application.Contracts/LINGYUN/Abp/TextTemplating/TextTemplateDefinitionCreateOrUpdateDto.cs b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Application.Contracts/LINGYUN/Abp/TextTemplating/TextTemplateDefinitionCreateOrUpdateDto.cs new file mode 100644 index 000000000..17b638ef5 --- /dev/null +++ b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Application.Contracts/LINGYUN/Abp/TextTemplating/TextTemplateDefinitionCreateOrUpdateDto.cs @@ -0,0 +1,24 @@ +using System.ComponentModel.DataAnnotations; +using Volo.Abp.Validation; + +namespace LINGYUN.Abp.TextTemplating; + +public abstract class TextTemplateDefinitionCreateOrUpdateDto +{ + [Required] + [DynamicStringLength(typeof(TextTemplateDefinitionConsts), nameof(TextTemplateDefinitionConsts.MaxDisplayNameLength))] + public string DisplayName { get; set; } + + [DynamicStringLength(typeof(TextTemplateDefinitionConsts), nameof(TextTemplateDefinitionConsts.MaxDefaultCultureNameLength))] + public string DefaultCultureName { get; set; } + + public bool IsInlineLocalized { get; set; } + + public bool IsLayout { get; set; } + + [DynamicStringLength(typeof(TextTemplateDefinitionConsts), nameof(TextTemplateDefinitionConsts.MaxLayoutLength))] + public string Layout { get; set; } + + [DynamicStringLength(typeof(TextTemplateDefinitionConsts), nameof(TextTemplateDefinitionConsts.MaxRenderEngineLength))] + public string RenderEngine { get; set; } +} diff --git a/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Application.Contracts/LINGYUN/Abp/TextTemplating/TextTemplateDefinitionDto.cs b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Application.Contracts/LINGYUN/Abp/TextTemplating/TextTemplateDefinitionDto.cs index a2852b36c..103bf6fc4 100644 --- a/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Application.Contracts/LINGYUN/Abp/TextTemplating/TextTemplateDefinitionDto.cs +++ b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Application.Contracts/LINGYUN/Abp/TextTemplating/TextTemplateDefinitionDto.cs @@ -1,6 +1,8 @@ -namespace LINGYUN.Abp.TextTemplating; +using Volo.Abp.Domain.Entities; -public class TextTemplateDefinitionDto +namespace LINGYUN.Abp.TextTemplating; + +public class TextTemplateDefinitionDto : IHasConcurrencyStamp { public string Name { get; set; } public string DisplayName { get; set; } @@ -8,4 +10,6 @@ public class TextTemplateDefinitionDto public bool IsInlineLocalized { get; set; } public bool IsLayout { get; set; } public string Layout { get; set; } + public bool IsStatic { get; set; } + public string ConcurrencyStamp { get; set; } } diff --git a/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Application.Contracts/LINGYUN/Abp/TextTemplating/TextTemplateDefinitionUpdateDto.cs b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Application.Contracts/LINGYUN/Abp/TextTemplating/TextTemplateDefinitionUpdateDto.cs new file mode 100644 index 000000000..ea5819589 --- /dev/null +++ b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Application.Contracts/LINGYUN/Abp/TextTemplating/TextTemplateDefinitionUpdateDto.cs @@ -0,0 +1,7 @@ +using Volo.Abp.Domain.Entities; + +namespace LINGYUN.Abp.TextTemplating; +public class TextTemplateDefinitionUpdateDto : TextTemplateDefinitionCreateOrUpdateDto, IHasConcurrencyStamp +{ + public string ConcurrencyStamp { get; set; } +} diff --git a/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Application.Contracts/LINGYUN/Abp/TextTemplating/TextTemplateRestoreInput.cs b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Application.Contracts/LINGYUN/Abp/TextTemplating/TextTemplateRestoreInput.cs index eb6239b97..d3225ea57 100644 --- a/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Application.Contracts/LINGYUN/Abp/TextTemplating/TextTemplateRestoreInput.cs +++ b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Application.Contracts/LINGYUN/Abp/TextTemplating/TextTemplateRestoreInput.cs @@ -1,14 +1,9 @@ -using System.ComponentModel.DataAnnotations; -using Volo.Abp.Validation; +using Volo.Abp.Validation; namespace LINGYUN.Abp.TextTemplating; public class TextTemplateRestoreInput { - [Required] - [DynamicStringLength(typeof(TextTemplateConsts), nameof(TextTemplateConsts.MaxNameLength))] - public string Name { get; set; } - [DynamicStringLength(typeof(TextTemplateConsts), nameof(TextTemplateConsts.MaxCultureLength))] public string Culture { get; set; } } diff --git a/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Application/LINGYUN.Abp.TextTemplating.Application.csproj b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Application/LINGYUN.Abp.TextTemplating.Application.csproj index 7a8d8a78f..026c358d2 100644 --- a/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Application/LINGYUN.Abp.TextTemplating.Application.csproj +++ b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Application/LINGYUN.Abp.TextTemplating.Application.csproj @@ -8,6 +8,10 @@ + + + + diff --git a/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Application/LINGYUN/Abp/TextTemplating/AbpTextTemplatingApplicationAutoMapperProfile.cs b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Application/LINGYUN/Abp/TextTemplating/AbpTextTemplatingApplicationAutoMapperProfile.cs index cc1c7ff57..bce5e1104 100644 --- a/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Application/LINGYUN/Abp/TextTemplating/AbpTextTemplatingApplicationAutoMapperProfile.cs +++ b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Application/LINGYUN/Abp/TextTemplating/AbpTextTemplatingApplicationAutoMapperProfile.cs @@ -6,5 +6,6 @@ public class AbpTextTemplatingApplicationAutoMapperProfile : Profile { public AbpTextTemplatingApplicationAutoMapperProfile() { + CreateMap(); } } diff --git a/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Application/LINGYUN/Abp/TextTemplating/TextTemplateAppService.cs b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Application/LINGYUN/Abp/TextTemplating/TextTemplateAppService.cs deleted file mode 100644 index 1f90ac77f..000000000 --- a/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Application/LINGYUN/Abp/TextTemplating/TextTemplateAppService.cs +++ /dev/null @@ -1,174 +0,0 @@ -using Microsoft.AspNetCore.Authorization; -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Linq; -using System.Threading.Tasks; -using Volo.Abp; -using Volo.Abp.Application.Dtos; -using Volo.Abp.Localization; -using Volo.Abp.TextTemplating; - -namespace LINGYUN.Abp.TextTemplating; - -[Authorize(AbpTextTemplatingPermissions.TextTemplate.Default)] -public class TextTemplateAppService : AbpTextTemplatingAppServiceBase, ITextTemplateAppService -{ - protected ITextTemplateRepository TextTemplateRepository { get; } - protected ITemplateContentProvider TemplateContentProvider { get; } - protected ITemplateDefinitionManager TemplateDefinitionManager { get; } - - public TextTemplateAppService( - ITextTemplateRepository textTemplateRepository, - ITemplateContentProvider templateContentProvider, - ITemplateDefinitionManager templateDefinitionManager) - { - TextTemplateRepository = textTemplateRepository; - TemplateContentProvider = templateContentProvider; - TemplateDefinitionManager = templateDefinitionManager; - } - - public virtual Task GetAsync(string name) - { - var templateDefinition = GetTemplateDefinition(name); - - var layout = templateDefinition.Layout; - if (!layout.IsNullOrWhiteSpace()) - { - var layoutDefinition = GetTemplateDefinition(templateDefinition.Layout); - layout = layoutDefinition.DisplayName.Localize(StringLocalizerFactory); - } - - var result = new TextTemplateDefinitionDto - { - DefaultCultureName = templateDefinition.DefaultCultureName, - IsInlineLocalized = templateDefinition.IsInlineLocalized, - IsLayout = templateDefinition.IsLayout, - Layout = layout, - Name = templateDefinition.Name, - DisplayName = templateDefinition.DisplayName.Localize(StringLocalizerFactory), - }; - - return Task.FromResult(result); - } - - public async virtual Task GetContentAsync(TextTemplateContentGetInput input) - { - var templateDefinition = GetTemplateDefinition(input.Name); - - var content = await TemplateContentProvider.GetContentOrNullAsync(templateDefinition.Name, input.Culture); - - return new TextTemplateContentDto - { - Name = templateDefinition.Name, - Culture = input.Culture, - Content = content, - }; - } - - public virtual Task> GetListAsync(TextTemplateDefinitionGetListInput input) - { - var templates = new List(); - var templateDefinitions = TemplateDefinitionManager.GetAll(); - var filterTemplates = templateDefinitions - .WhereIf(!input.Filter.IsNullOrWhiteSpace(), x => - x.Name.Contains(input.Filter) || x.Layout.Contains(input.Filter)) - .Skip(input.SkipCount) - .Take(input.MaxResultCount); - - foreach (var templateDefinition in filterTemplates) - { - var layout = templateDefinition.Layout; - if (!layout.IsNullOrWhiteSpace()) - { - var layoutDefinition = GetTemplateDefinition(templateDefinition.Layout); - layout = layoutDefinition.DisplayName.Localize(StringLocalizerFactory); - } - - var result = new TextTemplateDefinitionDto - { - DefaultCultureName = templateDefinition.DefaultCultureName, - IsInlineLocalized = templateDefinition.IsInlineLocalized, - IsLayout = templateDefinition.IsLayout, - Layout = layout, - Name = templateDefinition.Name, - DisplayName = templateDefinition.DisplayName.Localize(StringLocalizerFactory), - }; - - templates.Add(result); - } - - return Task.FromResult(new PagedResultDto(templateDefinitions.Count, templates)); - } - - [Authorize(AbpTextTemplatingPermissions.TextTemplate.Delete)] - public async virtual Task RestoreToDefaultAsync(TextTemplateRestoreInput input) - { - var templateDefinition = GetTemplateDefinition(input.Name); - - var templates = await TextTemplateRepository - .GetListAsync(x => x.Name.Equals(templateDefinition.Name) && x.Culture.Equals(input.Culture)); - - await TextTemplateRepository.DeleteManyAsync(templates); - - await CurrentUnitOfWork.SaveChangesAsync(); - } - - [Authorize(AbpTextTemplatingPermissions.TextTemplate.Update)] - public async virtual Task UpdateAsync(TextTemplateUpdateInput input) - { - var templateDefinition = GetTemplateDefinition(input.Name); - - var template = await TextTemplateRepository.FindByNameAsync(input.Name, input.Culture); - if (template == null) - { - template = new TextTemplate( - GuidGenerator.Create(), - templateDefinition.Name, - templateDefinition.DisplayName.Localize(StringLocalizerFactory), - input.Content, - input.Culture); - - await TextTemplateRepository.InsertAsync(template); - } - else - { - template.SetContent(input.Content); - - await TextTemplateRepository.UpdateAsync(template); - } - - await CurrentUnitOfWork.SaveChangesAsync(); - - var layout = templateDefinition.Layout; - if (!layout.IsNullOrWhiteSpace()) - { - var layoutDefinition = GetTemplateDefinition(templateDefinition.Layout); - layout = layoutDefinition.DisplayName.Localize(StringLocalizerFactory); - } - - return new TextTemplateDefinitionDto - { - DefaultCultureName = templateDefinition.DefaultCultureName, - IsInlineLocalized = templateDefinition.IsInlineLocalized, - IsLayout = templateDefinition.IsLayout, - Layout = layout, - Name = templateDefinition.Name, - DisplayName = templateDefinition.DisplayName.Localize(StringLocalizerFactory), - }; - } - - protected virtual TemplateDefinition GetTemplateDefinition(string name) - { - var template = TemplateDefinitionManager.GetOrNull(name); - if (template == null) - { - throw new BusinessException( - AbpTextTemplatingErrorCodes.TemplateNotFound, - $"The text template {name} does not exist!") - .WithData("Name", name); - } - - return template; - } -} diff --git a/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Application/LINGYUN/Abp/TextTemplating/TextTemplateContentAppService.cs b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Application/LINGYUN/Abp/TextTemplating/TextTemplateContentAppService.cs new file mode 100644 index 000000000..cbbb322d2 --- /dev/null +++ b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Application/LINGYUN/Abp/TextTemplating/TextTemplateContentAppService.cs @@ -0,0 +1,127 @@ +using Microsoft.AspNetCore.Authorization; +using System.Threading.Tasks; +using Volo.Abp; +using Volo.Abp.TextTemplating; + +namespace LINGYUN.Abp.TextTemplating; + +[Authorize(AbpTextTemplatingPermissions.TextTemplateContent.Default)] +public class TextTemplateContentAppService : AbpTextTemplatingAppServiceBase, ITextTemplateContentAppService +{ + protected ITextTemplateRepository TextTemplateRepository { get; } + protected ITemplateContentProvider TemplateContentProvider { get; } + protected ITemplateDefinitionStore TemplateDefinitionStore { get; } + + public TextTemplateContentAppService( + ITextTemplateRepository textTemplateRepository, + ITemplateContentProvider templateContentProvider, + ITemplateDefinitionStore templateDefinitionStore) + { + TextTemplateRepository = textTemplateRepository; + TemplateContentProvider = templateContentProvider; + TemplateDefinitionStore = templateDefinitionStore; + } + + public async virtual Task GetAsync(TextTemplateContentGetInput input) + { + var templateDefinition = await GetTemplateDefinition(input.Name); + + var content = await TemplateContentProvider.GetContentOrNullAsync(templateDefinition.Name, input.Culture); + + return new TextTemplateContentDto + { + Name = templateDefinition.Name, + Culture = input.Culture, + Content = content, + }; + } + + //public virtual Task> GetListAsync(TextTemplateDefinitionGetListInput input) + //{ + // var templates = new List(); + // var templateDefinitions = TemplateDefinitionManager.GetAll(); + // var filterTemplates = templateDefinitions + // .WhereIf(!input.Filter.IsNullOrWhiteSpace(), x => + // x.Name.Contains(input.Filter) || x.Layout.Contains(input.Filter)) + // .Skip(input.SkipCount) + // .Take(input.MaxResultCount); + + // foreach (var templateDefinition in filterTemplates) + // { + // var layout = templateDefinition.Layout; + // if (!layout.IsNullOrWhiteSpace()) + // { + // var layoutDefinition = GetTemplateDefinition(templateDefinition.Layout); + // layout = layoutDefinition.DisplayName.Localize(StringLocalizerFactory); + // } + + // var result = new TextTemplateDefinitionDto + // { + // DefaultCultureName = templateDefinition.DefaultCultureName, + // IsInlineLocalized = templateDefinition.IsInlineLocalized, + // IsLayout = templateDefinition.IsLayout, + // Layout = layout, + // Name = templateDefinition.Name, + // DisplayName = templateDefinition.DisplayName.Localize(StringLocalizerFactory), + // }; + + // templates.Add(result); + // } + + // return Task.FromResult(new PagedResultDto(templateDefinitions.Count, templates)); + //} + + [Authorize(AbpTextTemplatingPermissions.TextTemplateContent.Delete)] + public async virtual Task RestoreToDefaultAsync(string name, TextTemplateRestoreInput input) + { + var templateDefinition = await GetTemplateDefinition(name); + + var templates = await TextTemplateRepository + .GetListAsync(x => x.Name.Equals(templateDefinition.Name) && x.Culture.Equals(input.Culture)); + + await TextTemplateRepository.DeleteManyAsync(templates); + + await CurrentUnitOfWork.SaveChangesAsync(); + } + + [Authorize(AbpTextTemplatingPermissions.TextTemplateContent.Update)] + public async virtual Task UpdateAsync(string name, TextTemplateContentUpdateDto input) + { + var templateDefinition = await GetTemplateDefinition(name); + + var template = await TextTemplateRepository.FindByNameAsync(name, input.Culture); + if (template == null) + { + template = new TextTemplate( + GuidGenerator.Create(), + templateDefinition.Name, + templateDefinition.DisplayName.Localize(StringLocalizerFactory), + input.Content, + input.Culture); + + await TextTemplateRepository.InsertAsync(template); + } + else + { + template.SetContent(input.Content); + + await TextTemplateRepository.UpdateAsync(template); + } + + await CurrentUnitOfWork.SaveChangesAsync(); + + return new TextTemplateContentDto + { + Name = templateDefinition.Name, + Culture = input.Culture, + Content = template.Content, + }; + } + + protected async virtual Task GetTemplateDefinition(string name) + { + return await TemplateDefinitionStore.GetOrNullAsync(name) + ?? throw new BusinessException(AbpTextTemplatingErrorCodes.TextTemplateDefinition.TemplateNotFound) + .WithData(nameof(TextTemplateDefinition.Name), name); + } +} diff --git a/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Application/LINGYUN/Abp/TextTemplating/TextTemplateDefinitionAppService.cs b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Application/LINGYUN/Abp/TextTemplating/TextTemplateDefinitionAppService.cs new file mode 100644 index 000000000..19251adb9 --- /dev/null +++ b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Application/LINGYUN/Abp/TextTemplating/TextTemplateDefinitionAppService.cs @@ -0,0 +1,257 @@ +using Microsoft.AspNetCore.Authorization; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Dynamic.Core; +using System.Threading.Tasks; +using Volo.Abp; +using Volo.Abp.Application.Dtos; +using Volo.Abp.Localization; +using Volo.Abp.TextTemplating; + +namespace LINGYUN.Abp.TextTemplating; + +[Authorize(AbpTextTemplatingPermissions.TextTemplateDefinition.Default)] +public class TextTemplateDefinitionAppService : AbpTextTemplatingAppServiceBase, ITextTemplateDefinitionAppService +{ + private readonly ITemplateDefinitionStore _store; + private readonly ITextTemplateDefinitionRepository _repository; + private readonly ILocalizableStringSerializer _localizableStringSerializer; + + public TextTemplateDefinitionAppService( + ITemplateDefinitionStore store, + ITextTemplateDefinitionRepository repository, + ILocalizableStringSerializer localizableStringSerializer) + { + _store = store; + _repository = repository; + _localizableStringSerializer = localizableStringSerializer; + } + + [Authorize(AbpTextTemplatingPermissions.TextTemplateDefinition.Create)] + public async virtual Task CreateAsync(TextTemplateDefinitionCreateDto input) + { + var template = await _store.GetOrNullAsync(input.Name); + if (template != null) + { + throw new BusinessException(AbpTextTemplatingErrorCodes.TextTemplateDefinition.NameAlreadyExists) + .WithData(nameof(TextTemplateDefinition.Name), input.Name); + } + + var layout = input.Layout; + if (!layout.IsNullOrWhiteSpace()) + { + var layoutDefinition = await _store.GetAsync(layout); + layout = await layoutDefinition.DisplayName.LocalizeAsync(StringLocalizerFactory); + } + + var formatDisplayName = input.DisplayName; + if (!formatDisplayName.IsNullOrWhiteSpace()) + { + var displayName = _localizableStringSerializer.Deserialize(formatDisplayName); + formatDisplayName = await displayName.LocalizeAsync(StringLocalizerFactory); + } + + var templateDefinition = new TextTemplateDefinition( + GuidGenerator.Create(), + input.Name, + input.DisplayName, + input.IsLayout, + input.Layout, + input.IsInlineLocalized, + input.DefaultCultureName, + input.RenderEngine); + + await _store.CreateAsync(templateDefinition); + + await CurrentUnitOfWork.SaveChangesAsync(); + + var result = new TextTemplateDefinitionDto + { + DefaultCultureName = templateDefinition.DefaultCultureName, + IsInlineLocalized = templateDefinition.IsInlineLocalized, + IsLayout = templateDefinition.IsLayout, + Layout = layout, + Name = templateDefinition.Name, + DisplayName = formatDisplayName, + IsStatic = templateDefinition.IsStatic, + ConcurrencyStamp = templateDefinition.ConcurrencyStamp, + }; + + return result; + } + + [Authorize(AbpTextTemplatingPermissions.TextTemplateDefinition.Delete)] + public async virtual Task DeleteAsync(string name) + { + await _store.DeleteAsync(name); + } + + public async virtual Task GetByNameAsync(string name) + { + var template = await _store.GetAsync(name); + + var layout = template.Layout; + if (!layout.IsNullOrWhiteSpace()) + { + var layoutDefinition = await _store.GetAsync(template.Layout); + layout = await layoutDefinition.DisplayName.LocalizeAsync(StringLocalizerFactory); + } + + var result = new TextTemplateDefinitionDto + { + DefaultCultureName = template.DefaultCultureName, + IsInlineLocalized = template.IsInlineLocalized, + IsLayout = template.IsLayout, + Layout = layout, + Name = template.Name, + DisplayName = await template.DisplayName.LocalizeAsync(StringLocalizerFactory), + }; + + var staticState = template.Properties.GetOrDefault(nameof(TextTemplateDefinition.IsStatic)); + if (staticState != null && staticState is bool isStatic) + { + result.IsStatic = isStatic; + } + + return result; + } + + public async virtual Task> GetListAsync(TextTemplateDefinitionGetListInput input) + { + var templates = new List(); + + var templateDefinitions = await _store.GetAllAsync(); + + var sorting = input.Sorting; + if (sorting.IsNullOrWhiteSpace()) + { + sorting = nameof(TextTemplateDefinition.Name); + } + var filterTemplates = templateDefinitions.AsQueryable() + .WhereIf(!input.Filter.IsNullOrWhiteSpace(), x => + x.Name.Contains(input.Filter) || x.Layout.Contains(input.Filter)) + .OrderBy(sorting) + .Skip(input.SkipCount) + .Take(input.MaxResultCount); + + foreach (var templateDefinition in filterTemplates) + { + var layout = templateDefinition.Layout; + if (!layout.IsNullOrWhiteSpace()) + { + var layoutDefinition = await _store.GetOrNullAsync(templateDefinition.Layout); + if (layoutDefinition != null) + { + layout = await layoutDefinition.DisplayName.LocalizeAsync(StringLocalizerFactory); + } + } + + var result = new TextTemplateDefinitionDto + { + DefaultCultureName = templateDefinition.DefaultCultureName, + IsInlineLocalized = templateDefinition.IsInlineLocalized, + IsLayout = templateDefinition.IsLayout, + Layout = layout, + Name = templateDefinition.Name, + DisplayName = templateDefinition.DisplayName.Localize(StringLocalizerFactory), + }; + + var staticState = templateDefinition.Properties.GetOrDefault(nameof(TextTemplateDefinition.IsStatic)); + if (staticState != null && staticState is bool isStatic) + { + result.IsStatic = isStatic; + } + + templates.Add(result); + } + + return new PagedResultDto(templateDefinitions.Count, templates); + } + + [Authorize(AbpTextTemplatingPermissions.TextTemplateDefinition.Update)] + public async virtual Task UpdateAsync(string name, TextTemplateDefinitionUpdateDto input) + { + var templateDefinitionRecord = await _repository.FindByNameAsync(name); + + if (templateDefinitionRecord == null) + { + var templateDefinition = await _store.GetAsync(name); + + templateDefinitionRecord = new TextTemplateDefinition( + GuidGenerator.Create(), + templateDefinition.Name, + _localizableStringSerializer.Serialize(templateDefinition.DisplayName), + templateDefinition.IsLayout, + templateDefinition.Layout, + templateDefinition.IsInlineLocalized, + templateDefinition.DefaultCultureName, + templateDefinition.RenderEngine); + + UpdateByInput(templateDefinitionRecord, input); + + await _store.CreateAsync(templateDefinitionRecord); + } + else + { + UpdateByInput(templateDefinitionRecord, input); + + if (!string.Equals(templateDefinitionRecord.DisplayName, input.DisplayName, StringComparison.InvariantCultureIgnoreCase)) + { + var displayNameD = _localizableStringSerializer.Deserialize(input.DisplayName); + + templateDefinitionRecord.DisplayName = await displayNameD.LocalizeAsync(StringLocalizerFactory); + } + + await _store.UpdateAsync(templateDefinitionRecord); + } + + await CurrentUnitOfWork.SaveChangesAsync(); + + var layout = templateDefinitionRecord.Layout; + if (!layout.IsNullOrWhiteSpace()) + { + var layoutDefinition = await _store.GetAsync(layout); + layout = await layoutDefinition.DisplayName.LocalizeAsync(StringLocalizerFactory); + } + + var displayName = templateDefinitionRecord.DisplayName; + if (!displayName.IsNullOrWhiteSpace()) + { + var displayNameD = _localizableStringSerializer.Deserialize(displayName); + displayName = await displayNameD.LocalizeAsync(StringLocalizerFactory); + } + + var result = new TextTemplateDefinitionDto + { + DefaultCultureName = templateDefinitionRecord.DefaultCultureName, + IsInlineLocalized = templateDefinitionRecord.IsInlineLocalized, + IsLayout = templateDefinitionRecord.IsLayout, + Layout = layout, + Name = templateDefinitionRecord.Name, + DisplayName = displayName, + IsStatic = templateDefinitionRecord.IsStatic, + ConcurrencyStamp = templateDefinitionRecord.ConcurrencyStamp, + }; + + return result; + } + + protected virtual void UpdateByInput(TextTemplateDefinition templateDefinition, TextTemplateDefinitionCreateOrUpdateDto input) + { + templateDefinition.IsInlineLocalized = input.IsInlineLocalized; + templateDefinition.IsLayout = input.IsLayout; + if (!string.Equals(templateDefinition.Layout, input.Layout, StringComparison.InvariantCultureIgnoreCase)) + { + templateDefinition.Layout = input.Layout; + } + if (!string.Equals(templateDefinition.DefaultCultureName, input.DefaultCultureName, StringComparison.InvariantCultureIgnoreCase)) + { + templateDefinition.DefaultCultureName = input.DefaultCultureName; + } + if (!string.Equals(templateDefinition.RenderEngine, input.RenderEngine, StringComparison.InvariantCultureIgnoreCase)) + { + templateDefinition.RenderEngine = input.RenderEngine; + } + } +} diff --git a/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Domain.Shared/LINGYUN/Abp/TextTemplating/AbpTextTemplatingErrorCodes.cs b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Domain.Shared/LINGYUN/Abp/TextTemplating/AbpTextTemplatingErrorCodes.cs index d3dc1e466..2bc46178a 100644 --- a/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Domain.Shared/LINGYUN/Abp/TextTemplating/AbpTextTemplatingErrorCodes.cs +++ b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Domain.Shared/LINGYUN/Abp/TextTemplating/AbpTextTemplatingErrorCodes.cs @@ -3,9 +3,16 @@ public static class AbpTextTemplatingErrorCodes { public const string Namespace = "TextTemplating"; - - /// - /// 模板不存在! - /// - public const string TemplateNotFound = Namespace + ":01404"; + public static class TextTemplateDefinition + { + private const string Prefix = Namespace + ":01"; + /// + /// 模板 {Name} 已经存在 + /// + public const string NameAlreadyExists = Prefix + "100"; + /// + /// 模板 {Name} 不存在! + /// + public const string TemplateNotFound = Prefix + "404"; + } } diff --git a/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Domain.Shared/LINGYUN/Abp/TextTemplating/Localization/Resources/en.json b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Domain.Shared/LINGYUN/Abp/TextTemplating/Localization/Resources/en.json index 11a4d5942..26770a342 100644 --- a/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Domain.Shared/LINGYUN/Abp/TextTemplating/Localization/Resources/en.json +++ b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Domain.Shared/LINGYUN/Abp/TextTemplating/Localization/Resources/en.json @@ -2,18 +2,24 @@ "culture": "en", "texts": { "Permission:TextTemplating": "Templating", - "Permission:TextTemplates": "Text Templates", + "Permission:TextTemplateContents": "Template Contents", + "Permission:TextTemplateDefinitions": "Template Definitions", "Permission:Create": "Create", "Permission:Edit": "Edit", "Permission:Delete": "Delete", - "TextTemplates": "Text Templates", "DisplayName:Name": "Name", "DisplayName:Culture": "Culture", "DisplayName:Content": "Content", "DisplayName:DisplayName": "DisplayName", "DisplayName:IsInlineLocalized": "Is Inline Localized", "DisplayName:IsLayout": "Is Layout", + "DisplayName:Layout": "Layout", "DisplayName:DefaultCultureName": "Default Culture", + "DisplayName:RenderEngine": "Render Engine", + "DisplayName:IsStatic": "Static", + "TextTemplating:01100": "Text template {Name} already exists!", + "TextTemplating:01404": "No text template named {Name} found!", + "TextTemplates": "Text Templates", "Contents": "Contents", "Layout": "Layout", "LocalizationResource": "Localization Resource", @@ -30,6 +36,9 @@ "TemplateContentUpdated": "The template content has been updated", "TemplateContentRestoredToDefault": "The template content is restored to the default value.", "CustomizePerCulture": "Customize per culture", - "InlineContentDescription": "This template uses inline localization. You can use the L<\/b> function to localize a text, like {{L \"Hello\"}}<\/b>. If you still want to define a completely new template for a culture, use the \"Customize per culture\" button.
To get more information about syntax and other details, please check the Text Templates documentation<\/a>.." + "InlineContentDescription": "This template uses inline localization. You can use the L<\/b> function to localize a text, like {{L \"Hello\"}}<\/b>. If you still want to define a completely new template for a culture, use the \"Customize per culture\" button.
To get more information about syntax and other details, please check the
Text Templates documentation<\/a>..", + "RestoreTemplateToDefault": "Revert to the default template", + "RestoreTemplateToDefaultMessage": "Are you sure? This is a built-in template. This operation restores the template to its default properties.", + "TemplateUpdated": "Template properties have been updated" } } \ No newline at end of file diff --git a/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Domain.Shared/LINGYUN/Abp/TextTemplating/Localization/Resources/zh-Hans.json b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Domain.Shared/LINGYUN/Abp/TextTemplating/Localization/Resources/zh-Hans.json index b4738a61a..5646ba734 100644 --- a/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Domain.Shared/LINGYUN/Abp/TextTemplating/Localization/Resources/zh-Hans.json +++ b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Domain.Shared/LINGYUN/Abp/TextTemplating/Localization/Resources/zh-Hans.json @@ -2,18 +2,24 @@ "culture": "zh-Hans", "texts": { "Permission:TextTemplating": "模板管理", - "Permission:TextTemplates": "文本模板", + "Permission:TextTemplateContents": "模板内容", + "Permission:TextTemplateDefinitions": "定义模板", "Permission:Create": "新增", "Permission:Edit": "修改", "Permission:Delete": "删除", - "TextTemplates": "文本模板", "DisplayName:Name": "名称", "DisplayName:Culture": "区域", "DisplayName:Content": "内容", "DisplayName:DisplayName": "显示名称", "DisplayName:IsInlineLocalized": "内联本地化", "DisplayName:IsLayout": "是否为布局页", + "DisplayName:Layout": "布局页", "DisplayName:DefaultCultureName": "默认文化名称", + "DisplayName:RenderEngine": "渲染引擎", + "DisplayName:IsStatic": "内置", + "TextTemplating:01100": "文本模板 {Name} 已经存在!", + "TextTemplating:01404": "没有找到名为 {Name} 的文本模板!", + "TextTemplates": "文本模板", "Contents": "内容", "Layout": "布局页", "LocalizationResource": "本地化资源", @@ -30,6 +36,9 @@ "TemplateContentUpdated": "模板内容已更新", "TemplateContentRestoredToDefault": "模板内容恢复为默认值.", "CustomizePerCulture": "根据文化定制", - "InlineContentDescription": "该模板使用内联本地化. 你可以使用L函数对文本进行本地化,例如 {{L \"Hello\"}}如果你仍想为区域性定义一个全新的模板,请使用\"根据文化定制\"按钮.
请检查
文本模板文档获取更多信息." + "InlineContentDescription": "该模板使用内联本地化. 你可以使用L函数对文本进行本地化,例如 {{L \"Hello\"}}如果你仍想为区域性定义一个全新的模板,请使用\"根据文化定制\"按钮.
请检查文本模板文档获取更多信息.", + "RestoreTemplateToDefault": "还原到默认模板", + "RestoreTemplateToDefaultMessage": "你确定吗? 此模板为内置模板, 此操作将还原模板为默认属性.", + "TemplateUpdated": "模板属性已更新" } } \ No newline at end of file diff --git a/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Domain.Shared/LINGYUN/Abp/TextTemplating/TextTemplateDefinitionConsts.cs b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Domain.Shared/LINGYUN/Abp/TextTemplating/TextTemplateDefinitionConsts.cs new file mode 100644 index 000000000..dd7f2f633 --- /dev/null +++ b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Domain.Shared/LINGYUN/Abp/TextTemplating/TextTemplateDefinitionConsts.cs @@ -0,0 +1,9 @@ +namespace LINGYUN.Abp.TextTemplating; +public static class TextTemplateDefinitionConsts +{ + public static int MaxNameLength { get; set; } = 128; + public static int MaxDisplayNameLength { get; set; } = 512; + public static int MaxLayoutLength { get; set; } = 60; + public static int MaxDefaultCultureNameLength { get; set; } = 30; + public static int MaxRenderEngineLength { get; set; } = 30; +} diff --git a/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Domain/LINGYUN.Abp.TextTemplating.Domain.csproj b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Domain/LINGYUN.Abp.TextTemplating.Domain.csproj index e05b8a0bb..fe12bd0a5 100644 --- a/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Domain/LINGYUN.Abp.TextTemplating.Domain.csproj +++ b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Domain/LINGYUN.Abp.TextTemplating.Domain.csproj @@ -8,10 +8,15 @@ + + + + + diff --git a/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Domain/LINGYUN/Abp/TextTemplating/AbpTextTemplatingCachingOptions.cs b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Domain/LINGYUN/Abp/TextTemplating/AbpTextTemplatingCachingOptions.cs index 02470854f..e3e9c96ff 100644 --- a/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Domain/LINGYUN/Abp/TextTemplating/AbpTextTemplatingCachingOptions.cs +++ b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Domain/LINGYUN/Abp/TextTemplating/AbpTextTemplatingCachingOptions.cs @@ -12,10 +12,39 @@ public class AbpTextTemplatingCachingOptions /// 文本模板缓存绝对过期时间 /// public TimeSpan? MaximumCacheDuration { get; set; } + /// + /// Default: true. + /// + public bool SaveStaticTemplateDefinitionToDatabase { get; set; } + /// + /// Default: false. + /// + public bool IsDynamicTemplateDefinitionStoreEnabled { get; set; } + /// + /// 缓存刷新时间 + /// default: 2 hours + /// + public TimeSpan TemplateDefinitionsCacheRefreshInterval { get; set; } + /// + /// 申请时间戳超时时间 + /// default: 1 minutes + /// + public TimeSpan TemplateDefinitionsCacheStampTimeOut { get; set; } + /// + /// 时间戳过期时间 + /// default: 30 days + /// + public TimeSpan TemplateDefinitionsCacheStampExpiration { get; set; } public AbpTextTemplatingCachingOptions() { MinimumCacheDuration = TimeSpan.FromHours(1); MaximumCacheDuration = TimeSpan.FromDays(30); + + SaveStaticTemplateDefinitionToDatabase = true; + IsDynamicTemplateDefinitionStoreEnabled = false; + TemplateDefinitionsCacheRefreshInterval = TimeSpan.FromHours(2); + TemplateDefinitionsCacheStampTimeOut = TimeSpan.FromMinutes(1); + TemplateDefinitionsCacheStampExpiration = TimeSpan.FromDays(30); } } diff --git a/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Domain/LINGYUN/Abp/TextTemplating/AbpTextTemplatingDomainModule.cs b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Domain/LINGYUN/Abp/TextTemplating/AbpTextTemplatingDomainModule.cs index 8ea529d21..1248a00f5 100644 --- a/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Domain/LINGYUN/Abp/TextTemplating/AbpTextTemplatingDomainModule.cs +++ b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Domain/LINGYUN/Abp/TextTemplating/AbpTextTemplatingDomainModule.cs @@ -1,6 +1,12 @@ -using Volo.Abp.Caching; +using Microsoft.Extensions.DependencyInjection; +using System.Threading; +using System.Threading.Tasks; +using Volo.Abp; +using Volo.Abp.Caching; +using Volo.Abp.Data; using Volo.Abp.Modularity; using Volo.Abp.TextTemplating; +using Volo.Abp.Threading; namespace LINGYUN.Abp.TextTemplating; @@ -10,5 +16,35 @@ namespace LINGYUN.Abp.TextTemplating; typeof(AbpCachingModule))] public class AbpTextTemplatingDomainModule : AbpModule { + private readonly CancellationTokenSource _cancellationTokenSource = new(); + public override void ConfigureServices(ServiceConfigurationContext context) + { + if (context.Services.IsDataMigrationEnvironment()) + { + Configure(options => + { + options.SaveStaticTemplateDefinitionToDatabase = false; + options.IsDynamicTemplateDefinitionStoreEnabled = false; + }); + } + } + + public override void OnApplicationInitialization(ApplicationInitializationContext context) + { + AsyncHelper.RunSync(() => OnApplicationInitializationAsync(context)); + } + + public override Task OnApplicationInitializationAsync(ApplicationInitializationContext context) + { + return context.ServiceProvider + .GetRequiredService() + .InitializeDynamicTemplates(_cancellationTokenSource.Token); + } + + public override Task OnApplicationShutdownAsync(ApplicationShutdownContext context) + { + _cancellationTokenSource.Cancel(); + return Task.CompletedTask; + } } diff --git a/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Domain/LINGYUN/Abp/TextTemplating/IStaticTemplateDefinitionSaver.cs b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Domain/LINGYUN/Abp/TextTemplating/IStaticTemplateDefinitionSaver.cs new file mode 100644 index 000000000..7ec0daae6 --- /dev/null +++ b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Domain/LINGYUN/Abp/TextTemplating/IStaticTemplateDefinitionSaver.cs @@ -0,0 +1,7 @@ +using System.Threading.Tasks; + +namespace LINGYUN.Abp.TextTemplating; +public interface IStaticTemplateDefinitionSaver +{ + Task SaveAsync(); +} diff --git a/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Domain/LINGYUN/Abp/TextTemplating/ITemplateDefinitionStore.cs b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Domain/LINGYUN/Abp/TextTemplating/ITemplateDefinitionStore.cs new file mode 100644 index 000000000..29aef4554 --- /dev/null +++ b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Domain/LINGYUN/Abp/TextTemplating/ITemplateDefinitionStore.cs @@ -0,0 +1,24 @@ +using JetBrains.Annotations; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using Volo.Abp.TextTemplating; + +namespace LINGYUN.Abp.TextTemplating; +public interface ITemplateDefinitionStore +{ + Task CreateAsync(TextTemplateDefinition template); + + Task UpdateAsync(TextTemplateDefinition template); + + Task DeleteAsync(string name, CancellationToken cancellationToken = default); + + [NotNull] + Task GetAsync(string name, CancellationToken cancellationToken = default); + + [NotNull] + Task> GetAllAsync(CancellationToken cancellationToken = default); + + [CanBeNull] + Task GetOrNullAsync(string name, CancellationToken cancellationToken = default); +} diff --git a/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Domain/LINGYUN/Abp/TextTemplating/ITemplateDefinitionStoreCache.cs b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Domain/LINGYUN/Abp/TextTemplating/ITemplateDefinitionStoreCache.cs new file mode 100644 index 000000000..945c181f2 --- /dev/null +++ b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Domain/LINGYUN/Abp/TextTemplating/ITemplateDefinitionStoreCache.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using Volo.Abp.TextTemplating; + +namespace LINGYUN.Abp.TextTemplating; + +public interface ITemplateDefinitionStoreCache +{ + string CacheStamp { get; set; } + + SemaphoreSlim SyncSemaphore { get; } + + DateTime? LastCheckTime { get; set; } + + Task FillAsync( + List templateDefinitionRecords, + IReadOnlyList templateDefinitions); + + TemplateDefinition GetOrNull(string name); + + IReadOnlyList GetAll(); +} diff --git a/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Domain/LINGYUN/Abp/TextTemplating/ITextTemplateDefinitionRepository.cs b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Domain/LINGYUN/Abp/TextTemplating/ITextTemplateDefinitionRepository.cs new file mode 100644 index 000000000..f46bb4108 --- /dev/null +++ b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Domain/LINGYUN/Abp/TextTemplating/ITextTemplateDefinitionRepository.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using Volo.Abp.Domain.Repositories; + +namespace LINGYUN.Abp.TextTemplating; +public interface ITextTemplateDefinitionRepository : IBasicRepository +{ + Task FindByNameAsync( + string name, + CancellationToken cancellationToken = default); + + Task GetCountAsync( + string filter = null, + CancellationToken cancellationToken = default); + + Task> GetListAsync( + string filter = null, + string sorting = nameof(TextTemplateDefinition.Name), + int skipCount = 0, + int maxResultCount = 10, + CancellationToken cancellationToken = default); +} diff --git a/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Domain/LINGYUN/Abp/TextTemplating/ITextTemplateDefinitionSerializer.cs b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Domain/LINGYUN/Abp/TextTemplating/ITextTemplateDefinitionSerializer.cs new file mode 100644 index 000000000..e00909333 --- /dev/null +++ b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Domain/LINGYUN/Abp/TextTemplating/ITextTemplateDefinitionSerializer.cs @@ -0,0 +1,12 @@ +using JetBrains.Annotations; +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; +using Volo.Abp.TextTemplating; + +namespace LINGYUN.Abp.TextTemplating; +public interface ITextTemplateDefinitionSerializer +{ + Task SerializeAsync(TemplateDefinition template); +} diff --git a/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Domain/LINGYUN/Abp/TextTemplating/InMemoryTemplateDefinitionStoreCache.cs b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Domain/LINGYUN/Abp/TextTemplating/InMemoryTemplateDefinitionStoreCache.cs new file mode 100644 index 000000000..c8ece18b5 --- /dev/null +++ b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Domain/LINGYUN/Abp/TextTemplating/InMemoryTemplateDefinitionStoreCache.cs @@ -0,0 +1,86 @@ +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Threading; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Localization; +using Volo.Abp.TextTemplating; + +namespace LINGYUN.Abp.TextTemplating; +public class InMemoryTemplateDefinitionStoreCache : ITemplateDefinitionStoreCache, ISingletonDependency +{ + public string CacheStamp { get; set; } + public SemaphoreSlim SyncSemaphore { get; } + public DateTime? LastCheckTime { get; set; } + + protected IDictionary TemplateDefinitions { get; } + + protected ILocalizableStringSerializer LocalizableStringSerializer { get; } + + public InMemoryTemplateDefinitionStoreCache(ILocalizableStringSerializer localizableStringSerializer) + { + LocalizableStringSerializer = localizableStringSerializer; + + SyncSemaphore = new(1, 1); + TemplateDefinitions = new ConcurrentDictionary(); + } + + public virtual Task FillAsync( + List templateDefinitionRecords, + IReadOnlyList templateDefinitions) + { + TemplateDefinitions.Clear(); + + foreach (var templateDefinitionRecord in templateDefinitionRecords) + { + var templateDefinition = new TemplateDefinition( + templateDefinitionRecord.Name, + typeof(NonTypedLocalizationResource), + LocalizableStringSerializer.Deserialize(templateDefinitionRecord.DisplayName), + templateDefinitionRecord.IsLayout, + templateDefinitionRecord.Layout, + templateDefinitionRecord.DefaultCultureName) + { + IsInlineLocalized = templateDefinitionRecord.IsInlineLocalized, + }; + if (!templateDefinitionRecord.RenderEngine.IsNullOrWhiteSpace()) + { + templateDefinition.WithRenderEngine(templateDefinitionRecord.RenderEngine); + } + foreach (var property in templateDefinitionRecord.ExtraProperties) + { + templateDefinition.WithProperty(property.Key, property.Value); + } + templateDefinition.WithProperty(nameof(TextTemplateDefinition.IsStatic), templateDefinitionRecord.IsStatic); + + TemplateDefinitions[templateDefinition.Name] = templateDefinition; + } + + foreach (var templateDefinition in templateDefinitions) + { + if (TemplateDefinitions.TryGetValue(templateDefinition.Name, out var inCacheTemplate)) + { + inCacheTemplate.WithProperty(nameof(TextTemplateDefinition.IsStatic), true); + } + else + { + templateDefinition.WithProperty(nameof(TextTemplateDefinition.IsStatic), true); + TemplateDefinitions[templateDefinition.Name] = templateDefinition; + } + } + + return Task.CompletedTask; + } + + public virtual TemplateDefinition GetOrNull(string name) + { + return TemplateDefinitions.GetOrDefault(name); + } + + public virtual IReadOnlyList GetAll() + { + return TemplateDefinitions.Values.ToImmutableList(); + } +} diff --git a/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Domain/LINGYUN/Abp/TextTemplating/StaticTemplateDefinitionSaver.cs b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Domain/LINGYUN/Abp/TextTemplating/StaticTemplateDefinitionSaver.cs new file mode 100644 index 000000000..2f669a19f --- /dev/null +++ b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Domain/LINGYUN/Abp/TextTemplating/StaticTemplateDefinitionSaver.cs @@ -0,0 +1,96 @@ +using Microsoft.Extensions.Options; +using System.Collections.Generic; +using System.Threading.Tasks; +using Volo.Abp.Caching; +using Volo.Abp.Data; +using Volo.Abp.DependencyInjection; +using Volo.Abp.DistributedLocking; +using Volo.Abp.Guids; +using Volo.Abp.Localization; +using Volo.Abp.TextTemplating; +using Volo.Abp.Uow; + +namespace LINGYUN.Abp.TextTemplating; + +public class StaticTemplateDefinitionSaver : IStaticTemplateDefinitionSaver, ITransientDependency +{ + protected AbpDistributedCacheOptions CacheOptions { get; } + protected IGuidGenerator GuidGenerator { get; } + protected IAbpDistributedLock DistributedLock { get; } + protected ITextTemplateDefinitionRepository TemplateDefinitionRepository { get; } + protected AbpTextTemplatingCachingOptions TemplatingCachingOptions { get; } + protected ITemplateDefinitionManager TemplateDefinitionManager { get; } + protected ILocalizableStringSerializer LocalizableStringSerializer { get; } + + public StaticTemplateDefinitionSaver( + IOptions cacheOptions, + IOptions templatingCachingOptions, + IGuidGenerator guidGenerator, + IAbpDistributedLock distributedLock, + ITextTemplateDefinitionRepository templateDefinitionRepository, + ITemplateDefinitionManager templateDefinitionManager, + ILocalizableStringSerializer localizableStringSerializer) + { + CacheOptions = cacheOptions.Value; + GuidGenerator = guidGenerator; + DistributedLock = distributedLock; + TemplateDefinitionRepository = templateDefinitionRepository; + TemplatingCachingOptions = templatingCachingOptions.Value; + TemplateDefinitionManager = templateDefinitionManager; + LocalizableStringSerializer = localizableStringSerializer; + } + + [UnitOfWork] + public async virtual Task SaveAsync() + { + if (TemplatingCachingOptions.SaveStaticTemplateDefinitionToDatabase) + { + await using var commonLockHandle = await DistributedLock + .TryAcquireAsync(GetCommonDistributedLockKey(), TemplatingCachingOptions.TemplateDefinitionsCacheStampTimeOut); + + if (commonLockHandle == null) + { + return; + } + + var templateDefinitions = TemplateDefinitionManager.GetAll(); + + var saveNewTemplateDefinitionRecords = new List(); + + foreach (var templateDefinition in templateDefinitions) + { + if (await TemplateDefinitionRepository.FindByNameAsync(templateDefinition.Name) != null) + { + continue; + } + + var templateDefinitionRecord = new TextTemplateDefinition( + GuidGenerator.Create(), + templateDefinition.Name, + LocalizableStringSerializer.Serialize(templateDefinition.DisplayName), + templateDefinition.IsLayout, + templateDefinition.Layout, + templateDefinition.IsInlineLocalized, + templateDefinition.DefaultCultureName, + templateDefinition.RenderEngine) + { + IsStatic = true + }; + + foreach (var property in templateDefinition.Properties) + { + templateDefinitionRecord.SetProperty(property.Key, property.Value); + } + + saveNewTemplateDefinitionRecords.Add(templateDefinitionRecord); + } + + await TemplateDefinitionRepository.InsertManyAsync(saveNewTemplateDefinitionRecords); + } + } + + protected virtual string GetCommonDistributedLockKey() + { + return $"{CacheOptions.KeyPrefix}_Common_AbpTemplateDefinitionStaticSaverLock"; + } +} diff --git a/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Domain/LINGYUN/Abp/TextTemplating/TemplateContentCacheItem.cs b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Domain/LINGYUN/Abp/TextTemplating/TemplateContentCacheItem.cs index 58a3c51ef..5916b1437 100644 --- a/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Domain/LINGYUN/Abp/TextTemplating/TemplateContentCacheItem.cs +++ b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Domain/LINGYUN/Abp/TextTemplating/TemplateContentCacheItem.cs @@ -1,5 +1,8 @@ -namespace LINGYUN.Abp.TextTemplating; +using System; +namespace LINGYUN.Abp.TextTemplating; + +[Serializable] public class TemplateContentCacheItem { private const string CacheKeyFormat = "pn:template-content,n:{0},c:{1}"; diff --git a/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Domain/LINGYUN/Abp/TextTemplating/TemplateDefinitionStore.cs b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Domain/LINGYUN/Abp/TextTemplating/TemplateDefinitionStore.cs new file mode 100644 index 000000000..89f05fe8c --- /dev/null +++ b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Domain/LINGYUN/Abp/TextTemplating/TemplateDefinitionStore.cs @@ -0,0 +1,209 @@ +using JetBrains.Annotations; +using Microsoft.Extensions.Caching.Distributed; +using Microsoft.Extensions.Options; +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using Volo.Abp; +using Volo.Abp.Caching; +using Volo.Abp.DependencyInjection; +using Volo.Abp.DistributedLocking; +using Volo.Abp.TextTemplating; +using Volo.Abp.Threading; + +namespace LINGYUN.Abp.TextTemplating; + +public class TemplateDefinitionStore : ITemplateDefinitionStore, ITransientDependency +{ + protected AbpDistributedCacheOptions CacheOptions { get; } + protected AbpTextTemplatingCachingOptions TemplatingCachingOptions { get; } + protected IAbpDistributedLock DistributedLock { get; } + protected IDistributedCache DistributedCache { get; } + protected ITextTemplateDefinitionRepository TextTemplateDefinitionRepository { get; } + protected ITemplateDefinitionManager TemplateDefinitionManager { get; } + protected ITemplateDefinitionStoreCache TemplateDefinitionStoreCache { get; } + + public TemplateDefinitionStore( + IOptions cacheOptions, + IOptions templatingCachingOptions, + IAbpDistributedLock distributedLock, + IDistributedCache distributedCache, + ITextTemplateDefinitionRepository textTemplateDefinitionRepository, + ITemplateDefinitionManager templateDefinitionManager, + ITemplateDefinitionStoreCache templateDefinitionStoreCache) + { + CacheOptions = cacheOptions.Value; + TemplatingCachingOptions = templatingCachingOptions.Value; + DistributedLock = distributedLock; + DistributedCache = distributedCache; + TextTemplateDefinitionRepository = textTemplateDefinitionRepository; + TemplateDefinitionManager = templateDefinitionManager; + TemplateDefinitionStoreCache = templateDefinitionStoreCache; + } + + public async virtual Task CreateAsync(TextTemplateDefinition template) + { + await TextTemplateDefinitionRepository.InsertAsync(template); + + TemplateDefinitionStoreCache.LastCheckTime = DateTime.Now; + } + + public async virtual Task UpdateAsync(TextTemplateDefinition template) + { + await TextTemplateDefinitionRepository.UpdateAsync(template); + + TemplateDefinitionStoreCache.LastCheckTime = DateTime.Now; + } + + public async virtual Task DeleteAsync(string name, CancellationToken cancellationToken = default) + { + if (!TemplatingCachingOptions.IsDynamicTemplateDefinitionStoreEnabled) + { + return; + } + + using (await TemplateDefinitionStoreCache.SyncSemaphore.LockAsync()) + { + var templateDefinitionRecord = await TextTemplateDefinitionRepository.FindByNameAsync(name); + if (templateDefinitionRecord != null) + { + await TextTemplateDefinitionRepository.DeleteAsync(templateDefinitionRecord); + // 及时更新便于下次检索刷新缓存 + TemplateDefinitionStoreCache.LastCheckTime = DateTime.Now; + } + } + } + + public async virtual Task GetAsync([NotNull] string name, CancellationToken cancellationToken = default) + { + if (!TemplatingCachingOptions.IsDynamicTemplateDefinitionStoreEnabled) + { + return TemplateDefinitionManager.Get(name); + } + + using (await TemplateDefinitionStoreCache.SyncSemaphore.LockAsync()) + { + await EnsureCacheIsUptoDateAsync(); + + var templateDefinition = TemplateDefinitionStoreCache.GetOrNull(name); + templateDefinition ??= TemplateDefinitionManager.Get(name); + + return templateDefinition; + } + } + + public async virtual Task> GetAllAsync(CancellationToken cancellationToken = default) + { + if (!TemplatingCachingOptions.IsDynamicTemplateDefinitionStoreEnabled) + { + return TemplateDefinitionManager.GetAll(); + } + + using (await TemplateDefinitionStoreCache.SyncSemaphore.LockAsync()) + { + await EnsureCacheIsUptoDateAsync(); + + return TemplateDefinitionStoreCache.GetAll(); + } + } + + public async virtual Task GetOrNullAsync(string name, CancellationToken cancellationToken = default) + { + if (!TemplatingCachingOptions.IsDynamicTemplateDefinitionStoreEnabled) + { + return TemplateDefinitionManager.GetOrNull(name); + } + + using (await TemplateDefinitionStoreCache.SyncSemaphore.LockAsync()) + { + await EnsureCacheIsUptoDateAsync(); + + var templateDefinition = TemplateDefinitionStoreCache.GetOrNull(name); + + return templateDefinition; + } + } + + protected async virtual Task EnsureCacheIsUptoDateAsync() + { + if (TemplateDefinitionStoreCache.LastCheckTime.HasValue && + DateTime.Now.Subtract(TemplateDefinitionStoreCache.LastCheckTime.Value) < TemplatingCachingOptions.TemplateDefinitionsCacheRefreshInterval) + { + return; + } + + var stampInDistributedCache = await GetOrSetStampInDistributedCache(); + + if (stampInDistributedCache == TemplateDefinitionStoreCache.CacheStamp) + { + TemplateDefinitionStoreCache.LastCheckTime = DateTime.Now; + return; + } + + await UpdateInMemoryStoreCache(); + + TemplateDefinitionStoreCache.CacheStamp = stampInDistributedCache; + TemplateDefinitionStoreCache.LastCheckTime = DateTime.Now; + } + + protected async virtual Task UpdateInMemoryStoreCache() + { + var templateDefinitions = TemplateDefinitionManager.GetAll(); + var textTemplateDefinitions = await TextTemplateDefinitionRepository.GetListAsync(includeDetails: false); + + await TemplateDefinitionStoreCache.FillAsync(textTemplateDefinitions, templateDefinitions); + } + + protected async virtual Task GetOrSetStampInDistributedCache() + { + var cacheKey = GetCommonStampCacheKey(); + + var stampInDistributedCache = await DistributedCache.GetStringAsync(cacheKey); + if (stampInDistributedCache != null) + { + return stampInDistributedCache; + } + + await using (var commonLockHandle = await DistributedLock + .TryAcquireAsync(GetCommonDistributedLockKey(), TemplatingCachingOptions.TemplateDefinitionsCacheStampTimeOut)) + { + if (commonLockHandle == null) + { + /* This request will fail */ + throw new AbpException( + "Could not acquire distributed lock for template definition common stamp check!" + ); + } + + stampInDistributedCache = await DistributedCache.GetStringAsync(cacheKey); + if (stampInDistributedCache != null) + { + return stampInDistributedCache; + } + + stampInDistributedCache = Guid.NewGuid().ToString(); + + await DistributedCache.SetStringAsync( + cacheKey, + stampInDistributedCache, + new DistributedCacheEntryOptions + { + SlidingExpiration = TemplatingCachingOptions.TemplateDefinitionsCacheStampExpiration + } + ); + } + + return stampInDistributedCache; + } + + protected virtual string GetCommonStampCacheKey() + { + return $"{CacheOptions.KeyPrefix}_AbpInMemoryTemplateDefinitionCacheStamp"; + } + + protected virtual string GetCommonDistributedLockKey() + { + return $"{CacheOptions.KeyPrefix}_Common_AbpTemplateDefinitionUpdateLock"; + } +} diff --git a/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Domain/LINGYUN/Abp/TextTemplating/TextTemplateContentProvider.cs b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Domain/LINGYUN/Abp/TextTemplating/TextTemplateContentProvider.cs new file mode 100644 index 000000000..f668f214b --- /dev/null +++ b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Domain/LINGYUN/Abp/TextTemplating/TextTemplateContentProvider.cs @@ -0,0 +1,37 @@ +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; +using Volo.Abp.TextTemplating; + +namespace LINGYUN.Abp.TextTemplating; + +[Dependency(ReplaceServices = true)] +[ExposeServices( + typeof(ITemplateContentProvider), + typeof(TemplateContentProvider))] +public class TextTemplateContentProvider : TemplateContentProvider, ITransientDependency +{ + protected ITemplateDefinitionStore TemplateDefinitionStore { get; } + + public TextTemplateContentProvider( + ITemplateDefinitionManager templateDefinitionManager, + ITemplateDefinitionStore templateDefinitionStore, + IServiceScopeFactory serviceScopeFactory, + IOptions options) + : base(templateDefinitionManager, serviceScopeFactory, options) + { + TemplateDefinitionStore = templateDefinitionStore; + } + + public async override Task GetContentOrNullAsync( + string templateName, + string cultureName = null, + bool tryDefaults = true, + bool useCurrentCultureIfCultureNameIsNull = true) + { + var template = await TemplateDefinitionStore.GetAsync(templateName); + + return await GetContentOrNullAsync(template, cultureName); + } +} diff --git a/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Domain/LINGYUN/Abp/TextTemplating/TextTemplateDefinition.cs b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Domain/LINGYUN/Abp/TextTemplating/TextTemplateDefinition.cs new file mode 100644 index 000000000..1202ad4c5 --- /dev/null +++ b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Domain/LINGYUN/Abp/TextTemplating/TextTemplateDefinition.cs @@ -0,0 +1,41 @@ +using System; +using Volo.Abp; +using Volo.Abp.Data; +using Volo.Abp.Domain.Entities; + +namespace LINGYUN.Abp.TextTemplating; +public class TextTemplateDefinition : AggregateRoot, IHasExtraProperties +{ + public virtual string Name { get; protected set; } + public virtual string DisplayName { get; set; } + public virtual bool IsLayout { get; set; } + public virtual string Layout { get; set; } + public virtual bool IsInlineLocalized { get; set; } + public virtual string DefaultCultureName { get; set; } + public virtual string RenderEngine { get; set; } + public virtual bool IsStatic { get; set; } + protected TextTemplateDefinition() + { + + } + + public TextTemplateDefinition( + Guid id, + string name, + string displayName, + bool isLayout = false, + string layout = null, + bool isInlineLocalized = false, + string defaultCultureName = null, + string renderEngine = null) + : base(id) + { + Name = Check.NotNullOrWhiteSpace(name, nameof(name), TextTemplateDefinitionConsts.MaxNameLength); + DisplayName = Check.NotNullOrWhiteSpace(displayName, nameof(displayName), TextTemplateDefinitionConsts.MaxDisplayNameLength); + IsLayout = isLayout; + Layout = Check.Length(layout, nameof(layout), TextTemplateDefinitionConsts.MaxLayoutLength); + IsInlineLocalized = isInlineLocalized; + DefaultCultureName = Check.Length(defaultCultureName, nameof(defaultCultureName), TextTemplateDefinitionConsts.MaxDefaultCultureNameLength); + RenderEngine = Check.Length(renderEngine, nameof(renderEngine), TextTemplateDefinitionConsts.MaxRenderEngineLength); + } +} diff --git a/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Domain/LINGYUN/Abp/TextTemplating/TextTemplateDefinitionInitializer.cs b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Domain/LINGYUN/Abp/TextTemplating/TextTemplateDefinitionInitializer.cs new file mode 100644 index 000000000..e4e853623 --- /dev/null +++ b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Domain/LINGYUN/Abp/TextTemplating/TextTemplateDefinitionInitializer.cs @@ -0,0 +1,113 @@ +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; +using Polly; +using System; +using System.Threading; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Threading; + +namespace LINGYUN.Abp.TextTemplating; +public class TextTemplateDefinitionInitializer : ITransientDependency +{ + protected IRootServiceProvider RootServiceProvider { get; } + protected ICancellationTokenProvider CancellationTokenProvider { get; } + protected AbpTextTemplatingCachingOptions TextTemplatingCachingOptions { get; } + + public TextTemplateDefinitionInitializer( + IRootServiceProvider rootServiceProvider, + ICancellationTokenProvider cancellationTokenProvider, + IOptions textTemplatingCachingOptions) + { + RootServiceProvider = rootServiceProvider; + CancellationTokenProvider = cancellationTokenProvider; + TextTemplatingCachingOptions = textTemplatingCachingOptions.Value; + } + + public async virtual Task InitializeDynamicTemplates(CancellationToken cancellationToken) + { + if (!TextTemplatingCachingOptions.SaveStaticTemplateDefinitionToDatabase && !TextTemplatingCachingOptions.IsDynamicTemplateDefinitionStoreEnabled) + { + return; + } + + using var scope = RootServiceProvider.CreateScope(); + var applicationLifetime = scope.ServiceProvider.GetService(); + var token = applicationLifetime?.ApplicationStopping ?? cancellationToken; + using (CancellationTokenProvider.Use(cancellationToken)) + { + if (CancellationTokenProvider.Token.IsCancellationRequested) + { + return; + } + + await SaveStaticTemplateDefinitionsToDatabaseAsync(scope); + + if (CancellationTokenProvider.Token.IsCancellationRequested) + { + return; + } + + await PreCacheDynamicTemplateDefinitionsAsync(scope); + } + } + + private async Task SaveStaticTemplateDefinitionsToDatabaseAsync(IServiceScope serviceScope) + { + if (!TextTemplatingCachingOptions.SaveStaticTemplateDefinitionToDatabase) + { + return; + } + + await Policy + .Handle() + .WaitAndRetryAsync(8, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt) * 10)) + .ExecuteAsync(async _ => + { + try + { + // ReSharper disable once AccessToDisposedClosure + var saver = serviceScope.ServiceProvider.GetRequiredService(); + + await saver.SaveAsync(); + } + catch (Exception ex) + { + // ReSharper disable once AccessToDisposedClosure + serviceScope.ServiceProvider + .GetService>()? + .LogException(ex); + + throw; // Polly will catch it + } + }, CancellationTokenProvider.Token); + + } + + private async Task PreCacheDynamicTemplateDefinitionsAsync(IServiceScope serviceScope) + { + if (!TextTemplatingCachingOptions.IsDynamicTemplateDefinitionStoreEnabled) + { + return; + } + + try + { + // ReSharper disable once AccessToDisposedClosure + var store = serviceScope.ServiceProvider.GetRequiredService(); + + await store.GetAllAsync(); + } + catch (Exception ex) + { + // ReSharper disable once AccessToDisposedClosure + serviceScope.ServiceProvider + .GetService>()? + .LogException(ex); + + throw; // Polly will catch it + } + } +} diff --git a/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Domain/LINGYUN/Abp/TextTemplating/TextTemplateRenderer.cs b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Domain/LINGYUN/Abp/TextTemplating/TextTemplateRenderer.cs new file mode 100644 index 000000000..57f39bf4d --- /dev/null +++ b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Domain/LINGYUN/Abp/TextTemplating/TextTemplateRenderer.cs @@ -0,0 +1,57 @@ +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Volo.Abp; +using Volo.Abp.DependencyInjection; +using Volo.Abp.TextTemplating; + +namespace LINGYUN.Abp.TextTemplating; + +[Dependency(ReplaceServices = true)] +[ExposeServices( + typeof(ITemplateRenderer), + typeof(AbpTemplateRenderer))] +public class TextTemplateRenderer : AbpTemplateRenderer, ITransientDependency +{ + protected ITemplateDefinitionStore TemplateDefinitionStore { get; } + public TextTemplateRenderer( + IServiceScopeFactory serviceScopeFactory, + ITemplateDefinitionManager templateDefinitionManager, + ITemplateDefinitionStore templateDefinitionStore, + IOptions options) + : base(serviceScopeFactory, templateDefinitionManager, options) + { + TemplateDefinitionStore = templateDefinitionStore; + } + + public override async Task RenderAsync( + string templateName, + object model = null, + string cultureName = null, + Dictionary globalContext = null) + { + var templateDefinition = await TemplateDefinitionStore.GetAsync(templateName); + + var renderEngine = templateDefinition.RenderEngine; + + if (renderEngine.IsNullOrWhiteSpace()) + { + renderEngine = Options.DefaultRenderingEngine; + } + + var providerType = Options.RenderingEngines.GetOrDefault(renderEngine); + + if (providerType != null && typeof(ITemplateRenderingEngine).IsAssignableFrom(providerType)) + { + using (var scope = ServiceScopeFactory.CreateScope()) + { + var templateRenderingEngine = (ITemplateRenderingEngine)scope.ServiceProvider.GetRequiredService(providerType); + return await templateRenderingEngine.RenderAsync(templateName, model, cultureName, globalContext); + } + } + + throw new AbpException("There is no rendering engine found with template name: " + templateName); + } +} diff --git a/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.EntityFrameworkCore/LINGYUN/Abp/TextTemplating/AbpTextTemplatingDbContextModelCreatingExtensions.cs b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.EntityFrameworkCore/LINGYUN/Abp/TextTemplating/AbpTextTemplatingDbContextModelCreatingExtensions.cs index 3818f54e3..58fa36c01 100644 --- a/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.EntityFrameworkCore/LINGYUN/Abp/TextTemplating/AbpTextTemplatingDbContextModelCreatingExtensions.cs +++ b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.EntityFrameworkCore/LINGYUN/Abp/TextTemplating/AbpTextTemplatingDbContextModelCreatingExtensions.cs @@ -39,6 +39,34 @@ public static class AbpTextTemplatingDbContextModelCreatingExtensions b.ApplyObjectExtensionMappings(); }); + builder.Entity(b => + { + b.ToTable(AbpTextTemplatingDbProperties.DbTablePrefix + "TextTemplateDefinitions", AbpTextTemplatingDbProperties.DbSchema); + + b.ConfigureByConvention(); + + b.Property(t => t.Name) + .HasColumnName(nameof(TextTemplateDefinition.Name)) + .HasMaxLength(TextTemplateDefinitionConsts.MaxNameLength) + .IsRequired(); + b.Property(t => t.DisplayName) + .HasColumnName(nameof(TextTemplateDefinition.DisplayName)) + .HasMaxLength(TextTemplateDefinitionConsts.MaxDisplayNameLength) + .IsRequired(); + + b.Property(t => t.Layout) + .HasColumnName(nameof(TextTemplateDefinition.Layout)) + .HasMaxLength(TextTemplateDefinitionConsts.MaxLayoutLength); + b.Property(t => t.DefaultCultureName) + .HasColumnName(nameof(TextTemplateDefinition.DefaultCultureName)) + .HasMaxLength(TextTemplateDefinitionConsts.MaxDefaultCultureNameLength); + b.Property(t => t.RenderEngine) + .HasColumnName(nameof(TextTemplateDefinition.RenderEngine)) + .HasMaxLength(TextTemplateDefinitionConsts.MaxRenderEngineLength); + + b.ApplyObjectExtensionMappings(); + }); + builder.TryConfigureObjectExtensions(); } } diff --git a/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.EntityFrameworkCore/LINGYUN/Abp/TextTemplating/AbpTextTemplatingEntityFrameworkCoreModule.cs b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.EntityFrameworkCore/LINGYUN/Abp/TextTemplating/AbpTextTemplatingEntityFrameworkCoreModule.cs index f6f308316..56fa0f593 100644 --- a/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.EntityFrameworkCore/LINGYUN/Abp/TextTemplating/AbpTextTemplatingEntityFrameworkCoreModule.cs +++ b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.EntityFrameworkCore/LINGYUN/Abp/TextTemplating/AbpTextTemplatingEntityFrameworkCoreModule.cs @@ -14,6 +14,7 @@ public class AbpTextTemplatingEntityFrameworkCoreModule : AbpModule context.Services.AddAbpDbContext(options => { options.AddRepository(); + options.AddRepository(); options.AddDefaultRepositories(); }); diff --git a/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.EntityFrameworkCore/LINGYUN/Abp/TextTemplating/EfCoreTextTemplateDefinitionRepository.cs b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.EntityFrameworkCore/LINGYUN/Abp/TextTemplating/EfCoreTextTemplateDefinitionRepository.cs new file mode 100644 index 000000000..714bcafaa --- /dev/null +++ b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.EntityFrameworkCore/LINGYUN/Abp/TextTemplating/EfCoreTextTemplateDefinitionRepository.cs @@ -0,0 +1,55 @@ +using LINGYUN.Abp.TextTemplating.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Dynamic.Core; +using System.Threading; +using System.Threading.Tasks; +using Volo.Abp.Domain.Repositories.EntityFrameworkCore; +using Volo.Abp.EntityFrameworkCore; + +namespace LINGYUN.Abp.TextTemplating; +public class EfCoreTextTemplateDefinitionRepository : EfCoreRepository, ITextTemplateDefinitionRepository +{ + public EfCoreTextTemplateDefinitionRepository( + IDbContextProvider dbContextProvider) + : base(dbContextProvider) + { + } + + public async virtual Task FindByNameAsync(string name, CancellationToken cancellationToken = default) + { + return await (await GetDbSetAsync()) + .Where(x => x.Name == name) + .FirstOrDefaultAsync(GetCancellationToken(cancellationToken)); + } + + public async virtual Task GetCountAsync(string filter = null, CancellationToken cancellationToken = default) + { + return await (await GetDbSetAsync()) + .WhereIf(!filter.IsNullOrWhiteSpace(), x => x.Name.Contains(filter) || + x.DefaultCultureName.Contains(filter) || x.Layout.Contains(filter)) + .CountAsync(GetCancellationToken(cancellationToken)); + } + + public async virtual Task> GetListAsync( + string filter = null, + string sorting = "Name", + int skipCount = 0, + int maxResultCount = 10, + CancellationToken cancellationToken = default) + { + if (sorting.IsNullOrWhiteSpace()) + { + sorting = nameof(TextTemplateDefinition.Name); + } + + return await (await GetDbSetAsync()) + .WhereIf(!filter.IsNullOrWhiteSpace(), x => x.Name.Contains(filter) || + x.DefaultCultureName.Contains(filter) || x.Layout.Contains(filter)) + .OrderBy(sorting) + .PageBy(skipCount, maxResultCount) + .ToListAsync(GetCancellationToken(cancellationToken)); + } +} diff --git a/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.EntityFrameworkCore/LINGYUN/Abp/TextTemplating/ITextTemplatingDbContext.cs b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.EntityFrameworkCore/LINGYUN/Abp/TextTemplating/ITextTemplatingDbContext.cs index dab92e53e..cf66cb69e 100644 --- a/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.EntityFrameworkCore/LINGYUN/Abp/TextTemplating/ITextTemplatingDbContext.cs +++ b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.EntityFrameworkCore/LINGYUN/Abp/TextTemplating/ITextTemplatingDbContext.cs @@ -10,4 +10,6 @@ namespace LINGYUN.Abp.TextTemplating.EntityFrameworkCore; public interface ITextTemplatingDbContext : IEfCoreDbContext { DbSet TextTemplates { get; } + + DbSet TextTemplateDefinitions { get; } } diff --git a/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.EntityFrameworkCore/LINGYUN/Abp/TextTemplating/TextTemplatingDbContext.cs b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.EntityFrameworkCore/LINGYUN/Abp/TextTemplating/TextTemplatingDbContext.cs index 120b0527f..97d6a501b 100644 --- a/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.EntityFrameworkCore/LINGYUN/Abp/TextTemplating/TextTemplatingDbContext.cs +++ b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.EntityFrameworkCore/LINGYUN/Abp/TextTemplating/TextTemplatingDbContext.cs @@ -11,6 +11,8 @@ public class TextTemplatingDbContext : AbpDbContext, IT { public DbSet TextTemplates { get; set; } + public DbSet TextTemplateDefinitions { get; set; } + public TextTemplatingDbContext(DbContextOptions options) : base(options) { diff --git a/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.HttpApi/LINGYUN/Abp/TextTemplating/TextTemplateContentController.cs b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.HttpApi/LINGYUN/Abp/TextTemplating/TextTemplateContentController.cs new file mode 100644 index 000000000..f1160568c --- /dev/null +++ b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.HttpApi/LINGYUN/Abp/TextTemplating/TextTemplateContentController.cs @@ -0,0 +1,45 @@ +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using System.Threading.Tasks; +using Volo.Abp; + +namespace LINGYUN.Abp.TextTemplating; + +[Controller] +[Authorize(AbpTextTemplatingPermissions.TextTemplateContent.Default)] +[RemoteService(Name = AbpTextTemplatingRemoteServiceConsts.RemoteServiceName)] +[Area(AbpTextTemplatingRemoteServiceConsts.ModuleName)] +[Route("api/text-templating/templates/content")] +public class TextTemplateContentController : AbpTextTemplatingControllerBase, ITextTemplateContentAppService +{ + private readonly ITextTemplateContentAppService _service; + + public TextTemplateContentController(ITextTemplateContentAppService service) + { + _service = service; + } + + [HttpGet] + [Route("{Name}")] + [Route("{Culture}/{Name}")] + public virtual Task GetAsync(TextTemplateContentGetInput input) + { + return _service.GetAsync(input); + } + + [HttpPut] + [Route("{name}/restore-to-default")] + [Authorize(AbpTextTemplatingPermissions.TextTemplateContent.Delete)] + public virtual Task RestoreToDefaultAsync(string name, TextTemplateRestoreInput input) + { + return _service.RestoreToDefaultAsync(name, input); + } + + [HttpPut] + [Authorize(AbpTextTemplatingPermissions.TextTemplateContent.Update)] + [Route("{name}")] + public virtual Task UpdateAsync(string name, TextTemplateContentUpdateDto input) + { + return _service.UpdateAsync(name, input); + } +} diff --git a/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.HttpApi/LINGYUN/Abp/TextTemplating/TextTemplateController.cs b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.HttpApi/LINGYUN/Abp/TextTemplating/TextTemplateController.cs deleted file mode 100644 index ca4524ffa..000000000 --- a/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.HttpApi/LINGYUN/Abp/TextTemplating/TextTemplateController.cs +++ /dev/null @@ -1,59 +0,0 @@ -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Mvc; -using System.Threading.Tasks; -using Volo.Abp; -using Volo.Abp.Application.Dtos; - -namespace LINGYUN.Abp.TextTemplating; - -[Controller] -[Authorize(AbpTextTemplatingPermissions.TextTemplate.Default)] -[RemoteService(Name = AbpTextTemplatingRemoteServiceConsts.RemoteServiceName)] -[Area(AbpTextTemplatingRemoteServiceConsts.ModuleName)] -[Route("api/text-templating/templates")] -public class TextTemplateController : AbpTextTemplatingControllerBase, ITextTemplateAppService -{ - protected ITextTemplateAppService TextTemplateAppService { get; } - - public TextTemplateController( - ITextTemplateAppService textTemplateAppService) - { - TextTemplateAppService = textTemplateAppService; - } - - [HttpGet] - [Route("{name}")] - public virtual Task GetAsync(string name) - { - return TextTemplateAppService.GetAsync(name); - } - - [HttpGet] - [Route("content/{Name}")] - [Route("content/{Culture}/{Name}")] - public virtual Task GetContentAsync(TextTemplateContentGetInput input) - { - return TextTemplateAppService.GetContentAsync(input); - } - - [HttpGet] - public virtual Task> GetListAsync(TextTemplateDefinitionGetListInput input) - { - return TextTemplateAppService.GetListAsync(input); - } - - [HttpPut] - [Route("restore-to-default")] - [Authorize(AbpTextTemplatingPermissions.TextTemplate.Delete)] - public virtual Task RestoreToDefaultAsync(TextTemplateRestoreInput input) - { - return TextTemplateAppService.RestoreToDefaultAsync(input); - } - - [HttpPost] - [Authorize(AbpTextTemplatingPermissions.TextTemplate.Update)] - public virtual Task UpdateAsync(TextTemplateUpdateInput input) - { - return TextTemplateAppService.UpdateAsync(input); - } -} diff --git a/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.HttpApi/LINGYUN/Abp/TextTemplating/TextTemplateDefinitionController.cs b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.HttpApi/LINGYUN/Abp/TextTemplating/TextTemplateDefinitionController.cs new file mode 100644 index 000000000..b8d841c73 --- /dev/null +++ b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.HttpApi/LINGYUN/Abp/TextTemplating/TextTemplateDefinitionController.cs @@ -0,0 +1,58 @@ +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using System.Threading.Tasks; +using Volo.Abp; +using Volo.Abp.Application.Dtos; + +namespace LINGYUN.Abp.TextTemplating; + +[Controller] +[Authorize(AbpTextTemplatingPermissions.TextTemplateDefinition.Default)] +[RemoteService(Name = AbpTextTemplatingRemoteServiceConsts.RemoteServiceName)] +[Area(AbpTextTemplatingRemoteServiceConsts.ModuleName)] +[Route("api/text-templating/template/definitions")] +public class TextTemplateDefinitionController : AbpTextTemplatingControllerBase, ITextTemplateDefinitionAppService +{ + private readonly ITextTemplateDefinitionAppService _service; + + public TextTemplateDefinitionController(ITextTemplateDefinitionAppService service) + { + _service = service; + } + + [Authorize(AbpTextTemplatingPermissions.TextTemplateDefinition.Create)] + [HttpPost] + public virtual Task CreateAsync(TextTemplateDefinitionCreateDto input) + { + return _service.CreateAsync(input); + } + + [Authorize(AbpTextTemplatingPermissions.TextTemplateDefinition.Delete)] + [HttpDelete] + [Route("{name}")] + public virtual Task DeleteAsync(string name) + { + return _service.DeleteAsync(name); + } + + [HttpGet] + [Route("{name}")] + public virtual Task GetByNameAsync(string name) + { + return _service.GetByNameAsync(name); + } + + [HttpGet] + public virtual Task> GetListAsync(TextTemplateDefinitionGetListInput input) + { + return _service.GetListAsync(input); + } + + [Authorize(AbpTextTemplatingPermissions.TextTemplateDefinition.Update)] + [HttpPut] + [Route("{name}")] + public virtual Task UpdateAsync(string name, TextTemplateDefinitionUpdateDto input) + { + return _service.UpdateAsync(name, input); + } +} diff --git a/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Razor/FodyWeavers.xml b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Razor/FodyWeavers.xml new file mode 100644 index 000000000..ac6b5b292 --- /dev/null +++ b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Razor/FodyWeavers.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Razor/FodyWeavers.xsd b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Razor/FodyWeavers.xsd new file mode 100644 index 000000000..11da52550 --- /dev/null +++ b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Razor/FodyWeavers.xsd @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed. + + + + + A comma-separated list of error codes that can be safely ignored in assembly verification. + + + + + 'false' to turn off automatic generation of the XML Schema file. + + + + + \ No newline at end of file diff --git a/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Razor/LINGYUN.Abp.TextTemplating.Razor.csproj b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Razor/LINGYUN.Abp.TextTemplating.Razor.csproj new file mode 100644 index 000000000..0c4cc9212 --- /dev/null +++ b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Razor/LINGYUN.Abp.TextTemplating.Razor.csproj @@ -0,0 +1,19 @@ + + + + + + + netstandard2.0 + + + + + + + + + + + + diff --git a/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Razor/LINGYUN/Abp/TextTemplating/Razor/AbpTextTemplatingRazorModule.cs b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Razor/LINGYUN/Abp/TextTemplating/Razor/AbpTextTemplatingRazorModule.cs new file mode 100644 index 000000000..3f936fffe --- /dev/null +++ b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Razor/LINGYUN/Abp/TextTemplating/Razor/AbpTextTemplatingRazorModule.cs @@ -0,0 +1,30 @@ +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; +using System; +using Volo.Abp.Modularity; +using Volo.Abp.TextTemplating; +using Volo.Abp.TextTemplating.Razor; +using VoloAbpTextTemplatingRazorModule = Volo.Abp.TextTemplating.Razor.AbpTextTemplatingRazorModule; + +namespace LINGYUN.Abp.TextTemplating.Razor; + +[DependsOn( + typeof(AbpTextTemplatingDomainModule), + typeof(VoloAbpTextTemplatingRazorModule))] +public class AbpTextTemplatingRazorModule : AbpModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) + { + context.Services.Replace( + ServiceDescriptor.Transient()); + + Configure(options => + { + if (options.DefaultRenderingEngine.IsNullOrWhiteSpace()) + { + options.DefaultRenderingEngine = RazorTemplateRenderingEngine.EngineName; + } + options.RenderingEngines[RazorTemplateRenderingEngine.EngineName] = typeof(RazorTextTemplateRenderingEngine); + }); + } +} diff --git a/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Razor/LINGYUN/Abp/TextTemplating/Razor/RazorTextTemplateRenderingEngine.cs b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Razor/LINGYUN/Abp/TextTemplating/Razor/RazorTextTemplateRenderingEngine.cs new file mode 100644 index 000000000..374e085b0 --- /dev/null +++ b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Razor/LINGYUN/Abp/TextTemplating/Razor/RazorTextTemplateRenderingEngine.cs @@ -0,0 +1,48 @@ +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Localization; +using System.Collections.Generic; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; +using Volo.Abp.TextTemplating; +using Volo.Abp.TextTemplating.Razor; + +namespace LINGYUN.Abp.TextTemplating.Razor; +public class RazorTextTemplateRenderingEngine : RazorTemplateRenderingEngine, ITransientDependency +{ + protected ITemplateDefinitionStore TemplateDefinitionStore { get; } + + public RazorTextTemplateRenderingEngine( + IServiceScopeFactory serviceScopeFactory, + IAbpCompiledViewProvider abpCompiledViewProvider, + ITemplateDefinitionManager templateDefinitionManager, + ITemplateDefinitionStore templateDefinitionStore, + ITemplateContentProvider templateContentProvider, + IStringLocalizerFactory stringLocalizerFactory) + : base(serviceScopeFactory, abpCompiledViewProvider, templateDefinitionManager, templateContentProvider, stringLocalizerFactory) + { + TemplateDefinitionStore = templateDefinitionStore; + } + + protected async override Task RenderInternalAsync(string templateName, string body, Dictionary globalContext, object model = null) + { + var templateDefinition = await TemplateDefinitionStore.GetAsync(templateName); + + var renderedContent = await RenderSingleTemplateAsync( + templateDefinition, + body, + globalContext, + model + ); + + if (templateDefinition.Layout != null) + { + renderedContent = await RenderInternalAsync( + templateDefinition.Layout, + renderedContent, + globalContext + ); + } + + return renderedContent; + } +} diff --git a/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Scriban/FodyWeavers.xml b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Scriban/FodyWeavers.xml new file mode 100644 index 000000000..ac6b5b292 --- /dev/null +++ b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Scriban/FodyWeavers.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Scriban/FodyWeavers.xsd b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Scriban/FodyWeavers.xsd new file mode 100644 index 000000000..11da52550 --- /dev/null +++ b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Scriban/FodyWeavers.xsd @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed. + + + + + A comma-separated list of error codes that can be safely ignored in assembly verification. + + + + + 'false' to turn off automatic generation of the XML Schema file. + + + + + \ No newline at end of file diff --git a/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Scriban/LINGYUN.Abp.TextTemplating.Scriban.csproj b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Scriban/LINGYUN.Abp.TextTemplating.Scriban.csproj new file mode 100644 index 000000000..80a85ad29 --- /dev/null +++ b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Scriban/LINGYUN.Abp.TextTemplating.Scriban.csproj @@ -0,0 +1,19 @@ + + + + + + + netstandard2.0 + + + + + + + + + + + + diff --git a/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Scriban/LINGYUN/Abp/TextTemplating/Scriban/AbpTextTemplatingScribanModule.cs b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Scriban/LINGYUN/Abp/TextTemplating/Scriban/AbpTextTemplatingScribanModule.cs new file mode 100644 index 000000000..18e28909e --- /dev/null +++ b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Scriban/LINGYUN/Abp/TextTemplating/Scriban/AbpTextTemplatingScribanModule.cs @@ -0,0 +1,26 @@ +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; +using Volo.Abp.Modularity; +using Volo.Abp.TextTemplating; +using Volo.Abp.TextTemplating.Scriban; +using VoloAbpTextTemplatingScribanModule = Volo.Abp.TextTemplating.Scriban.AbpTextTemplatingScribanModule; + +namespace LINGYUN.Abp.TextTemplating.Scriban; + +[DependsOn( + typeof(AbpTextTemplatingDomainModule), + typeof(VoloAbpTextTemplatingScribanModule))] +public class AbpTextTemplatingScribanModule : AbpModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) + { + context.Services.Replace( + ServiceDescriptor.Transient()); + + Configure(options => + { + options.DefaultRenderingEngine = ScribanTemplateRenderingEngine.EngineName; + options.RenderingEngines[ScribanTemplateRenderingEngine.EngineName] = typeof(ScribanTextTemplateRenderingEngine); + }); + } +} diff --git a/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Scriban/LINGYUN/Abp/TextTemplating/Scriban/ScribanTextTemplateRenderingEngine.cs b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Scriban/LINGYUN/Abp/TextTemplating/Scriban/ScribanTextTemplateRenderingEngine.cs new file mode 100644 index 000000000..e632a9c97 --- /dev/null +++ b/aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Scriban/LINGYUN/Abp/TextTemplating/Scriban/ScribanTextTemplateRenderingEngine.cs @@ -0,0 +1,44 @@ +using Microsoft.Extensions.Localization; +using System.Collections.Generic; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; +using Volo.Abp.TextTemplating; +using Volo.Abp.TextTemplating.Scriban; + +namespace LINGYUN.Abp.TextTemplating.Scriban; + +public class ScribanTextTemplateRenderingEngine : ScribanTemplateRenderingEngine, ITransientDependency +{ + protected ITemplateDefinitionStore TemplateDefinitionStore { get; } + public ScribanTextTemplateRenderingEngine( + ITemplateDefinitionManager templateDefinitionManager, + ITemplateDefinitionStore templateDefinitionStore, + ITemplateContentProvider templateContentProvider, + IStringLocalizerFactory stringLocalizerFactory) + : base(templateDefinitionManager, templateContentProvider, stringLocalizerFactory) + { + TemplateDefinitionStore = templateDefinitionStore; + } + + protected async override Task RenderInternalAsync(string templateName, Dictionary globalContext, object model = null) + { + var templateDefinition = await TemplateDefinitionStore.GetAsync(templateName); + + var renderedContent = await RenderSingleTemplateAsync( + templateDefinition, + globalContext, + model + ); + + if (templateDefinition.Layout != null) + { + globalContext["content"] = renderedContent; + renderedContent = await RenderInternalAsync( + templateDefinition.Layout, + globalContext + ); + } + + return renderedContent; + } +} diff --git a/aspnet-core/services/LY.MicroService.BackendAdmin.HttpApi.Host/BackendAdminHttpApiHostModule.Configure.cs b/aspnet-core/services/LY.MicroService.BackendAdmin.HttpApi.Host/BackendAdminHttpApiHostModule.Configure.cs index 2b251c008..92546e12f 100644 --- a/aspnet-core/services/LY.MicroService.BackendAdmin.HttpApi.Host/BackendAdminHttpApiHostModule.Configure.cs +++ b/aspnet-core/services/LY.MicroService.BackendAdmin.HttpApi.Host/BackendAdminHttpApiHostModule.Configure.cs @@ -5,6 +5,7 @@ using LINGYUN.Abp.Localization.CultureMap; using LINGYUN.Abp.Saas; using LINGYUN.Abp.Serilog.Enrichers.Application; using LINGYUN.Abp.Serilog.Enrichers.UniqueId; +using LINGYUN.Abp.TextTemplating; using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Cors; using Microsoft.AspNetCore.DataProtection; @@ -90,6 +91,14 @@ public partial class BackendAdminHttpApiHostModule }); } + private void ConfigureTextTemplating() + { + Configure(options => + { + options.IsDynamicTemplateDefinitionStoreEnabled = true; + }); + } + private void ConfigureFeatureManagement() { Configure(options => diff --git a/aspnet-core/services/LY.MicroService.BackendAdmin.HttpApi.Host/BackendAdminHttpApiHostModule.cs b/aspnet-core/services/LY.MicroService.BackendAdmin.HttpApi.Host/BackendAdminHttpApiHostModule.cs index e5323d34b..bcdd76896 100644 --- a/aspnet-core/services/LY.MicroService.BackendAdmin.HttpApi.Host/BackendAdminHttpApiHostModule.cs +++ b/aspnet-core/services/LY.MicroService.BackendAdmin.HttpApi.Host/BackendAdminHttpApiHostModule.cs @@ -120,6 +120,7 @@ public partial class BackendAdminHttpApiHostModule : AbpModule ConfigureJsonSerializer(); ConfigureExceptionHandling(); ConfigureVirtualFileSystem(); + ConfigureTextTemplating(); ConfigureFeatureManagement(); ConfigurePermissionManagement(); ConfigureCaching(configuration); diff --git a/aspnet-core/services/LY.MicroService.BackendAdmin.HttpApi.Host/appsettings.Development.json b/aspnet-core/services/LY.MicroService.BackendAdmin.HttpApi.Host/appsettings.Development.json index a917bdb7e..80ee99743 100644 --- a/aspnet-core/services/LY.MicroService.BackendAdmin.HttpApi.Host/appsettings.Development.json +++ b/aspnet-core/services/LY.MicroService.BackendAdmin.HttpApi.Host/appsettings.Development.json @@ -29,15 +29,15 @@ } }, "ConnectionStrings": { - "Default": "Server=127.0.0.1;Database=Platform;User Id=root;Password=123456", - "AbpIdentity": "Server=127.0.0.1;Database=IdentityServer;User Id=root;Password=123456", - "AbpIdentityServer": "Server=127.0.0.1;Database=IdentityServer;User Id=root;Password=123456", - "AbpSaas": "Server=127.0.0.1;Database=Platform;User Id=root;Password=123456", - "AbpSettingManagement": "Server=127.0.0.1;Database=Platform;User Id=root;Password=123456", - "AbpFeatureManagement": "Server=127.0.0.1;Database=Platform;User Id=root;Password=123456", - "AbpPermissionManagement": "Server=127.0.0.1;Database=Platform;User Id=root;Password=123456", - "AbpLocalizationManagement": "Server=127.0.0.1;Database=Platform;User Id=root;Password=123456", - "AbpTextTemplating": "Server=127.0.0.1;Database=Platform;User Id=root;Password=123456" + "Default": "Server=127.0.0.1;Database=Platform-V70;User Id=root;Password=123456", + "AbpIdentity": "Server=127.0.0.1;Database=IdentityServer-V70;User Id=root;Password=123456", + "AbpIdentityServer": "Server=127.0.0.1;Database=IdentityServer-V70;User Id=root;Password=123456", + "AbpSaas": "Server=127.0.0.1;Database=Platform-V70;User Id=root;Password=123456", + "AbpSettingManagement": "Server=127.0.0.1;Database=Platform-V70;User Id=root;Password=123456", + "AbpFeatureManagement": "Server=127.0.0.1;Database=Platform-V70;User Id=root;Password=123456", + "AbpPermissionManagement": "Server=127.0.0.1;Database=Platform-V70;User Id=root;Password=123456", + "AbpLocalizationManagement": "Server=127.0.0.1;Database=Platform-V70;User Id=root;Password=123456", + "AbpTextTemplating": "Server=127.0.0.1;Database=Platform-V70;User Id=root;Password=123456" }, "CAP": { "EventBus": { diff --git a/aspnet-core/services/LY.MicroService.RealtimeMessage.HttpApi.Host/BackgroundJobs/NotificationPublishJob.cs b/aspnet-core/services/LY.MicroService.RealtimeMessage.HttpApi.Host/BackgroundJobs/NotificationPublishJob.cs index 8ade06248..8ea47d66d 100644 --- a/aspnet-core/services/LY.MicroService.RealtimeMessage.HttpApi.Host/BackgroundJobs/NotificationPublishJob.cs +++ b/aspnet-core/services/LY.MicroService.RealtimeMessage.HttpApi.Host/BackgroundJobs/NotificationPublishJob.cs @@ -12,13 +12,15 @@ public class NotificationPublishJob : AsyncBackgroundJob options, - IServiceScopeFactory serviceScopeFactory) + IServiceScopeFactory serviceScopeFactory, + INotificationDataSerializer notificationDataSerializer) { Options = options.Value; ServiceScopeFactory = serviceScopeFactory; + NotificationDataSerializer = notificationDataSerializer; } public override async Task ExecuteAsync(NotificationPublishJobArgs args) @@ -30,7 +32,7 @@ public class NotificationPublishJob : AsyncBackgroundJob(); var notification = await store.GetNotificationOrNullAsync(args.TenantId, args.NotificationId); - notification.Data = NotificationDataConverter.Convert(notification.Data); + notification.Data = NotificationDataSerializer.Serialize(notification.Data); var notifacationDataMapping = Options.NotificationDataMappings .GetMapItemOrDefault(notification.Name, publishProvider.Name); diff --git a/aspnet-core/services/LY.MicroService.RealtimeMessage.HttpApi.Host/EventBus/Distributed/NotificationEventHandler.cs b/aspnet-core/services/LY.MicroService.RealtimeMessage.HttpApi.Host/EventBus/Distributed/NotificationEventHandler.cs index 0c61e997a..8f08c603b 100644 --- a/aspnet-core/services/LY.MicroService.RealtimeMessage.HttpApi.Host/EventBus/Distributed/NotificationEventHandler.cs +++ b/aspnet-core/services/LY.MicroService.RealtimeMessage.HttpApi.Host/EventBus/Distributed/NotificationEventHandler.cs @@ -7,12 +7,14 @@ using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.Options; using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using System.Threading.Tasks; using Volo.Abp.BackgroundJobs; using Volo.Abp.DependencyInjection; using Volo.Abp.EventBus.Distributed; using Volo.Abp.Json; +using Volo.Abp.Localization; using Volo.Abp.MultiTenancy; using Volo.Abp.TextTemplating; using Volo.Abp.Uow; @@ -126,23 +128,31 @@ namespace LY.MicroService.RealtimeMessage.EventBus.Distributed return; } - if (notification.NotificationType == NotificationType.System) + var culture = eventData.Data.Culture; + if (culture.IsNullOrWhiteSpace()) { - using (CurrentTenant.Change(null)) + culture = CultureInfo.CurrentCulture.Name; + } + using (CultureHelper.Use(culture, culture)) + { + if (notification.NotificationType == NotificationType.System) { - await SendToTenantAsync(null, notification, eventData); + using (CurrentTenant.Change(null)) + { + await SendToTenantAsync(null, notification, eventData); - var allActiveTenants = await TenantConfigurationCache.GetTenantsAsync(); + var allActiveTenants = await TenantConfigurationCache.GetTenantsAsync(); - foreach (var activeTenant in allActiveTenants) - { - await SendToTenantAsync(activeTenant.Id, notification, eventData); + foreach (var activeTenant in allActiveTenants) + { + await SendToTenantAsync(activeTenant.Id, notification, eventData); + } } } - } - else - { - await SendToTenantAsync(eventData.TenantId, notification, eventData); + else + { + await SendToTenantAsync(eventData.TenantId, notification, eventData); + } } } @@ -234,7 +244,7 @@ namespace LY.MicroService.RealtimeMessage.EventBus.Distributed var notificationData = new NotificationData(); notificationData.WriteStandardData( - title: title, + title: title.ToString(), message: message, createTime: eventData.CreationTime, formUser: eventData.Data.FormUser); diff --git a/gateways/Directory.Build.props b/gateways/Directory.Build.props index 0357e352e..f20a1c60c 100644 --- a/gateways/Directory.Build.props +++ b/gateways/Directory.Build.props @@ -1,8 +1,8 @@  - 7.0.1 - 7.0.1 - 1.8.0 + 7.0.2 + 7.0.2 + 1.10.0 7.0.2 1.5.10 2.13.0 @@ -23,7 +23,7 @@ 8.4.1 5.0.0 6.1.5 - 6.0.* + 7.0.* 2.4.1 3.0.2 4.2.1 diff --git a/gateways/common.props b/gateways/common.props index 3d27dce88..a75e6e3c3 100644 --- a/gateways/common.props +++ b/gateways/common.props @@ -1,7 +1,7 @@ latest - 7.0.1 + 7.0.2 colin $(NoWarn);CS1591;CS0436;CS8618;NU1803 https://github.com/colinin/abp-next-admin