Browse Source

feat(openiddict): provides the application management ui

pull/812/head
cKey 3 years ago
parent
commit
b9baa86f0a
  1. 2
      apps/vue/.env.development
  2. 10
      apps/vue/build/utils.ts
  3. 2
      apps/vue/src/api/openiddict/open-iddict-application/model/index.ts
  4. 2
      apps/vue/src/api/openiddict/open-iddict-scope/model/index.ts
  5. 17
      apps/vue/src/api/oss-management/oss.ts
  6. 2
      apps/vue/src/api/sys/user.ts
  7. 9
      apps/vue/src/layouts/default/setting/components/SettingFooter.vue
  8. 14
      apps/vue/src/store/modules/user.ts
  9. 5
      apps/vue/src/utils/http/abp/abp.ts
  10. 397
      apps/vue/src/views/openiddict/applications/components/ApplicationModal.vue
  11. 68
      apps/vue/src/views/openiddict/applications/components/ApplicationScope.vue
  12. 42
      apps/vue/src/views/openiddict/applications/components/ApplicationTable.vue
  13. 60
      apps/vue/src/views/openiddict/applications/components/PostLogoutRedirectUri.vue
  14. 60
      apps/vue/src/views/openiddict/applications/components/RedirectUri.vue
  15. 18
      apps/vue/src/views/openiddict/applications/types/props.ts
  16. 133
      apps/vue/src/views/openiddict/components/DisplayNames/DisplayNameForm.vue
  17. 41
      apps/vue/src/views/openiddict/components/Permissions/PermissionForm.vue
  18. 120
      apps/vue/src/views/openiddict/components/Properties/PropertyForm.vue
  19. 124
      apps/vue/src/views/openiddict/components/Uris/UriForm.vue
  20. 10
      aspnet-core/modules/localization/LINGYUN.Abp.AspNetCore.Mvc.Localization/LINGYUN/Abp/AspNetCore/Mvc/Localization/TextAppService.cs
  21. 14
      aspnet-core/modules/lt/LINGYUN.Abp.LocalizationManagement.Domain/LINGYUN/Abp/LocalizationManagement/LocalizationStoreInMemoryCache.cs
  22. 6
      aspnet-core/modules/openIddict/LINGYUN.Abp.OpenIddict.Application.Contracts/LINGYUN/Abp/OpenIddict/Applications/OpenIddictApplicationCreateDto.cs
  23. 4
      aspnet-core/modules/openIddict/LINGYUN.Abp.OpenIddict.Application.Contracts/LINGYUN/Abp/OpenIddict/Applications/OpenIddictApplicationCreateOrUpdateDto.cs
  24. 4
      aspnet-core/modules/openIddict/LINGYUN.Abp.OpenIddict.Application.Contracts/LINGYUN/Abp/OpenIddict/Applications/OpenIddictApplicationDto.cs
  25. 4
      aspnet-core/modules/openIddict/LINGYUN.Abp.OpenIddict.Application.Contracts/LINGYUN/Abp/OpenIddict/Applications/OpenIddictApplicationUpdateDto.cs
  26. 4
      aspnet-core/modules/openIddict/LINGYUN.Abp.OpenIddict.Application.Contracts/LINGYUN/Abp/OpenIddict/Authorizations/OpenIddictAuthorizationDto.cs
  27. 28
      aspnet-core/modules/openIddict/LINGYUN.Abp.OpenIddict.Application.Contracts/LINGYUN/Abp/OpenIddict/Localization/Resources/en.json
  28. 28
      aspnet-core/modules/openIddict/LINGYUN.Abp.OpenIddict.Application.Contracts/LINGYUN/Abp/OpenIddict/Localization/Resources/zh-Hans.json
  29. 14
      aspnet-core/modules/openIddict/LINGYUN.Abp.OpenIddict.Application.Contracts/LINGYUN/Abp/OpenIddict/OpenIddictApplicationErrorCodes.cs
  30. 5
      aspnet-core/modules/openIddict/LINGYUN.Abp.OpenIddict.Application.Contracts/LINGYUN/Abp/OpenIddict/Scopes/OpenIddictScopeDto.cs
  31. 4
      aspnet-core/modules/openIddict/LINGYUN.Abp.OpenIddict.Application.Contracts/LINGYUN/Abp/OpenIddict/Scopes/OpenIddictScopeUpdateDto.cs
  32. 5
      aspnet-core/modules/openIddict/LINGYUN.Abp.OpenIddict.Application.Contracts/LINGYUN/Abp/OpenIddict/Tokens/OpenIddictTokenDto.cs
  33. 55
      aspnet-core/modules/openIddict/LINGYUN.Abp.OpenIddict.Application/LINGYUN/Abp/OpenIddict/Applications/OpenIddictApplicationAppService.cs
  34. 1
      aspnet-core/modules/openIddict/LINGYUN.Abp.OpenIddict.Application/LINGYUN/Abp/OpenIddict/Applications/OpenIddictApplicationExtensions.cs
  35. 26
      aspnet-core/modules/openIddict/LINGYUN.Abp.OpenIddict.Application/LINGYUN/Abp/OpenIddict/Authorizations/OpenIddictAuthorizationAppService.cs
  36. 41
      aspnet-core/modules/openIddict/LINGYUN.Abp.OpenIddict.Application/LINGYUN/Abp/OpenIddict/Scopes/OpenIddictScopeAppService.cs
  37. 30
      aspnet-core/modules/openIddict/LINGYUN.Abp.OpenIddict.Application/LINGYUN/Abp/OpenIddict/Tokens/OpenIddictTokenAppService.cs
  38. 7
      aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Domain/LINGYUN/Abp/TextTemplating/TemplateDefinitionStoreCacheInvalidator.cs
  39. 2
      aspnet-core/services/LY.MicroService.Applications.Single/MicroServiceApplicationsSingleModule.Configure.cs
  40. 2
      aspnet-core/services/LY.MicroService.Applications.Single/appsettings.Development.json

2
apps/vue/.env.development

@ -26,5 +26,5 @@ VITE_GLOB_MULTITENANCY_KEY='__tenant'
# STS Connect
VITE_GLOB_AUTHORITY='http://127.0.0.1:44385'
VITE_GLOB_CLIENT_ID='vue-admin-element'
VITE_GLOB_CLIENT_ID='vue-admin-client'
VITE_GLOB_CLIENT_SECRET='1q2w3e*'

10
apps/vue/build/utils.ts

@ -36,11 +36,11 @@ export function wrapperEnv(envConf: Recordable): ViteEnv {
}
}
ret[envName] = realName;
if (typeof realName === 'string') {
process.env[envName] = realName;
} else if (typeof realName === 'object') {
process.env[envName] = JSON.stringify(realName);
}
// if (typeof realName === 'string') {
// process.env[envName] = realName;
// } else if (typeof realName === 'object') {
// process.env[envName] = JSON.stringify(realName);
// }
}
return ret;
}

2
apps/vue/src/api/openiddict/open-iddict-application/model/index.ts

