Browse Source

feat(openiddict): 增加授权预览页面.

pull/1056/head
colin 1 year ago
parent
commit
3f6bee9264
  1. 1
      apps/vben5/packages/@abp/identity/src/api/index.ts
  2. 55
      apps/vben5/packages/@abp/identity/src/api/users-lookup.ts
  3. 8
      apps/vben5/packages/@abp/identity/src/constants/permissions.ts
  4. 1
      apps/vben5/packages/@abp/identity/src/index.ts
  5. 10
      apps/vben5/packages/@abp/identity/src/types/users.ts
  6. 5
      apps/vben5/packages/@abp/openiddict/package.json
  7. 151
      apps/vben5/packages/@abp/openiddict/src/components/authorizations/AuthorizationModal.vue
  8. 181
      apps/vben5/packages/@abp/openiddict/src/components/authorizations/AuthorizationTable.vue
  9. 8
      apps/vben5/packages/@abp/openiddict/src/constants/permissions.ts
  10. 2
      apps/vben5/pnpm-workspace.yaml

1
apps/vben5/packages/@abp/identity/src/api/index.ts

@ -0,0 +1 @@
export * as userLookupApi from './users-lookup';

55
apps/vben5/packages/@abp/identity/src/api/users-lookup.ts

@ -0,0 +1,55 @@
import type { ListResultDto } from '@abp/core';
import type {
IdentityUserDto,
UserLookupCountInput,
UserLookupSearchInput,
} from '../types/users';
import { requestClient } from '@abp/request';
/**
* id查询用户
* @param id id
* @returns
*/
export function findByIdApi(id: string): Promise<IdentityUserDto> {
return requestClient.get<IdentityUserDto>(`/api/identity/users/lookup/${id}`);
}
/**
*
* @param userName
* @returns
*/
export function findByUserNameApi(userName: string): Promise<IdentityUserDto> {
return requestClient.get<IdentityUserDto>(
`/api/identity/users/lookup/by-username/${userName}`,
);
}
/**
*
* @param input
* @returns
*/
export function searchApi(
input?: UserLookupSearchInput,
): Promise<ListResultDto<IdentityUserDto>> {
return requestClient.get<ListResultDto<IdentityUserDto>>(
`/api/identity/users/lookup/search`,
{
params: input,
},
);
}
/**
*
* @param input
*/
export function countApi(input?: UserLookupCountInput): Promise<number> {
return requestClient.get<number>(`/api/identity/users/lookup/count`, {
params: input,
});
}

8
apps/vben5/packages/@abp/identity/src/constants/permissions.ts

@ -45,3 +45,11 @@ export const SecurityLogPermissions = {
/** 删除 */
Delete: 'AbpAuditing.SecurityLog.Delete',
};
/**
*
* @deprecated 使.
* @todo abp框架权限定义
*/
export const UserLookupPermissions = {
Default: 'AbpIdentity.UserLookup',
};

1
apps/vben5/packages/@abp/identity/src/index.ts

@ -1,3 +1,4 @@
export * from './api';
export * from './components';
export * from './constants';
export * from './types';

10
apps/vben5/packages/@abp/identity/src/types/users.ts

@ -90,6 +90,14 @@ interface GetUserPagedListInput extends PagedAndSortedResultRequestDto {
type IdentityUserCreateDto = IdentityUserCreateOrUpdateDto;
type IdentityUserUpdateDto = IdentityUserCreateOrUpdateDto;
interface UserLookupCountInput {
filter?: string;
}
interface UserLookupSearchInput
extends UserLookupCountInput,
PagedAndSortedResultRequestDto {}
export type {
ChangeMyPasswordInput,
ChangeUserPasswordInput,
@ -98,4 +106,6 @@ export type {
IdentityUserDto,
IdentityUserOrganizationUnitUpdateDto,
IdentityUserUpdateDto,
UserLookupCountInput,
UserLookupSearchInput,
};

5
apps/vben5/packages/@abp/openiddict/package.json

@ -21,6 +21,7 @@
},
"dependencies": {
"@abp/core": "workspace:*",
"@abp/identity": "workspace:*",
"@abp/permission": "workspace:*",
"@abp/request": "workspace:*",
"@abp/ui": "workspace:*",
@ -32,7 +33,11 @@
"@vben/layouts": "workspace:*",
"@vben/locales": "workspace:*",
"ant-design-vue": "catalog:",
"lodash.debounce": "catalog:",
"vue": "catalog:*",
"vxe-table": "catalog:"
},
"devDependencies": {
"@types/lodash.debounce": "catalog:"
}
}