@ -9,7 +9,7 @@ export interface OpenIddictApplicationUpdateDto extends OpenIddictApplicationCre
}
export interface OpenIddictApplicationDto extends ExtensibleAuditedEntityDto<string> {
clientId?: string;
clientId: string;
clientSecret?: string;
consentType?: string;
displayName?: string;

2
apps/vue/src/api/openiddict/open-iddict-scope/model/index.ts

@ -23,7 +23,7 @@ export interface OpenIddictScopeDto extends ExtensibleAuditedEntityDto<string> {
descriptions?: Dictionary<string, string>;
displayName?: string;
displayNames?: Dictionary<string, string>;
name?: string;
name: string;
properties?: Dictionary<string, string>;
resources?: string[];
}

17
apps/vue/src/api/oss-management/oss.ts

@ -14,6 +14,7 @@ import { format } from '/@/utils/strings';
import { AxiosResponse } from 'axios';
import { isFunction } from '/@/utils/is';
import { UploadFileParams } from '/#/axios';
import { useAbpStoreWithOut } from '/@/store/modules/abp';
enum Api {
CreateObject = '/api/oss-management/objects',
@ -73,7 +74,7 @@ export const uploadObject = (params: UploadFileParams, event: any) => {
// 已完成大小
let loadedSize = 0;
// 返回包装的结果
return new Promise<AxiosResponse<void>>(async (resolve, reject) => {
return new Promise<AxiosResponse<any>>(async (resolve, reject) => {
function onPregress(progress: number, res: AxiosResponse) {
// 回调上传进度
if (isFunction(event)) {
@ -84,8 +85,20 @@ export const uploadObject = (params: UploadFileParams, event: any) => {
}
if (progress === totalSize) {
if (!res.data) {
let formatUrl = '/api/files/static/{bucket}/p/{path}/{name}';
const abpStore = useAbpStoreWithOut();
const { currentTenant } = abpStore.getApplication;
if (currentTenant.id) {
formatUrl = '/api/files/static/t/{tenantId}/{bucket}/p/{path}/{name}';
}
const path = encodeURIComponent(params.data?.path);
res.data = {
url: format('/api/files/static/{bucket}/p/{path}/{name}', { bucket: params.data?.bucket, path: params.data?.path, name: fileName }),
url: format(formatUrl, {
bucket: params.data?.bucket,
tenantId: currentTenant.id,
path: path,
name: fileName,
}),
};
}
resolve(res);

2
apps/vue/src/api/sys/user.ts

@ -33,6 +33,7 @@ export function loginApi(params: LoginParams, mode: ErrorMessageMode = 'modal')
grant_type: 'password',
username: params.username,
password: params.password,
scope: 'openid email address phone profile offline_access lingyun-abp-application',
TwoFactorProvider: params.twoFactorProvider,
TwoFactorCode: params.twoFactorCode,
};
@ -47,6 +48,7 @@ export function loginApi(params: LoginParams, mode: ErrorMessageMode = 'modal')
{
errorMessageMode: mode,
apiUrl: '/connect',
withToken: false,
},
);
}

9
apps/vue/src/layouts/default/setting/components/SettingFooter.vue

@ -38,9 +38,10 @@
import { updateColorWeak } from '/@/logics/theme/updateColorWeak';
import { updateGrayMode } from '/@/logics/theme/updateGrayMode';
import { changeTheme } from '/@/logics/theme';
import defaultSetting from '/@/settings/projectSetting';
import { changeTheme } from '/@/api/sys/theme';
import { changeTheme as changeThemeApi } from '/@/api/sys/theme';
import { ThemeSetting } from '/@/api/sys/model/themeModel';
export default defineComponent({
@ -69,8 +70,8 @@
function handleResetSetting() {
try {
appStore.setProjectConfig(defaultSetting);
const { colorWeak, grayMode } = defaultSetting;
// updateTheme(themeColor);
const { colorWeak, grayMode, themeColor } = defaultSetting;
changeTheme(themeColor);
updateColorWeak(colorWeak);
updateGrayMode(grayMode);
createMessage.success(t('layout.setting.resetSuccess'));
@ -96,7 +97,7 @@
};
syncLoading.value = true;
changeTheme(themeSetting)
changeThemeApi(themeSetting)
.then(() => {
createMessage.success(t('layout.setting.operatingTitle'));
})

14
apps/vue/src/store/modules/user.ts

@ -173,7 +173,7 @@ export const useUserStore = defineStore({
const abpStore = useAbpStoreWithOut();
let currentUser = abpStore.getApplication.currentUser;
// 避免多次请求接口
if (userInfo.sub !== currentUser.id) {
if (userInfo?.sub !== currentUser.id) {
await abpStore.initlizeAbpApplication();
currentUser = abpStore.getApplication.currentUser;
}
@ -184,13 +184,13 @@ export const useUserStore = defineStore({
username: currentUser.userName,
roles: currentUser.roles,
// 从 userinfo 端点获取
realName: userInfo.nickname,
phoneNumber: userInfo.phone_number,
phoneNumberConfirmed: userInfo.phone_number_verified === 'True',
email: userInfo.email,
emailConfirmed: userInfo.email_verified === 'True',
realName: userInfo?.nickname,
phoneNumber: userInfo?.phone_number,
phoneNumberConfirmed: userInfo?.phone_number_verified === 'True',
email: userInfo?.email,
emailConfirmed: userInfo?.email_verified === 'True',
};
if (userInfo.avatarUrl) {
if (userInfo?.avatarUrl) {
outgoingUserInfo.avatar = formatUrl(userInfo.avatarUrl);
}
this.setUserInfo(outgoingUserInfo);

5
apps/vue/src/utils/http/abp/abp.ts

@ -8,7 +8,6 @@ import {
ModuleApiDescriptionModel,
} from '/@/api/abp/model/apiDefinition';
import { ParameterBindingSources, UrlBuilder } from '/@/utils/helper/abpApiHelper';
import { ListResultDto, PagedResultDto } from '/@/api/model/baseModel';
import { useI18n } from '/@/hooks/web/useI18n';
import { useMessage } from '/@/hooks/web/useMessage';
@ -26,7 +25,7 @@ export class abpRequest {
uniqueName?: string;
data?: any;
params?: any;
}) {
}): Promise<PagedResultDto<TResult>> {
return this.request<PagedResultDto<TResult>>(options);
}
@ -37,7 +36,7 @@ export class abpRequest {
uniqueName?: string;
data?: any;
params?: any;
}) {
}): Promise<ListResultDto<TResult>> {
return this.request<ListResultDto<TResult>>(options);
}

397
apps/vue/src/views/openiddict/applications/components/ApplicationModal.vue

@ -1,29 +1,408 @@
<template>
<BasicModal
@register="registerModal"
:title="title"
:title="L('Applications')"
:can-fullscreen="false"
:show-ok-btn="false"
:width="800"
:height="500"
:close-func="handleBeforeClose"
@ok="handleSubmit"
>
<Form
ref="formRef"
:model="state.application"
:rules="state.formRules"
:label-col="{ span: 6 }"
:wrapper-col="{ span: 18 }"
>
<Tabs v-model:active-key="state.activeTab" @change="handleTabChange">
<!-- Basic -->
<TabPane key="basic" :tab="L('BasicInfo')">
<FormItem name="clientId" :label="L('DisplayName:ClientId')">
<Input :disabled="state.isEdit" v-model:value="state.application.clientId" />
</FormItem>
<FormItem name="type" :label="L('DisplayName:Type')">
<Input v-model:value="state.application.type" />
</FormItem>
<FormItem name="clientUri" :label="L('DisplayName:ClientUri')">
<Input v-model:value="state.application.clientUri" />
</FormItem>
<FormItem name="logoUri" :label="L('DisplayName:LogoUri')">
<Input v-model:value="state.application.logoUri" />
</FormItem>
<FormItem
name="consentType"
:label="L('DisplayName:ConsentType')"
:label-col="{ span: 4 }"
:wrapper-col="{ span: 20 }"
>
<Select :options="consentTypes" v-model:value="state.application.consentType" />
</FormItem>
</TabPane>
<!-- DisplayName -->
<TabPane key="displayName" :tab="L('DisplayNames')">
<FormItem name="displayName" :label="L('DisplayName:DefaultDisplayName')">
<Input v-model:value="state.application.displayName" />
</FormItem>
<DisplayNameForm
:displayNames="state.application.displayNames"
@create="handleNewDisplayName"
@delete="handleDelDisplayName"
/>
</TabPane>
<!-- Endpoints -->
<TabPane key="endpoints">
<template #tab>
<Dropdown>
<span
>{{ L('Endpoints') }}
<DownOutlined />
</span>
<template #overlay>
<Menu @click="handleClickUrisMenu">
<MenuItem
key="redirectUris"
>
{{ L('DisplayName:RedirectUris') }}
</MenuItem>
<MenuItem
key="postLogoutRedirectUris"
>
{{ L('DisplayName:PostLogoutRedirectUris') }}
</MenuItem>
</Menu>
</template>
</Dropdown>
</template>
<component
:is="componentsRef[state.endPoint.component]"
:uris="state.endPoint.uris"
@create-redirect-uri="handleNewRedirectUri"
@delete-redirect-uri="handleDelRedirectUri"
@create-logout-uri="handleNewLogoutUri"
@delete-logout-uri="handleDelLogoutUri"
/>
</TabPane>
<!-- Scopes -->
<TabPane key="permissions" :tab="L('Scopes')">
<ApplicationScope
:scopes="state.application.scopes"
:support-scopes="state.openIdConfiguration?.scopes_supported"
@create="handleNewScope"
@delete="handleDelScope"
/>
</TabPane>
<!-- Authorizations -->
<TabPane key="authorizations" :tab="L('Authorizations')">
<FormItem
name="endpoints"
:label="L('DisplayName:Endpoints')"
:label-col="{ span: 4 }"
:wrapper-col="{ span: 20 }"
>
<Select :options="endpoints" mode="tags" v-model:value="state.application.endpoints" />
</FormItem>
<FormItem
name="grantTypes"
:label="L('DisplayName:GrantTypes')"
:label-col="{ span: 4 }"
:wrapper-col="{ span: 20 }"
>
<Select :options="grantTypes" mode="tags" v-model:value="state.application.grantTypes" />
</FormItem>
<FormItem
name="responseTypes"
:label="L('DisplayName:ResponseTypes')"
:label-col="{ span: 4 }"
:wrapper-col="{ span: 20 }"
>
<Select :options="responseTypes" mode="tags" v-model:value="state.application.responseTypes" />
</FormItem>
</TabPane>
<!-- Propertites -->
<TabPane key="propertites" :tab="L('Propertites')">
<PropertyForm
:properties="state.application.properties"
@create="handleNewProperty"
@delete="handleDelProperty"
/>
</TabPane>
</Tabs>
</Form>
</BasicModal>
</template>
<script lang="ts" setup>
import { computed } from 'vue';
import { Form } from 'ant-design-vue';
import type { FormInstance } from 'ant-design-vue/lib/form';
import { cloneDeep } from 'lodash-es';
import { computed, nextTick, ref, unref, reactive, shallowRef, onMounted, watch } from 'vue';
import { DownOutlined } from '@ant-design/icons-vue';
import { Dropdown, Form, Menu, Input, Select, Tabs } from 'ant-design-vue';
import { BasicModal, useModalInner } from '/@/components/Modal';
import { useMessage } from '/@/hooks/web/useMessage';
import { useValidation } from '/@/hooks/abp/useValidation';
import { useLocalization } from '/@/hooks/abp/useLocalization';
import { ApplicationState } from '../types/props';
import { GetAsyncById, CreateAsyncByInput, UpdateAsyncByIdAndInput } from '/@/api/openiddict/open-iddict-application';
import { OpenIddictApplicationDto } from '/@/api/openiddict/open-iddict-application/model';
import { discovery } from '/@/api/identity-server/identityServer';
import RedirectUri from './RedirectUri.vue';
import PostLogoutRedirectUri from './PostLogoutRedirectUri.vue';
import DisplayNameForm from '../../components/DisplayNames/DisplayNameForm.vue';
import ApplicationScope from './ApplicationScope.vue';
import PropertyForm from '../../components/Properties/PropertyForm.vue';
const FormItem = Form.Item;
const TabPane = Tabs.TabPane;
const MenuItem = Menu.Item;
const { L } = useLocalization('AbpOpenIddict');
const [registerModal] = useModalInner((data) => {
console.log(data);
const emits = defineEmits(['register', 'change']);
const { L } = useLocalization(['AbpOpenIddict']);
const { ruleCreator } = useValidation();
const { createMessage, createConfirm } = useMessage();
const componentsRef = shallowRef({
'redirectUris': RedirectUri,
'postLogoutRedirectUris': PostLogoutRedirectUri,
});
const formRef = ref<FormInstance>();
const state = reactive<ApplicationState>({
activeTab: 'basic',
isEdit: false,
entityChanged: false,
application: {} as OpenIddictApplicationDto,
formRules: {
clientId: ruleCreator.fieldRequired({
name: 'ClientId',
resourceName: 'AbpOpenIddict',
trigger: 'blur',
}),
},
endPoint: {
component: '',
uris: [],
},
});
watch(
() => state.application,
() => {
state.entityChanged = true;
},
{
deep: true,
},
);
const consentTypes = reactive([
{ label: 'explicit', value: 'explicit' },
{ label: 'external', value: 'external' },
{ label: 'implicit', value: 'implicit' },
{ label: 'systematic', value: 'systematic' },
]);
const endpoints = reactive([
{ label: 'authorization', value: 'authorization' },
{ label: 'token', value: 'token' },
{ label: 'logout', value: 'logout' },
{ label: 'device', value: 'device' },
{ label: 'revocation', value: 'revocation' },
{ label: 'introspection', value: 'introspection' },
]);
const grantTypes = computed(() => {
if (!state.openIdConfiguration) return[];
const types = state.openIdConfiguration.grant_types_supported;
return types.map((type) => {
return {
label: type,
value: type,
};
});
});
const responseTypes = computed(() => {
if (!state.openIdConfiguration) return[];
const types = state.openIdConfiguration.response_types_supported;
return types.map((type) => {
return {
label: type,
value: type,
};
});
});
const title = computed(() => {
const [registerModal, { changeLoading, changeOkLoading, closeModal }] = useModalInner((data) => {
nextTick(() => {
fetch(data?.id);
});
});
onMounted(initOpenidDiscovery);
function initOpenidDiscovery() {
discovery().then((openIdConfiuration) => {
state.openIdConfiguration = openIdConfiuration;
});
}
function fetch(id?: string) {
state.activeTab = 'basic';
state.isEdit = false;
state.entityChanged = false;
state.application = {} as OpenIddictApplicationDto;
const form = unref(formRef);
form?.resetFields();
if (!id) {
nextTick(() => {
state.isEdit = false;
state.entityChanged = false;
});
return;
}
changeLoading(true);
GetAsyncById(id).then((application) => {
state.application = application;
nextTick(() => {
state.isEdit = true;
state.entityChanged = false;
});
}).finally(() => {
changeLoading(false);
});
}
function handleTabChange(activeKey) {
state.activeTab = activeKey;
switch (activeKey) {
case 'endpoints':
if (!state.endPoint.component) {
state.endPoint = {
component : 'redirectUris',
uris: state.application?.redirectUris,
};
}
break;
}
}
function handleNewLogoutUri(uri: string) {
if (!state.application) {
return;
}
state.application.postLogoutRedirectUris ??= [];
state.application.postLogoutRedirectUris.push(uri);
}
function handleDelLogoutUri(uri: string) {
if (!state.application || !state.application.postLogoutRedirectUris) {
return;
}
const index = state.application.postLogoutRedirectUris.findIndex(logoutUri => logoutUri === uri);
if (!index) {
state.application.postLogoutRedirectUris.splice(index);
}
}
function handleNewRedirectUri(uri: string) {
if (!state.application) {
return;
}
state.application.redirectUris ??= [];
state.application.redirectUris.push(uri);
}
function handleDelRedirectUri(uri: string) {
if (!state.application || !state.application.redirectUris) {
return;
}
const index = state.application.redirectUris.findIndex(redirectUri => redirectUri === uri);
if (!index) {
state.application.redirectUris.splice(index);
}
}
function handleNewDisplayName(record) {
if (!state.application) {
return;
}
state.application.displayNames ??= {};
state.application.displayNames[record.culture] = record.displayName;
}
function handleDelDisplayName(record) {
if (!state.application || !state.application.displayNames) {
return;
}
delete state.application.displayNames[record.culture];
}
function handleNewProperty(record) {
if (!state.application) {
return;
}
state.application.properties ??= {};
state.application.properties[record.key] = record.value;
}
function handleDelProperty(record) {
if (!state.application || !state.application.properties) {
return;
}
delete state.application.properties[record.key];
}
function handleNewScope(scopes: string[]) {
if (!state.application) {
return;
}
state.application.scopes ??= [];
state.application.scopes.push(...scopes);
}
function handleDelScope(scopes: string[]) {
if (!state.application || !state.application.scopes) {
return;
}
state.application.scopes = state.application.scopes.filter((scope) => !scopes.includes(scope));
}
function handleClickUrisMenu(e) {
state.endPoint = {
component : e.key,
uris: state.application[e.key],
};
state.activeTab = 'endpoints';
}
function handleBeforeClose(): Promise<boolean> {
console.log(state);
return new Promise((resolve) => {
if (!state.entityChanged) {
return resolve(true);
}
createConfirm({
iconType: 'warning',
title: L('AreYouSure'),
content: L('AreYouSureYouWantToCancelEditingWarningMessage'),
onOk: () => {
resolve(true);
},
onCancel: () => {
resolve(false);
}
});
});
}
function handleSubmit() {
const form = unref(formRef);
form?.validate().then(() => {
changeOkLoading(true);
const api = state.application.id
? UpdateAsyncByIdAndInput(state.application.id, cloneDeep(state.application))
: CreateAsyncByInput(cloneDeep(state.application));
api.then((res) => {
createMessage.success(L('Successful'));
emits('change', res);
closeModal();
}).finally(() => {
changeOkLoading(false);
})
});
}
</script>

68
apps/vue/src/views/openiddict/applications/components/ApplicationScope.vue

@ -0,0 +1,68 @@
<template>
<PermissionForm :resources="getSupportScopes" :targetResources="targetResources" @change="handleChange" />
</template>
<script lang="ts" setup>
import { computed, ref, unref, onMounted } from 'vue';
import { GetListAsyncByInput } from '/@/api/openiddict/open-iddict-scope';
import PermissionForm from '../../components/Permissions/PermissionForm.vue';
const emits = defineEmits(['create', 'delete']);
const props = defineProps({
scopes: {
type: [Array] as PropType<string[]>,
},
supportScopes: {
type: [Array] as PropType<string[]>,
}
});
const resourcesRef = ref<{ key: string; title: string }[]>([]);
const targetResources = computed(() => {
if (!props.scopes) return [];
const targetScopes = getSupportScopes.value.filter((item) =>
props.scopes?.some((scope) => scope === item.key),
);
return targetScopes.map((item) => item.key);
});
const getSupportScopes = computed(() => {
const resources = unref(resourcesRef);
if (props.supportScopes) {
const supportScopes = props.supportScopes.map(scope => {
return {
key: scope,
title: scope,
}
});
supportScopes.push(...resources);
return supportScopes;
}
return resources;
});
onMounted(() => {
GetListAsyncByInput({
skipCount: 0,
maxResultCount: 100,
}).then((res) => {
resourcesRef.value = res.items.map((item) => {
return {
key: item.name,
title: item.displayName ?? item.name,
};
});
});
});
function handleChange(_, direction, moveKeys: string[]) {
switch (direction) {
case 'left':
emits('delete', moveKeys);
break;
case 'right':
emits('create', moveKeys);
break;
}
}
</script>

42
apps/vue/src/views/openiddict/applications/components/ApplicationTable.vue

@ -1,34 +1,52 @@
<template>
<div>
<BasicTable @register="registerTable">
<template #toolbar>
<Button
v-auth="['AbpOpenIddict.Applications.Create']"
type="primary"
@click="handleAddNew"
>
{{ L('Applications:AddNew') }}
</Button>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'action'">
<TableAction
:stop-button-propagation="true"
:actions="[
{
//auth: 'AbpOpenIddict.Applications.Update',
auth: 'AbpOpenIddict.Applications.Update',
label: L('Edit'),
icon: 'ant-design:edit-outlined',
onClick: handleEdit.bind(null, record),
},
{
//auth: 'AbpOpenIddict.Applications.Delete',
auth: 'AbpOpenIddict.Applications.Delete',
label: L('Delete'),
color: 'error',
icon: 'ant-design:delete-outlined',
onClick: handleDelete.bind(null, record),
},
]"
:dropDownActions="[
{
auth: 'AbpOpenIddict.Applications.ManagePermissions',
label: L('ManagePermissions'),
onClick: handlePermission.bind(null, record),
},
]"
/>
</template>
</template>
</BasicTable>
<ApplicationModal @register="registerModal" />
<ApplicationModal @register="registerModal" @change="reload" />
<PermissionModal @register="registerPermissionModal" />
</div>
</template>
<script lang="ts" setup>
import { Button } from 'ant-design-vue';
import { BasicTable, TableAction, useTable } from '/@/components/Table';
import { getDataColumns } from '../datas/TableData';
import { getSearchFormProps } from '../datas/ModalData';
@ -37,11 +55,13 @@
import { useLocalization } from '/@/hooks/abp/useLocalization';
import { GetListAsyncByInput, DeleteAsyncById } from '/@/api/openiddict/open-iddict-application';
import { formatPagedRequest } from '/@/utils/http/abp/helper';
import { PermissionModal } from '/@/components/Permission';
import ApplicationModal from './ApplicationModal.vue';
const { L } = useLocalization('AbpOpenIddict');
const { L } = useLocalization(['AbpOpenIddict']);
const { createConfirm, createMessage } = useMessage();
const [registerModal, { openModal }] = useModal();
const [registerPermissionModal, { openModal: openPermissionModal }] = useModal();
const [registerTable, { reload }] = useTable({
rowKey: 'id',
title: L('Applications'),
@ -58,16 +78,28 @@
canResize: true,
immediate: true,
actionColumn: {
width: 150,
width: 200,
title: L('Actions'),
dataIndex: 'action',
},
});
function handleAddNew() {
openModal(true, {});
}
function handleEdit(record) {
openModal(true, record);
}
function handlePermission(record) {
const props = {
providerName: 'C',
providerKey: record.clientId,
};
openPermissionModal(true, props, true);
}
function handleDelete(record) {
createConfirm({
iconType: 'warning',

60
apps/vue/src/views/openiddict/applications/components/PostLogoutRedirectUri.vue

@ -0,0 +1,60 @@
<template>
<UriEditForm
:title="L('DisplayName:PostLogoutRedirectUris')"
:schemas="schemas"
:columns="columns"
:data-source="dataSource"
rowKey="uri"
@create="handleAddNew"
@delete="handleDelete"
/>
</template>
<script lang="ts" setup>
import { computed } from 'vue';
import { FormSchema } from '/@/components/Form';
import { BasicColumn } from '/@/components/Table';
import { useLocalization } from '/@/hooks/abp/useLocalization';
import UriEditForm from '../../components/Uris/UriForm.vue';
const emits = defineEmits(['create-logout-uri', 'delete-logout-uri']);
const props = defineProps({
uris: {
type: Array as PropType<String[]>,
},
});
const { L } = useLocalization(['AbpOpenIddict']);
const dataSource = computed(() => {
if (!props.uris) return [];
return props.uris.map(uri => {
return {
uri: uri,
};
});
});
const schemas: FormSchema[] = [
{
field: 'uri',
component: 'Input',
label: 'Uri',
colProps: { span: 24 },
required: true,
},
];
const columns: BasicColumn[] = [
{
dataIndex: 'uri',
align: 'left',
width: 'auto',
sorter: true,
},
];
function handleAddNew(record) {
emits('create-logout-uri', record.uri);
}
function handleDelete(record) {
emits('delete-logout-uri', record.uri);
}
</script>

60
apps/vue/src/views/openiddict/applications/components/RedirectUri.vue

@ -0,0 +1,60 @@
<template>
<UriEditForm
:title="L('DisplayName:RedirectUris')"
:schemas="schemas"
:columns="columns"
:data-source="dataSource"
rowKey="uri"
@create="handleAddNew"
@delete="handleDelete"
/>
</template>
<script lang="ts" setup>
import { computed } from 'vue';
import { FormSchema } from '/@/components/Form';
import { BasicColumn } from '/@/components/Table';
import { useLocalization } from '/@/hooks/abp/useLocalization';
import UriEditForm from '../../components/Uris/UriForm.vue';
const emits = defineEmits(['create-redirect-uri', 'delete-redirect-uri']);
const props = defineProps({
uris: {
type: Array as PropType<String[]>,
},
});
const { L } = useLocalization(['AbpOpenIddict']);
const dataSource = computed(() => {
if (!props.uris) return [];
return props.uris.map(uri => {
return {
uri: uri,
};
});
});
const schemas: FormSchema[] = [
{
field: 'uri',
component: 'Input',
label: 'Uri',
colProps: { span: 24 },
required: true,
},
];
const columns: BasicColumn[] = [
{
dataIndex: 'uri',
align: 'left',
width: 'auto',
sorter: true,
},
];
function handleAddNew(record) {
emits('create-redirect-uri', record.uri);
}
function handleDelete(record) {
emits('delete-redirect-uri', record.uri);
}
</script>

18
apps/vue/src/views/openiddict/applications/types/props.ts

@ -0,0 +1,18 @@
import { Rule } from 'ant-design-vue/lib/form';
import { OpenIdConfiguration } from '/@/api/identity-server/model/basicModel';
import { OpenIddictApplicationDto } from '/@/api/openiddict/open-iddict-application/model';
export interface EndPointComponent {
component: string;
uris?: string[];
}
export interface ApplicationState {
activeTab: string;
formRules?: Dictionary<string, Rule>,
application: OpenIddictApplicationDto;
endPoint: EndPointComponent;
openIdConfiguration?: OpenIdConfiguration;
entityChanged: boolean;
isEdit: boolean;
}

133
apps/vue/src/views/openiddict/components/DisplayNames/DisplayNameForm.vue

@ -0,0 +1,133 @@
<template>
<Card :title="L('DisplayName:DisplayNames')">
<BasicForm @register="registerForm" @submit="handleSubmit" />
<BasicTable @register="registerTable" :data-source="dataSource">
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'action'">
<TableAction
:actions="[
{
color: 'error',
icon: 'ant-design:delete-outlined',
label: L('Delete'),
onClick: handleDelete.bind(null, record),
},
]"
/>
</template>
</template>
</BasicTable>
</Card>
</template>
<script lang="ts" setup>
import { computed, ref } from 'vue';
import { Card } from 'ant-design-vue';
import { useLocalization } from '/@/hooks/abp/useLocalization';
import { BasicForm, useForm } from '/@/components/Form';
import { BasicTable, TableAction, useTable } from '/@/components/Table';
import { getList as getLanguages } from '/@/api/localization/languages';
const emits = defineEmits(['create', 'delete']);
const props = defineProps({
displayNames: {
type: Object as PropType<Recordable>,
default: () => {},
},
});
const { L } = useLocalization(['AbpOpenIddict', 'AbpLocalization', 'AbpUi']);
const modelRef = ref({});
const [registerForm, { resetFields }] = useForm({
model: modelRef,
schemas: [
{
field: 'culture',
component: 'ApiSelect',
label: L('DisplayName:CultureName'),
colProps: { span: 24 },
required: true,
componentProps: {
api: getLanguages,
params: {
skipCount: 0,
maxResultCount: 100,
},
resultField: 'items',
labelField: 'displayName',
valueField: 'cultureName',
},
},
{
field: 'displayName',
component: 'Input',
label: L('DisplayName:DisplayName'),
colProps: { span: 24 },
required: true,
},
],
showResetButton: false,
submitButtonOptions: {
text: L('DisplayName:AddNew'),
// icon: 'ant-design:plus-outlined',
},
});
const [registerTable] = useTable({
rowKey: 'culture',
showHeader: false,
columns: [
{
dataIndex: 'culture',
align: 'left',
width: 100,
sorter: true,
},
{
dataIndex: 'displayName',
align: 'left',
width: 'auto',
sorter: true,
},
],
pagination: false,
striped: false,
useSearchForm: false,
showTableSetting: false,
showIndexColumn: false,
bordered: false,
actionColumn: {
width: 200,
title: L('Actions'),
dataIndex: 'action',
},
});
const dataSource = computed(() => {
if (!props.displayNames) {
return [];
}
return Object.keys(props.displayNames).map((key) => {
return {
culture: key,
displayName: props.displayNames[key]
}
});
});
function handleSubmit(input) {
if (!props.displayNames && !props.displayNames[input.culture]) {
return;
}
emits('create', input);
resetFields();
}
function handleDelete(record) {
emits('delete', record);
}
</script>
<style lang="less" scoped>
.title {
margin-bottom: 20px;
}
</style>

41
apps/vue/src/views/openiddict/components/Permissions/PermissionForm.vue

@ -0,0 +1,41 @@
<template>
<Transfer
:dataSource="resources"
:targetKeys="targetResources"
:titles="[L('Assigned'), L('Available')]"
:render="(item) => item.title"
:list-style="getListStyle"
@change="handleChange"
/>
</template>
<script lang="ts" setup>
import { computed } from 'vue';
import { Transfer } from 'ant-design-vue';
import { useLocalization } from '/@/hooks/abp/useLocalization';
const emits = defineEmits(['change']);
const props = defineProps({
resources: {
type: [Array] as PropType<{ key: string; title: string }[]>,
required: true,
default: () => [],
},
targetResources: { type: [Array] as PropType<string[]>, required: true, default: () => [] },
listStyle: { type: Object, required: false },
});
const { L } = useLocalization(['AbpOpenIddict']);
const defaultListStyle = {
width: '48%',
height: '500px',
minHeight: '500px',
};
const getListStyle = computed(() => {
return {...defaultListStyle, ...props.listStyle}
});
function handleChange(targetKeys, direction, moveKeys) {
emits('change', targetKeys, direction, moveKeys);
}
</script>

120
apps/vue/src/views/openiddict/components/Properties/PropertyForm.vue

@ -0,0 +1,120 @@
<template>
<Card :title="L('Propertites')">
<BasicTable @register="registerTable" :data-source="dataSource">
<template #toolbar>
<Button type="primary" @click="handleAddNew">{{ L('Propertites:New') }}</Button>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'action'">
<TableAction
:actions="[
{
color: 'error',
icon: 'ant-design:delete-outlined',
label: L('Delete'),
onClick: handleDelete.bind(null, record),
},
]"
/>
</template>
</template>
</BasicTable>
<BasicModal v-bind="$attrs" @register="registerModal" @ok="handleSubmit" :title="title">
<BasicForm @register="registerForm" />
</BasicModal>
</Card>
</template>
<script lang="ts" setup>
import { computed, ref } from 'vue';
import { Button, Card } from 'ant-design-vue';
import { BasicForm, useForm } from '/@/components/Form';
import { BasicModal, useModal } from '/@/components/Modal';
import { BasicTable, TableAction, useTable } from '/@/components/Table';
import { useLocalization } from '/@/hooks/abp/useLocalization';
const emits = defineEmits(['create', 'delete']);
const props = defineProps({
properties: {
type: Object as PropType<Dictionary<string, string>>,
default: () => [],
},
});
const { L } = useLocalization(['AbpOpenIddict']);
const title = ref('');
const [registerForm, { validate, resetFields }] = useForm({
labelWidth: 120,
showActionButtonGroup: false,
schemas: [
{
field: 'key',
component: 'Input',
label: L('Propertites:Key'),
colProps: { span: 24 },
required: true,
},
{
field: 'value',
component: 'Input',
label: L('Propertites:Value'),
colProps: { span: 24 },
required: true,
},
],
});
const dataSource = computed(() => {
if (!props.properties) return [];
return Object.keys(props.properties).map((key) => {
return {
key: key,
value: props.properties[key],
};
});
});
const [registerTable] = useTable({
rowKey: "key",
columns: [
{
title: L('Propertites:Key'),
dataIndex: 'key',
align: 'left',
width: 180,
sorter: true,
},
{
title: L('Propertites:Value'),
dataIndex: 'value',
align: 'left',
width: 180,
sorter: true,
},
],
pagination: false,
showTableSetting: true,
maxHeight: 230,
actionColumn: {
width: 100,
title: L('Actions'),
dataIndex: 'action',
},
});
const [registerModal, { openModal, closeModal }] = useModal();
function handleAddNew() {
title.value = L('Propertites:New');
openModal(true);
}
function handleDelete(record) {
emits('delete', record);
}
function handleSubmit() {
validate().then((input) => {
emits('create', input);
resetFields();
closeModal();
});
}
</script>

124
apps/vue/src/views/openiddict/components/Uris/UriForm.vue

@ -0,0 +1,124 @@
<template>
<div>
<BasicTitle class="title">{{ title }}</BasicTitle>
<BasicForm @register="registerForm" @submit="handleSubmit" />
<BasicTable @register="registerTable">
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'action'">
<TableAction
:actions="[
{
color: 'error',
icon: 'ant-design:delete-outlined',
label: L('Delete'),
onClick: handleDelete.bind(null, record),
},
]"
/>
</template>
</template>
</BasicTable>
</div>
</template>
<script lang="ts" setup>
import { ref, watch } from 'vue';
import { BasicTitle } from '/@/components/Basic';
import { useLocalization } from '/@/hooks/abp/useLocalization';
import { BasicForm, FormSchema, useForm } from '/@/components/Form';
import { BasicTable, BasicColumn, TableAction, useTable } from '/@/components/Table';
const emits = defineEmits(['create', 'delete']);
const props = defineProps({
schemas: {
type: [Array] as PropType<FormSchema[]>,
required: true,
default: () => [],
},
labelWidth: {
type: Number,
},
columns: {
type: [Array] as PropType<BasicColumn[]>,
required: true,
default: () => [],
},
dataSource: {
type: [Array] as PropType<Recordable[]>,
required: true,
default: () => [],
},
rowKey: {
type: String,
default: () => 'id',
},
showHeader: {
type: Boolean,
default: () => false,
},
title: {
type: String,
default: () => '',
},
tableTitle: {
type: String,
default: () => '',
},
});
const { L } = useLocalization(['AbpOpenIddict', 'AbpUi']);
const modelRef = ref({});
const [registerForm, { resetFields }] = useForm({
model: modelRef,
labelWidth: props.labelWidth,
schemas: props.schemas,
showResetButton: false,
submitButtonOptions: {
text: L('Uri:AddNew'),
// icon: 'ant-design:plus-outlined',
},
});
const [registerTable, { setTableData }] = useTable({
rowKey: props.rowKey,
showHeader: props.showHeader,
title: props.tableTitle,
columns: props.columns,
dataSource: props.dataSource,
pagination: false,
striped: false,
useSearchForm: false,
showTableSetting: false,
showIndexColumn: false,
bordered: false,
actionColumn: {
width: 200,
title: L('Actions'),
dataIndex: 'action',
},
});
watch(
() => props.dataSource,
(data) => {
setTableData(data);
},
{
deep: true,
},
);
function handleSubmit(input) {
emits('create', input);
resetFields();
}
function handleDelete(record) {
emits('delete', record);
}
</script>
<style lang="less" scoped>
.title {
margin-bottom: 20px;
}
</style>

10
aspnet-core/modules/localization/LINGYUN.Abp.AspNetCore.Mvc.Localization/LINGYUN/Abp/AspNetCore/Mvc/Localization/TextAppService.cs

@ -27,15 +27,11 @@ namespace LINGYUN.Abp.AspNetCore.Mvc.Localization
public async virtual Task<TextDto> GetByCultureKeyAsync(GetTextByKeyInput input)
{
var resource = _localizationOptions.Resources.GetOrDefault(input.ResourceName);
IEnumerable<LocalizedString> localizedStrings = new List<LocalizedString>();
var localizer = await _localizerFactory.CreateByResourceNameAsync(resource.ResourceName);
using (CultureHelper.Use(input.CultureName, input.CultureName))
{
localizedStrings = localizer.GetAllStrings(true)
.OrderBy(l => l.Name);
var result = new TextDto
{
Key = input.Key,
@ -96,7 +92,7 @@ namespace LINGYUN.Abp.AspNetCore.Mvc.Localization
using (CultureHelper.Use(cultureName, cultureName))
{
localizedStrings = localizer.GetAllStrings(true)
localizedStrings = (await localizer.GetAllStringsAsync(true))
.WhereIf(!filter.IsNullOrWhiteSpace(), x => x.Name.Contains(filter))
.OrderBy(l => l.Name);
}
@ -109,7 +105,7 @@ namespace LINGYUN.Abp.AspNetCore.Mvc.Localization
{
using (CultureHelper.Use(targetCultureName, targetCultureName))
{
targetLocalizedStrings = localizer.GetAllStrings(true)
targetLocalizedStrings = (await localizer.GetAllStringsAsync(true))
.WhereIf(!filter.IsNullOrWhiteSpace(), x => x.Name.Contains(filter))
.OrderBy(l => l.Name);
}

14
aspnet-core/modules/lt/LINGYUN.Abp.LocalizationManagement.Domain/LINGYUN/Abp/LocalizationManagement/LocalizationStoreInMemoryCache.cs

@ -175,15 +175,17 @@ public class LocalizationStoreInMemoryCache : ILocalizationStoreCache, ISingleto
localizedStrings ??= new LocalizationDictionaryWithCulture();
localizedStrings.Clear();
var currentCultureLocalizedStrings = new LocalizationDictionary();
foreach (var textRecord in textRecords.Where(x => x.ResourceName == resourceRecord.Name))
// 需要按照不同文化聚合
foreach (var textRecordByCulture in textRecords.Where(x => x.ResourceName == resourceRecord.Name).GroupBy(x => x.CultureName))
{
currentCultureLocalizedStrings[textRecord.Key] = new LocalizedString(textRecord.Key, textRecord.Value);
var currentCultureLocalizedStrings = new LocalizationDictionary();
foreach (var textRecord in textRecordByCulture)
{
currentCultureLocalizedStrings[textRecord.Key] = new LocalizedString(textRecord.Key, textRecord.Value);
}
localizedStrings[textRecordByCulture.Key] = currentCultureLocalizedStrings;
}
localizedStrings[CultureInfo.CurrentCulture.Name] = currentCultureLocalizedStrings;
LocalizedStrings[resourceRecord.Name] = localizedStrings;
}

6
aspnet-core/modules/openIddict/LINGYUN.Abp.OpenIddict.Application.Contracts/LINGYUN/Abp/OpenIddict/Applications/OpenIddictApplicationCreateDto.cs

@ -1,8 +1,14 @@
using System;
using System.ComponentModel.DataAnnotations;
using Volo.Abp.OpenIddict.Applications;
using Volo.Abp.Validation;
namespace LINGYUN.Abp.OpenIddict.Applications;
[Serializable]
public class OpenIddictApplicationCreateDto : OpenIddictApplicationCreateOrUpdateDto
{
[Required]
[DynamicStringLength(typeof(OpenIddictApplicationConsts), nameof(OpenIddictApplicationConsts.ClientIdMaxLength))]
public string ClientId { get; set; }
}

4
aspnet-core/modules/openIddict/LINGYUN.Abp.OpenIddict.Application.Contracts/LINGYUN/Abp/OpenIddict/Applications/OpenIddictApplicationCreateOrUpdateDto.cs

@ -8,10 +8,6 @@ namespace LINGYUN.Abp.OpenIddict.Applications;
public abstract class OpenIddictApplicationCreateOrUpdateDto : ExtensibleObject
{
[Required]
[DynamicStringLength(typeof(OpenIddictApplicationConsts), nameof(OpenIddictApplicationConsts.ClientIdMaxLength))]
public string ClientId { get; set; }
public string ClientSecret { get; set; }
[DynamicStringLength(typeof(OpenIddictApplicationConsts), nameof(OpenIddictApplicationConsts.ConsentTypeMaxLength))]

4
aspnet-core/modules/openIddict/LINGYUN.Abp.OpenIddict.Application.Contracts/LINGYUN/Abp/OpenIddict/Applications/OpenIddictApplicationDto.cs

@ -1,11 +1,12 @@
using System;
using System.Collections.Generic;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Domain.Entities;
namespace LINGYUN.Abp.OpenIddict.Applications;
[Serializable]
public class OpenIddictApplicationDto : ExtensibleAuditedEntityDto<Guid>
public class OpenIddictApplicationDto : ExtensibleAuditedEntityDto<Guid>, IHasConcurrencyStamp
{
public string ClientId { get; set; }
public string ClientSecret { get; set; }
@ -23,4 +24,5 @@ public class OpenIddictApplicationDto : ExtensibleAuditedEntityDto<Guid>
public string Type { get; set; }
public string ClientUri { get; set; }
public string LogoUri { get; set; }
public string ConcurrencyStamp { get; set; }
}

4
aspnet-core/modules/openIddict/LINGYUN.Abp.OpenIddict.Application.Contracts/LINGYUN/Abp/OpenIddict/Applications/OpenIddictApplicationUpdateDto.cs

@ -1,8 +1,10 @@
using System;
using Volo.Abp.Domain.Entities;
namespace LINGYUN.Abp.OpenIddict.Applications;
[Serializable]
public class OpenIddictApplicationUpdateDto : OpenIddictApplicationCreateOrUpdateDto
public class OpenIddictApplicationUpdateDto : OpenIddictApplicationCreateOrUpdateDto, IHasConcurrencyStamp
{
public string ConcurrencyStamp { get; set; }
}

4
aspnet-core/modules/openIddict/LINGYUN.Abp.OpenIddict.Application.Contracts/LINGYUN/Abp/OpenIddict/Authorizations/OpenIddictAuthorizationDto.cs

@ -1,12 +1,14 @@
using System;
using System.Collections.Generic;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Domain.Entities;
namespace LINGYUN.Abp.OpenIddict.Authorizations;
[Serializable]
public class OpenIddictAuthorizationDto : ExtensibleAuditedEntityDto<Guid>
public class OpenIddictAuthorizationDto : ExtensibleAuditedEntityDto<Guid>, IHasConcurrencyStamp
{
public string ConcurrencyStamp { get; set; }
public Guid? ApplicationId { get; set; }
public DateTime? CreationDate { get; set; }
public Dictionary<string, string> Properties { get; set; } = new Dictionary<string, string>();

28
aspnet-core/modules/openIddict/LINGYUN.Abp.OpenIddict.Application.Contracts/LINGYUN/Abp/OpenIddict/Localization/Resources/en.json

@ -9,14 +9,19 @@
"Permissions:Update": "Update",
"Permissions:Delete": "Delete",
"Permissions:ManagePermissions": "Manage Permissions",
"OpenIddict:Applications:0001": "The application client id {ClientId} already exists!",
"OpenIddict:Scopes:0001": "The scope name {Name} already exists!",
"OpenIddict:001001": "The application client id {ClientId} already exists!",
"OpenIddict:002001": "The scope name {Name} already exists!",
"DisplayName:ClientId": "Client Id",
"DisplayName:ClientSecret": "Client Secret",
"Description:ClientSecret": "Please copy the key information before saving. You can only reset the key after the data is submitted.",
"DisplayName:ConsentType": "Consent Type",
"DisplayName:DisplayName": "Display Name",
"DisplayName:DisplayNames": "Display Names",
"DisplayName:DefaultDisplayName": "Default Display Name",
"DisplayName:Permissions": "Permissions",
"DisplayName:Endpoints": "Endpoints",
"DisplayName:GrantTypes": "Grant Types",
"DisplayName:ResponseTypes": "Response Types",
"DisplayName:PostLogoutRedirectUris": "Post Logout Redirect Uris",
"DisplayName:Properties": "Properties",
"DisplayName:RedirectUris": "Redirect Uris",
@ -39,6 +44,23 @@
"DisplayName:RedemptionDate": "Redemption Date",
"DisplayName:ReferenceId": "Reference Id",
"DisplayName:LastModificationTime": "Modify time",
"DisplayName:CreationTime": "Creation time"
"DisplayName:CreationTime": "Creation time",
"Applications": "Applications",
"Applications:AddNew": "New Application",
"Authorizations": "Authorizations",
"Scopes": "Scopes",
"Tokens": "Tokens",
"ManagePermissions": "Manage Permissions",
"BasicInfo": "Basic",
"DisplayNames": "Display Names",
"DisplayName:AddNew": "New Display Name",
"Endpoints": "Endpoints",
"Propertites": "Propertites",
"Uri:AddNew": "New Uri",
"Assigned": "Assigned",
"Available": "Available",
"Propertites:New": "New Property",
"Propertites:Key": "Key",
"Propertites:Value": "Value"
}
}

28
aspnet-core/modules/openIddict/LINGYUN.Abp.OpenIddict.Application.Contracts/LINGYUN/Abp/OpenIddict/Localization/Resources/zh-Hans.json

@ -9,14 +9,19 @@
"Permissions:Update": "编辑",
"Permissions:Delete": "删除",
"Permissions:ManagePermissions": "管理权限",
"OpenIddict:Applications:0001": "应用标识 {ClientId} 已经存在!",
"OpenIddict:Scopes:0001": "范围名称 {Name} 已经存在!",
"OpenIddict:001001": "应用标识 {ClientId} 已经存在!",
"OpenIddict:002001": "范围名称 {Name} 已经存在!",
"DisplayName:ClientId": "客户端标识",
"DisplayName:ClientSecret": "客户端密钥",
"Description:ClientSecret": "请在保存之前复制密钥信息,数据提交后将只能重置密钥.",
"DisplayName:ConsentType": "同意类型",
"DisplayName:DisplayName": "显示名称",
"DisplayName:DisplayNames": "显示名称",
"DisplayName:DefaultDisplayName": "默认显示名称",
"DisplayName:Permissions": "权限",
"DisplayName:Endpoints": "端点",
"DisplayName:GrantTypes": "授权类型",
"DisplayName:ResponseTypes": "响应类型",
"DisplayName:PostLogoutRedirectUris": "注销后重定向Uri",
"DisplayName:Properties": "属性",
"DisplayName:RedirectUris": "重定向Uri",
@ -39,6 +44,23 @@
"DisplayName:RedemptionDate": "偿还时间",
"DisplayName:ReferenceId": "引用标识",
"DisplayName:LastModificationTime": "修改时间",
"DisplayName:CreationTime": "创建时间"
"DisplayName:CreationTime": "创建时间",
"Applications": "应用",
"Applications:AddNew": "新应用",
"Authorizations": "授权",
"Scopes": "范围",
"Tokens": "令牌",
"ManagePermissions": "管理权限",
"BasicInfo": "基本信息",
"DisplayNames": "显示名称",
"DisplayName:AddNew": "新显示配置",
"Endpoints": "端点",
"Propertites": "属性",
"Uri:AddNew": "新Uri",
"Assigned": "可分配的",
"Available": "已拥有的",
"Propertites:New": "新属性",
"Propertites:Key": "属性名称",
"Propertites:Value": "属性值"
}
}

14
aspnet-core/modules/openIddict/LINGYUN.Abp.OpenIddict.Application.Contracts/LINGYUN/Abp/OpenIddict/OpenIddictApplicationErrorCodes.cs

@ -6,21 +6,23 @@ public static class OpenIddictApplicationErrorCodes
public static class Applications
{
public const string ClientIdExisted = Namespace + "Applications:0001";
public const string Prefix = Namespace + ":001";
public const string ClientIdExisted = Prefix + "001";
}
public static class Authorizations
public static class Scopes
{
public const string Prefix = Namespace + ":002";
public const string NameExisted = Prefix + "001";
}
public static class Scopes
public static class Authorizations
{
public const string NameExisted = Namespace + "Scopes:0001";
public const string Prefix = Namespace + ":003";
}
public static class Tokens
{
public const string Prefix = Namespace + ":004";
}
}

5
aspnet-core/modules/openIddict/LINGYUN.Abp.OpenIddict.Application.Contracts/LINGYUN/Abp/OpenIddict/Scopes/OpenIddictScopeDto.cs

@ -1,12 +1,15 @@
using System;
using System.Collections.Generic;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Domain.Entities;
namespace LINGYUN.Abp.OpenIddict.Scopes;
[Serializable]
public class OpenIddictScopeDto : ExtensibleAuditedEntityDto<Guid>
public class OpenIddictScopeDto : ExtensibleAuditedEntityDto<Guid>, IHasConcurrencyStamp
{
public string ConcurrencyStamp { get; set; }
public string Description { get; set; }
public Dictionary<string, string> Descriptions { get; set; } = new Dictionary<string, string>();

4
aspnet-core/modules/openIddict/LINGYUN.Abp.OpenIddict.Application.Contracts/LINGYUN/Abp/OpenIddict/Scopes/OpenIddictScopeUpdateDto.cs

@ -1,8 +1,10 @@
using System;
using Volo.Abp.Domain.Entities;
namespace LINGYUN.Abp.OpenIddict.Scopes;
[Serializable]
public class OpenIddictScopeUpdateDto : OpenIddictScopeCreateOrUpdateDto
public class OpenIddictScopeUpdateDto : OpenIddictScopeCreateOrUpdateDto, IHasConcurrencyStamp
{
public string ConcurrencyStamp { get; set; }
}

5
aspnet-core/modules/openIddict/LINGYUN.Abp.OpenIddict.Application.Contracts/LINGYUN/Abp/OpenIddict/Tokens/OpenIddictTokenDto.cs

@ -1,11 +1,14 @@
using System;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Domain.Entities;
namespace LINGYUN.Abp.OpenIddict.Tokens;
[Serializable]
public class OpenIddictTokenDto : ExtensibleAuditedEntityDto<Guid>
public class OpenIddictTokenDto : ExtensibleAuditedEntityDto<Guid>, IHasConcurrencyStamp
{
public string ConcurrencyStamp { get; set; }
public Guid? ApplicationId { get; set; }
public Guid? AuthorizationId { get; set; }

55
aspnet-core/modules/openIddict/LINGYUN.Abp.OpenIddict.Application/LINGYUN/Abp/OpenIddict/Applications/OpenIddictApplicationAppService.cs

@ -1,10 +1,13 @@
using LINGYUN.Abp.OpenIddict.Permissions;
using Microsoft.AspNetCore.Authorization;
using OpenIddict.Abstractions;
using System;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Data;
using Volo.Abp.OpenIddict;
using Volo.Abp.OpenIddict.Applications;
namespace LINGYUN.Abp.OpenIddict.Applications;
@ -12,25 +15,29 @@ namespace LINGYUN.Abp.OpenIddict.Applications;
[Authorize(AbpOpenIddictPermissions.Applications.Default)]
public class OpenIddictApplicationAppService : OpenIddictApplicationServiceBase, IOpenIddictApplicationAppService
{
protected IOpenIddictApplicationRepository Repository { get; }
private readonly IAbpApplicationManager _applicationManager;
private readonly IOpenIddictApplicationRepository _applicationRepository;
public OpenIddictApplicationAppService(
IOpenIddictApplicationRepository repository)
IAbpApplicationManager applicationManager,
IOpenIddictApplicationRepository applicationRepository)
{
Repository = repository;
_applicationManager = applicationManager;
_applicationRepository = applicationRepository;
}
public async virtual Task<OpenIddictApplicationDto> GetAsync(Guid id)
{
var application = await Repository.GetAsync(id);
var application = await _applicationRepository.GetAsync(id);
return application.ToDto(JsonSerializer);
}
public async virtual Task<PagedResultDto<OpenIddictApplicationDto>> GetListAsync(OpenIddictApplicationGetListInput input)
{
var totalCount = await Repository.GetCountAsync(input.Filter);
var entites = await Repository.GetListAsync(input.Sorting, input.SkipCount, input.MaxResultCount, input.Filter);
var totalCount = await _applicationRepository.GetCountAsync(input.Filter);
var entites = await _applicationRepository.GetListAsync(input.Sorting, input.SkipCount, input.MaxResultCount, input.Filter);
return new PagedResultDto<OpenIddictApplicationDto>(totalCount,
entites.Select(entity => entity.ToDto(JsonSerializer)).ToList());
@ -39,16 +46,20 @@ public class OpenIddictApplicationAppService : OpenIddictApplicationServiceBase,
[Authorize(AbpOpenIddictPermissions.Applications.Create)]
public async virtual Task<OpenIddictApplicationDto> CreateAsync(OpenIddictApplicationCreateDto input)
{
if (await Repository.FindByClientIdAsync(input.ClientId) != null)
if (await _applicationRepository.FindByClientIdAsync(input.ClientId) != null)
{
throw new BusinessException(OpenIddictApplicationErrorCodes.Applications.ClientIdExisted)
.WithData(nameof(OpenIddictApplication.ClientId), input.ClientId);
}
var application = new OpenIddictApplication(GuidGenerator.Create());
var application = new OpenIddictApplication(GuidGenerator.Create())
{
ClientId = input.ClientId,
};
application = input.ToEntity(application, JsonSerializer);
application = await Repository.InsertAsync(application);
application = await _applicationRepository.InsertAsync(application);
await CurrentUnitOfWork.SaveChangesAsync();
@ -58,20 +69,24 @@ public class OpenIddictApplicationAppService : OpenIddictApplicationServiceBase,
[Authorize(AbpOpenIddictPermissions.Applications.Update)]
public async virtual Task<OpenIddictApplicationDto> UpdateAsync(Guid id, OpenIddictApplicationUpdateDto input)
{
var application = await Repository.GetAsync(id);
var application = await _applicationRepository.GetAsync(id);
if (!string.Equals(application.ClientId, input.ClientId) &&
await Repository.FindByClientIdAsync(input.ClientId) != null)
{
throw new BusinessException(OpenIddictApplicationErrorCodes.Applications.ClientIdExisted)
.WithData(nameof(OpenIddictApplicationCreateDto.ClientId), input.ClientId);
}
//if (!string.Equals(application.ClientId, input.ClientId) &&
// await _applicationRepository.FindByClientIdAsync(input.ClientId) != null)
//{
// throw new BusinessException(OpenIddictApplicationErrorCodes.Applications.ClientIdExisted)
// .WithData(nameof(OpenIddictApplicationCreateDto.ClientId), input.ClientId);
//}
application.SetConcurrencyStampIfNotNull(input.ConcurrencyStamp);
application = input.ToEntity(application, JsonSerializer);
application = await Repository.UpdateAsync(application);
var cache = LazyServiceProvider.LazyGetRequiredService<IOpenIddictApplicationCache<OpenIddictApplicationModel>>();
await CurrentUnitOfWork.SaveChangesAsync();
await cache.RemoveAsync(application.ToModel(), GetCancellationToken());
await _applicationRepository.UpdateAsync(application);
return application.ToDto(JsonSerializer);
}
@ -79,8 +94,8 @@ public class OpenIddictApplicationAppService : OpenIddictApplicationServiceBase,
[Authorize(AbpOpenIddictPermissions.Applications.Delete)]
public async virtual Task DeleteAsync(Guid id)
{
await Repository.DeleteAsync(id);
var application = await _applicationRepository.GetAsync(id);
await CurrentUnitOfWork.SaveChangesAsync();
await _applicationManager.DeleteAsync(application.ToModel());
}
}

1
aspnet-core/modules/openIddict/LINGYUN.Abp.OpenIddict.Application/LINGYUN/Abp/OpenIddict/Applications/OpenIddictApplicationExtensions.cs

@ -15,7 +15,6 @@ internal static class OpenIddictApplicationExtensions
Check.NotNull(dto, nameof(dto));
Check.NotNull(entity, nameof(entity));
entity.ClientId = dto.ClientId;
entity.ClientSecret = dto.ClientSecret;
entity.ConsentType = dto.ConsentType;
entity.DisplayName = dto.DisplayName;

26
aspnet-core/modules/openIddict/LINGYUN.Abp.OpenIddict.Application/LINGYUN/Abp/OpenIddict/Authorizations/OpenIddictAuthorizationAppService.cs

@ -1,5 +1,6 @@
using LINGYUN.Abp.OpenIddict.Permissions;
using Microsoft.AspNetCore.Authorization;
using OpenIddict.Abstractions;
using System;
using System.Linq;
using System.Linq.Dynamic.Core;
@ -13,32 +14,35 @@ namespace LINGYUN.Abp.OpenIddict.Authorizations;
[Authorize(AbpOpenIddictPermissions.Authorizations.Default)]
public class OpenIddictAuthorizationAppService : OpenIddictApplicationServiceBase, IOpenIddictAuthorizationAppService
{
protected IRepository<OpenIddictAuthorization, Guid> Repository { get; }
private readonly IOpenIddictAuthorizationManager _authorizationManager;
private readonly IRepository<OpenIddictAuthorization, Guid> _authorizationRepository;
public OpenIddictAuthorizationAppService(
IRepository<OpenIddictAuthorization, Guid> repository)
IOpenIddictAuthorizationManager authorizationManager,
IRepository<OpenIddictAuthorization, Guid> authorizationRepository)
{
Repository = repository;
_authorizationManager = authorizationManager;
_authorizationRepository = authorizationRepository;
}
[Authorize(AbpOpenIddictPermissions.Authorizations.Delete)]
public async virtual Task DeleteAsync(Guid id)
{
await Repository.DeleteAsync(id);
var authorization = await _authorizationRepository.GetAsync(id);
await CurrentUnitOfWork.SaveChangesAsync();
await _authorizationManager.DeleteAsync(authorization.ToModel());
}
public async virtual Task<OpenIddictAuthorizationDto> GetAsync(Guid id)
{
var authorization = await Repository.GetAsync(id);
var authorization = await _authorizationRepository.GetAsync(id);
return authorization.ToDto(JsonSerializer);
}
public async virtual Task<PagedResultDto<OpenIddictAuthorizationDto>> GetListAsync(OpenIddictAuthorizationGetListInput input)
{
var queryable = await Repository.GetQueryableAsync();
var queryable = await _authorizationRepository.GetQueryableAsync();
if (input.ClientId.HasValue)
{
queryable = queryable.Where(x => x.ApplicationId == input.ClientId);
@ -69,8 +73,14 @@ public class OpenIddictAuthorizationAppService : OpenIddictApplicationServiceBas
x.Status.Contains(input.Filter) || x.Type.Contains(input.Filter) ||
x.Scopes.Contains(input.Filter) || x.Properties.Contains(input.Filter));
}
var sorting = input.Sorting;
if (sorting.IsNullOrWhiteSpace())
{
sorting = $"{nameof(OpenIddictAuthorization.CreationTime)} DESC";
}
queryable = queryable
.OrderBy(input.Sorting ?? $"{nameof(OpenIddictAuthorization.CreationTime)} DESC")
.OrderBy(sorting)
.PageBy(input.SkipCount, input.MaxResultCount);
var totalCount = await AsyncExecuter.CountAsync(queryable);

41
aspnet-core/modules/openIddict/LINGYUN.Abp.OpenIddict.Application/LINGYUN/Abp/OpenIddict/Scopes/OpenIddictScopeAppService.cs

@ -1,10 +1,13 @@
using LINGYUN.Abp.OpenIddict.Permissions;
using Microsoft.AspNetCore.Authorization;
using OpenIddict.Abstractions;
using System;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Data;
using Volo.Abp.OpenIddict.Applications;
using Volo.Abp.OpenIddict.Scopes;
namespace LINGYUN.Abp.OpenIddict.Scopes;
@ -12,26 +15,32 @@ namespace LINGYUN.Abp.OpenIddict.Scopes;
[Authorize(AbpOpenIddictPermissions.Scopes.Default)]
public class OpenIddictScopeAppService : OpenIddictApplicationServiceBase, IOpenIddictScopeAppService
{
protected IOpenIddictScopeRepository Repository { get; }
private readonly IOpenIddictScopeManager _scopeManager;
public OpenIddictScopeAppService(IOpenIddictScopeRepository repository)
private readonly IOpenIddictScopeRepository _scoppeRepository;
public OpenIddictScopeAppService(
IOpenIddictScopeManager scopeManager,
IOpenIddictScopeRepository scopeRepository)
{
Repository = repository;
_scopeManager = scopeManager;
_scoppeRepository = scopeRepository;
}
[Authorize(AbpOpenIddictPermissions.Scopes.Create)]
public async virtual Task<OpenIddictScopeDto> CreateAsync(OpenIddictScopeCreateDto input)
{
if (await Repository.FindByNameAsync(input.Name) != null)
if (await _scoppeRepository.FindByNameAsync(input.Name) != null)
{
throw new BusinessException(OpenIddictApplicationErrorCodes.Scopes.NameExisted)
.WithData(nameof(OpenIddictScope.Name), input.Name);
}
var scope = new OpenIddictScope(GuidGenerator.Create());
scope = input.ToEntity(scope, JsonSerializer);
scope = await Repository.InsertAsync(scope);
scope = await _scoppeRepository.InsertAsync(scope);
await CurrentUnitOfWork.SaveChangesAsync();
@ -41,22 +50,22 @@ public class OpenIddictScopeAppService : OpenIddictApplicationServiceBase, IOpen
[Authorize(AbpOpenIddictPermissions.Scopes.Delete)]
public async virtual Task DeleteAsync(Guid id)
{
await Repository.DeleteAsync(id);
var scope = await _scoppeRepository.GetAsync(id);
await CurrentUnitOfWork.SaveChangesAsync();
await _scopeManager.DeleteAsync(scope.ToModel());
}
public async virtual Task<OpenIddictScopeDto> GetAsync(Guid id)
{
var scope = await Repository.GetAsync(id);
var scope = await _scoppeRepository.GetAsync(id);
return scope.ToDto(JsonSerializer);
}
public async virtual Task<PagedResultDto<OpenIddictScopeDto>> GetListAsync(OpenIddictScopeGetListInput input)
{
var totalCount = await Repository.GetCountAsync(input.Filter);
var entites = await Repository.GetListAsync(input.Sorting, input.SkipCount, input.MaxResultCount, input.Filter);
var totalCount = await _scoppeRepository.GetCountAsync(input.Filter);
var entites = await _scoppeRepository.GetListAsync(input.Sorting, input.SkipCount, input.MaxResultCount, input.Filter);
return new PagedResultDto<OpenIddictScopeDto>(totalCount,
entites.Select(entity => entity.ToDto(JsonSerializer)).ToList());
@ -65,20 +74,24 @@ public class OpenIddictScopeAppService : OpenIddictApplicationServiceBase, IOpen
[Authorize(AbpOpenIddictPermissions.Scopes.Update)]
public async virtual Task<OpenIddictScopeDto> UpdateAsync(Guid id, OpenIddictScopeUpdateDto input)
{
var scope = await Repository.GetAsync(id);
var scope = await _scoppeRepository.GetAsync(id);
if (!string.Equals(scope.Name, input.Name) &&
await Repository.FindByNameAsync(input.Name) != null)
await _scoppeRepository.FindByNameAsync(input.Name) != null)
{
throw new BusinessException(OpenIddictApplicationErrorCodes.Scopes.NameExisted)
.WithData(nameof(OpenIddictScope.Name), input.Name);
}
scope.SetConcurrencyStampIfNotNull(input.ConcurrencyStamp);
scope = input.ToEntity(scope, JsonSerializer);
scope = await Repository.UpdateAsync(scope);
var cache = LazyServiceProvider.LazyGetRequiredService<IOpenIddictScopeCache<OpenIddictScopeModel>>();
await CurrentUnitOfWork.SaveChangesAsync();
await cache.RemoveAsync(scope.ToModel(), GetCancellationToken());
await _scoppeRepository.UpdateAsync(scope);
return scope.ToDto(JsonSerializer);
}

30
aspnet-core/modules/openIddict/LINGYUN.Abp.OpenIddict.Application/LINGYUN/Abp/OpenIddict/Tokens/OpenIddictTokenAppService.cs

@ -1,5 +1,6 @@
using LINGYUN.Abp.OpenIddict.Permissions;
using Microsoft.AspNetCore.Authorization;
using OpenIddict.Abstractions;
using System;
using System.Linq;
using System.Linq.Dynamic.Core;
@ -13,31 +14,35 @@ namespace LINGYUN.Abp.OpenIddict.Tokens;
[Authorize(AbpOpenIddictPermissions.Tokens.Default)]
public class OpenIddictTokenAppService : OpenIddictApplicationServiceBase, IOpenIddictTokenAppService
{
protected IRepository<OpenIddictToken, Guid> Repository { get; }
private readonly IOpenIddictTokenManager _tokenManager;
private readonly IRepository<OpenIddictToken, Guid> _tokenRepository;
public OpenIddictTokenAppService(IRepository<OpenIddictToken, Guid> repository)
public OpenIddictTokenAppService(
IOpenIddictTokenManager tokenManager,
IRepository<OpenIddictToken, Guid> tokenRepository)
{
Repository = repository;
_tokenManager = tokenManager;
_tokenRepository = tokenRepository;
}
[Authorize(AbpOpenIddictPermissions.Tokens.Delete)]
public async virtual Task DeleteAsync(Guid id)
{
await Repository.DeleteAsync(id);
var token = await _tokenRepository.GetAsync(id);
await CurrentUnitOfWork.SaveChangesAsync();
await _tokenManager.DeleteAsync(token.ToModel());
}
public async virtual Task<OpenIddictTokenDto> GetAsync(Guid id)
{
var scope = await Repository.GetAsync(id);
var token = await _tokenRepository.GetAsync(id);
return scope.ToDto();
return token.ToDto();
}
public async virtual Task<PagedResultDto<OpenIddictTokenDto>> GetListAsync(OpenIddictTokenGetListInput input)
{
var queryable = await Repository.GetQueryableAsync();
var queryable = await _tokenRepository.GetQueryableAsync();
if (input.ClientId.HasValue)
{
queryable = queryable.Where(x => x.ApplicationId == input.ClientId);
@ -81,8 +86,15 @@ public class OpenIddictTokenAppService : OpenIddictApplicationServiceBase, IOpen
x.Payload.Contains(input.Filter) || x.Properties.Contains(input.Filter) ||
x.ReferenceId.Contains(input.ReferenceId));
}
var sorting = input.Sorting;
if (sorting.IsNullOrWhiteSpace())
{
sorting = $"{nameof(OpenIddictToken.CreationTime)} DESC";
}
queryable = queryable
.OrderBy(input.Sorting ?? $"{nameof(OpenIddictToken.CreationTime)} DESC")
.OrderBy(sorting)
.PageBy(input.SkipCount, input.MaxResultCount);
var totalCount = await AsyncExecuter.CountAsync(queryable);

7
aspnet-core/modules/text-templating/LINGYUN.Abp.TextTemplating.Domain/LINGYUN/Abp/TextTemplating/TemplateDefinitionStoreCacheInvalidator.cs

@ -25,17 +25,20 @@ public class TemplateDefinitionStoreCacheInvalidator :
private readonly IClock _clock;
private readonly IDistributedCache _distributedCache;
private readonly AbpDistributedCacheOptions _cacheOptions;
private readonly AbpTextTemplatingCachingOptions _templatingCachingOptions;
public TemplateDefinitionStoreCacheInvalidator(
IClock clock,
IDistributedCache distributedCache,
ITemplateDefinitionStoreCache storeCache,
IOptions<AbpDistributedCacheOptions> cacheOptions)
IOptions<AbpDistributedCacheOptions> cacheOptions,
IOptions<AbpTextTemplatingCachingOptions> templatingCachingOptions)
{
_storeCache = storeCache;
_clock = clock;
_distributedCache = distributedCache;
_cacheOptions = cacheOptions.Value;
_templatingCachingOptions = templatingCachingOptions.Value;
}
public async virtual Task HandleEventAsync(EntityChangedEventData<TextTemplateDefinition> eventData)
@ -67,7 +70,7 @@ public class TemplateDefinitionStoreCacheInvalidator :
await _distributedCache.RemoveAsync(cacheKey);
_storeCache.CacheStamp = Guid.NewGuid().ToString();
_storeCache.LastCheckTime = _clock.Now.AddMinutes(-5);
_storeCache.LastCheckTime = _clock.Now.Subtract(_templatingCachingOptions.TemplateDefinitionsCacheRefreshInterval);
}
}

2
aspnet-core/services/LY.MicroService.Applications.Single/MicroServiceApplicationsSingleModule.Configure.cs

@ -84,7 +84,7 @@ public partial class MicroServiceApplicationsSingleModule
{
builder.AddValidation(options =>
{
options.AddAudiences("lingyun-abp-application");
//options.AddAudiences("lingyun-abp-application");
options.UseLocalServer();

2
aspnet-core/services/LY.MicroService.Applications.Single/appsettings.Development.json

@ -110,7 +110,7 @@
},
"AuthServer": {
"UseOpenIddict": false,
"Authority": "http://127.0.0.1:44385/",
"Authority": "http://127.0.0.1:30000/",
"ApiName": "lingyun-abp-application",
"SwaggerClientId": "InternalServiceClient",
"SwaggerClientSecret": "1q2w3E*"

Loading…
Cancel
Save