151
apps/vben5/packages/@abp/openiddict/src/components/authorizations/AuthorizationModal.vue

@ -1,7 +1,154 @@
<script setup lang="ts"></script>
<script setup lang="ts">
import type { OpenIddictAuthorizationDto } from '../../types';
import { useAccess } from '@vben/access';
import { useVbenForm, useVbenModal } from '@vben/common-ui';
import { $t } from '@vben/locales';
import {
type IdentityUserDto,
userLookupApi,
UserLookupPermissions,
} from '@abp/identity';
import { CodeEditor } from '@abp/ui';
import { Select } from 'ant-design-vue';
import { getApi as getApplication } from '../../api/applications';
import { getApi as getAuthorization } from '../../api/authorizations';
defineOptions({
name: 'AuthorizationModal',
});
const Option = Select.Option;
const { hasAccessByCodes } = useAccess();
const [Form, formApi] = useVbenForm({
commonConfig: {
//
componentProps: {
class: 'w-full',
},
},
schema: [
{
component: 'Input',
componentProps: {
readonly: true,
},
fieldName: 'applicationId',
label: $t('AbpOpenIddict.DisplayName:ApplicationId'),
},
{
component: 'Input',
componentProps: {
readonly: true,
},
fieldName: 'subject',
label: $t('AbpOpenIddict.DisplayName:Subject'),
},
{
component: 'Input',
componentProps: {
readonly: true,
},
fieldName: 'type',
label: $t('AbpOpenIddict.DisplayName:Type'),
},
{
component: 'Input',
componentProps: {
readonly: true,
},
fieldName: 'creationDate',
label: $t('AbpOpenIddict.DisplayName:CreationDate'),
},
{
component: 'Input',
componentProps: {
readonly: true,
},
fieldName: 'status',
label: $t('AbpOpenIddict.DisplayName:Status'),
},
{
component: 'Input',
componentProps: {
readonly: true,
},
fieldName: 'scopes',
label: $t('AbpOpenIddict.DisplayName:Scopes'),
},
{
component: 'Input',
componentProps: {
readonly: true,
},
fieldName: 'properties',
label: $t('AbpOpenIddict.DisplayName:Properties'),
},
],
showDefaultActions: false,
});
const [Modal, modalApi] = useVbenModal({
class: 'w-1/2',
draggable: true,
fullscreenButton: false,
onCancel() {
modalApi.close();
},
async onOpenChange(isOpen) {
if (isOpen) {
try {
modalApi.setState({ loading: true });
const { id } = modalApi.getData<OpenIddictAuthorizationDto>();
await onGet(id);
} finally {
modalApi.setState({ loading: false });
}
}
},
showConfirmButton: false,
title: $t('AbpOpenIddict.Authorizations'),
});
async function onGet(id: string) {
const authorization = await getAuthorization(id);
const application = await getApplication(authorization.applicationId!);
let subjectInfo: IdentityUserDto | undefined;
if (hasAccessByCodes([UserLookupPermissions.Default])) {
subjectInfo = await userLookupApi.findByIdApi(authorization.subject!);
}
formApi.setValues({
...authorization,
applicationId: `${application.clientId}(${authorization.applicationId})`,
subject: subjectInfo?.userName
? `${subjectInfo.userName}(${authorization.subject})`
: authorization.subject,
});
}
</script>
<template>
<div></div>
<Modal>
<Form>
<template #scopes="{ modelValue }">
<Select :disabled="true" :value="modelValue" mode="tags">
<Option
v-for="scope in modelValue"
:key="scope"
:title="scope"
:value="scope"
/>
</Select>
</template>
<template #properties="{ modelValue }">
<CodeEditor :value="modelValue" readonly />
</template>
</Form>
</Modal>
</template>
<style scoped></style>

181
apps/vben5/packages/@abp/openiddict/src/components/authorizations/AuthorizationTable.vue

@ -1,25 +1,26 @@
<script setup lang="ts">
import type { VbenFormProps, VxeGridProps } from '@abp/ui';
import type { SelectValue } from 'ant-design-vue/es/select';
import type { OpenIddictApplicationDto } from '../../types';
import type { OpenIddictAuthorizationDto } from '../../types/authorizations';
import { defineAsyncComponent, h } from 'vue';
import { defineAsyncComponent, h, onMounted, ref } from 'vue';
import { useAccess } from '@vben/access';
import { useVbenModal } from '@vben/common-ui';
import { createIconifyIcon } from '@vben/icons';
import { $t } from '@vben/locales';
import { formatToDateTime } from '@abp/core';
import { useVbenVxeGrid } from '@abp/ui';
import {
DeleteOutlined,
EditOutlined,
PlusOutlined,
} from '@ant-design/icons-vue';
import { Button, message, Modal } from 'ant-design-vue';
import { DeleteOutlined, EditOutlined } from '@ant-design/icons-vue';
import { Button, message, Modal, Select } from 'ant-design-vue';
import debounce from 'lodash.debounce';
import { getPagedListApi as getApplications } from '../../api/applications';
import { deleteApi, getPagedListApi } from '../../api/authorizations';
import { ApplicationsPermissions } from '../../constants/permissions';
import { AuthorizationsPermissions } from '../../constants/permissions';
defineOptions({
name: 'AuthorizationTable',
@ -30,10 +31,55 @@ const CloseIcon = createIconifyIcon('ant-design:close-outlined');
const { hasAccessByCodes } = useAccess();
const applications = ref<OpenIddictApplicationDto[]>([]);
const formOptions: VbenFormProps = {
//
collapsed: false,
collapsed: true,
collapsedRows: 2,
//
commonConfig: {
// label
colon: true,
//
componentProps: {
class: 'w-full',
},
},
fieldMappingTime: [
['creationTime', ['beginCreationTime', 'endCreationTime'], 'YYYY-MM-DD'],
],
handleReset: onFormReset,
schema: [
{
component: 'Select',
fieldName: 'clientId',
formItemClass: 'col-span-1/3 items-baseline',
label: $t('AbpOpenIddict.DisplayName:ClientId'),
},
{
component: 'RangePicker',
fieldName: 'creationTime',
formItemClass: 'col-span-2 items-baseline',
label: $t('AbpOpenIddict.DisplayName:CreationTime'),
},
{
component: 'Input',
fieldName: 'subject',
formItemClass: 'col-span-1/3 items-baseline',
label: $t('AbpOpenIddict.DisplayName:Subject'),
},
{
component: 'Input',
fieldName: 'status',
formItemClass: 'col-span-1/3 items-baseline',
label: $t('AbpOpenIddict.DisplayName:Status'),
},
{
component: 'Input',
fieldName: 'type',
formItemClass: 'col-span-1/3 items-baseline',
label: $t('AbpOpenIddict.DisplayName:Type'),
},
{
component: 'Input',
fieldName: 'filter',
@ -51,55 +97,43 @@ const gridOptions: VxeGridProps<OpenIddictAuthorizationDto> = {
columns: [
{
align: 'left',
field: 'clientId',
minWidth: 150,
title: $t('AbpOpenIddict.DisplayName:ClientId'),
field: 'applicationId',
minWidth: 300,
title: $t('AbpOpenIddict.DisplayName:ApplicationId'),
},
{
align: 'left',
field: 'displayName',
minWidth: 150,
title: $t('AbpOpenIddict.DisplayName:DisplayName'),
field: 'subject',
minWidth: 300,
title: $t('AbpOpenIddict.DisplayName:Subject'),
},
{
align: 'center',
field: 'consentType',
title: $t('AbpOpenIddict.DisplayName:ConsentType'),
width: 200,
},
{
align: 'center',
field: 'clientType',
title: $t('AbpOpenIddict.DisplayName:ClientType'),
width: 120,
},
{
align: 'center',
field: 'applicationType',
title: $t('AbpOpenIddict.DisplayName:ApplicationType'),
width: 150,
align: 'left',
field: 'type',
minWidth: 150,
title: $t('AbpOpenIddict.DisplayName:Type'),
},
{
align: 'left',
field: 'clientUri',
title: $t('AbpOpenIddict.DisplayName:ClientUri'),
width: 150,
field: 'status',
minWidth: 150,
title: $t('AbpOpenIddict.DisplayName:Status'),
},
{
align: 'left',
field: 'logoUri',
title: $t('AbpOpenIddict.DisplayName:LogoUri'),
width: 120,
field: 'creationDate',
formatter: ({ cellValue }) => {
return cellValue ? formatToDateTime(cellValue) : cellValue;
},
minWidth: 200,
title: $t('AbpOpenIddict.DisplayName:CreationDate'),
},
{
field: 'action',
fixed: 'right',
slots: { default: 'action' },
title: $t('AbpUi.Actions'),
visible: hasAccessByCodes([
ApplicationsPermissions.Update,
ApplicationsPermissions.Delete,
]),
visible: hasAccessByCodes([AuthorizationsPermissions.Delete]),
width: 220,
},
],
@ -134,47 +168,65 @@ const [AuthorizationModal, modalApi] = useVbenModal({
),
});
const [Grid, { query }] = useVbenVxeGrid({
const [Grid, gridApi] = useVbenVxeGrid({
formOptions,
gridOptions,
});
const onCreate = () => {
modalApi.setData({});
modalApi.open();
};
const onSearchClient = debounce(async (filter?: string) => {
const { items } = await getApplications({
filter,
maxResultCount: 25,
});
applications.value = items;
}, 500);
const onUpdate = (row: OpenIddictAuthorizationDto) => {
function onChangeClient(value?: SelectValue) {
gridApi.formApi.setFieldValue('clientId', value);
}
function onUpdate(row: OpenIddictAuthorizationDto) {
modalApi.setData(row);
modalApi.open();
};
}
const onDelete = (row: OpenIddictAuthorizationDto) => {
function onDelete(row: OpenIddictAuthorizationDto) {
Modal.confirm({
centered: true,
content: `${$t('AbpUi.ItemWillBeDeletedMessageWithFormat')}`,
content: `${$t('AbpUi.ItemWillBeDeletedMessage')}`,
onOk: () => {
return deleteApi(row.id).then(() => {
message.success($t('AbpUi.SuccessfullyDeleted'));
query();
gridApi.query();
});
},
title: $t('AbpUi.AreYouSure'),
});
};
}
function onFormReset() {
gridApi.formApi.resetForm();
gridApi.formApi.submitForm();
}
onMounted(onSearchClient);
</script>
<template>
<Grid :table-title="$t('AbpOpenIddict.Applications')">
<template #toolbar-tools>
<Button
:icon="h(PlusOutlined)"
type="primary"
v-access:code="[ApplicationsPermissions.Create]"
@click="onCreate"
>
{{ $t('AbpOpenIddict.Applications:AddNew') }}
</Button>
<Grid :table-title="$t('AbpOpenIddict.Authorizations')">
<template #form-clientId="{ modelValue }">
<Select
:default-active-first-option="false"
:field-names="{ label: 'clientId', value: 'id' }"
:filter-option="false"
:options="applications"
:placeholder="$t('ui.placeholder.select')"
:value="modelValue"
allow-clear
class="w-full"
show-search
@change="onChangeClient"
@search="onSearchClient"
/>
</template>
<template #required="{ row }">
<div class="flex flex-row justify-center">
@ -195,7 +247,6 @@ const onDelete = (row: OpenIddictAuthorizationDto) => {
:icon="h(EditOutlined)"
block
type="link"
v-access:code="[ApplicationsPermissions.Update]"
@click="onUpdate(row)"
>
{{ $t('AbpUi.Edit') }}
@ -207,7 +258,7 @@ const onDelete = (row: OpenIddictAuthorizationDto) => {
block
danger
type="link"
v-access:code="[ApplicationsPermissions.Delete]"
v-access:code="[AuthorizationsPermissions.Delete]"
@click="onDelete(row)"
>
{{ $t('AbpUi.Delete') }}
@ -216,7 +267,7 @@ const onDelete = (row: OpenIddictAuthorizationDto) => {
</div>
</template>
</Grid>
<AuthorizationModal @change="() => query()" />
<AuthorizationModal @change="() => gridApi.query()" />
</template>
<style lang="scss" scoped></style>

8
apps/vben5/packages/@abp/openiddict/src/constants/permissions.ts

@ -14,3 +14,11 @@ export const ApplicationsPermissions = {
/** 更新 */
Update: 'AbpOpenIddict.Applications.Update',
};
/** 授权权限 */
export const AuthorizationsPermissions = {
/** 新增 */
Create: 'AbpOpenIddict.Authorizations.Create',
Default: 'AbpOpenIddict.Authorizations',
/** 删除 */
Delete: 'AbpOpenIddict.Authorizations.Delete',
};

2
apps/vben5/pnpm-workspace.yaml

@ -46,6 +46,7 @@ catalog:
'@types/html-minifier-terser': ^7.0.2
'@types/jsonwebtoken': ^9.0.7
'@types/lodash.clonedeep': ^4.5.9
'@types/lodash.debounce': ^4.0.9
'@types/lodash.get': ^4.4.9
'@types/lodash.isequal': ^4.5.8
'@types/lodash.merge': ^4.6.9
@ -119,6 +120,7 @@ catalog:
jsonwebtoken: ^9.0.2
lint-staged: ^15.2.11
lodash.clonedeep: ^4.5.0
lodash.debounce: ^4.0.8
lodash.get: ^4.4.2
lodash.isequal: ^4.5.0
lodash.merge: ^4.6.2

Loading…
Cancel
Save