@webitel/ui-datalist 26.12.4 → 26.12.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Readme.md +18 -0
- package/package.json +4 -4
- package/src/index.ts +5 -2
- package/src/modules/filters/modules/filterConfig/components/flow-type/flow-type-filter-value-field.vue +77 -0
- package/src/modules/filters/modules/filterConfig/components/flow-type/flow-type-filter-value-preview.vue +34 -0
- package/src/modules/filters/modules/filterConfig/components/grantee/index.ts +1 -1
- package/src/modules/filters/modules/filterConfig/components/index.ts +14 -0
- package/src/modules/filters/modules/filterConfig/components/tags/index.ts +17 -1
- package/src/modules/filters/modules/filterConfig/components/tags/tags-filter-value-field.vue +12 -2
- package/src/modules/filters/modules/filterConfig/components/trigger-job-state/trigger-job-state-filter-value-field.vue +87 -0
- package/src/modules/filters/modules/filterConfig/components/trigger-job-state/trigger-job-state-filter-value-preview.vue +42 -0
- package/src/modules/filters/modules/filterConfig/composables/useFlowTypeOptions.ts +21 -0
- package/src/modules/filters/modules/filterConfig/enums/FilterOption.ts +3 -0
- package/src/modules/filters/modules/filterConfig/index.ts +6 -1
- package/src/modules/permissions/components/_internal/permissions-role-row.vue +25 -0
- package/src/modules/permissions/components/_internal/permissions-role-select.vue +35 -0
- package/src/modules/permissions/components/_internal/permissions-tab-content.vue +161 -0
- package/src/modules/permissions/components/_internal/permissions-tab-role-popup.vue +94 -0
- package/src/modules/{permissions-page → permissions}/components/permissions-tab.vue +5 -5
- package/src/modules/permissions/composables/useAccessModeOptions.ts +48 -0
- package/src/modules/permissions/index.ts +40 -0
- package/src/modules/permissions/stores/_internals/headers.ts +52 -0
- package/src/modules/{permissions-page → permissions}/stores/createPermissionsStore.ts +19 -44
- package/src/modules/{permissions-page → permissions}/types/Permission.types.ts +2 -2
- package/src/modules/permissions/types/PermissionsUserAccess.ts +10 -0
- package/types/.tsbuildinfo +1 -1
- package/types/index.d.ts +2 -2
- package/types/modules/filter-presets/stores/createFilterPresetsStore.d.ts +1 -1
- package/types/modules/filters/modules/filterConfig/components/flow-type/flow-type-filter-value-field.vue.d.ts +18 -0
- package/types/modules/filters/modules/filterConfig/components/flow-type/flow-type-filter-value-preview.vue.d.ts +6 -0
- package/types/modules/filters/modules/filterConfig/components/grantee/index.d.ts +1 -1
- package/types/modules/filters/modules/filterConfig/components/index.d.ts +6 -2
- package/types/modules/filters/modules/filterConfig/components/tags/index.d.ts +32 -0
- package/types/modules/filters/modules/filterConfig/components/trigger-job-state/trigger-job-state-filter-value-field.vue.d.ts +18 -0
- package/types/modules/filters/modules/filterConfig/components/trigger-job-state/trigger-job-state-filter-value-preview.vue.d.ts +6 -0
- package/types/modules/filters/modules/filterConfig/composables/useFlowTypeOptions.d.ts +7 -0
- package/types/modules/filters/modules/filterConfig/enums/FilterOption.d.ts +3 -0
- package/types/modules/filters/modules/filterConfig/index.d.ts +2 -1
- package/types/modules/permissions/components/_internal/permissions-role-row.vue.d.ts +17 -0
- package/types/modules/permissions/components/_internal/permissions-role-select.vue.d.ts +11 -0
- package/types/modules/permissions/components/_internal/permissions-tab-content.vue.d.ts +32 -0
- package/types/modules/permissions/components/_internal/permissions-tab-role-popup.vue.d.ts +10 -0
- package/types/modules/{permissions-page → permissions}/components/permissions-tab.vue.d.ts +1 -1
- package/types/modules/permissions/composables/useAccessModeOptions.d.ts +22 -0
- package/types/modules/permissions/index.d.ts +17 -0
- package/types/modules/permissions/stores/_internals/headers.d.ts +22 -0
- package/types/modules/{permissions-page → permissions}/stores/createPermissionsStore.d.ts +5 -3
- package/types/modules/{permissions-page → permissions}/types/Permission.types.d.ts +2 -2
- package/types/modules/permissions/types/PermissionsUserAccess.d.ts +3 -0
- package/src/modules/permissions-page/index.ts +0 -23
- package/src/modules/permissions-page/scripts/PermissionsApiModule.ts +0 -57
- package/src/modules/permissions-page/scripts/__tests__/PermissionsApiModule.spec.ts +0 -31
- package/types/modules/permissions-page/index.d.ts +0 -7
- package/types/modules/permissions-page/scripts/PermissionsApiModule.d.ts +0 -9
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<section
|
|
3
|
+
v-if="access.read"
|
|
4
|
+
class="table-section"
|
|
5
|
+
>
|
|
6
|
+
<permissions-tab-role-popup
|
|
7
|
+
v-if="access.create"
|
|
8
|
+
:existing-grantee-ids="existingGranteeIds"
|
|
9
|
+
:add-role-permissions="addRolePermissions"
|
|
10
|
+
/>
|
|
11
|
+
|
|
12
|
+
<header class="table-title permissions-tab-content__header">
|
|
13
|
+
<wt-action-bar
|
|
14
|
+
:include="[IconAction.ADD, IconAction.REFRESH]"
|
|
15
|
+
:disabled:add="!access.create"
|
|
16
|
+
@click:add="openRolePopup"
|
|
17
|
+
@click:refresh="refresh"
|
|
18
|
+
/>
|
|
19
|
+
</header>
|
|
20
|
+
|
|
21
|
+
<div class="table-section__table-wrapper">
|
|
22
|
+
<wt-empty
|
|
23
|
+
v-show="showEmpty"
|
|
24
|
+
:image="imageEmpty"
|
|
25
|
+
:text="textEmpty"
|
|
26
|
+
/>
|
|
27
|
+
|
|
28
|
+
<wt-loader v-show="isLoading" />
|
|
29
|
+
|
|
30
|
+
<div
|
|
31
|
+
v-show="dataList.length && !isLoading"
|
|
32
|
+
class="table-section__visible-scroll-wrapper"
|
|
33
|
+
>
|
|
34
|
+
<wt-table
|
|
35
|
+
:data="localizedDataList"
|
|
36
|
+
:grid-actions="access.update"
|
|
37
|
+
:headers="headers"
|
|
38
|
+
:selectable="false"
|
|
39
|
+
sortable
|
|
40
|
+
@sort="sort"
|
|
41
|
+
>
|
|
42
|
+
<template #grantee="{ item }">
|
|
43
|
+
<permissions-role-row :role="item.grantee" />
|
|
44
|
+
</template>
|
|
45
|
+
|
|
46
|
+
<!-- [Claude] one select per rule column; "create" shows only where the headers have it, e.g. object classes OBAC -->
|
|
47
|
+
<template
|
|
48
|
+
v-for="(ruleName, column) of AccessRuleColumn"
|
|
49
|
+
:key="column"
|
|
50
|
+
#[column]="{ item }"
|
|
51
|
+
>
|
|
52
|
+
<wt-single-select
|
|
53
|
+
:show-clear="false"
|
|
54
|
+
:disabled="!access.update"
|
|
55
|
+
:options="accessOptions"
|
|
56
|
+
:model-value="item.access[ruleName]"
|
|
57
|
+
@update:model-value="changeAccessMode({ item, ruleName, mode: $event })"
|
|
58
|
+
/>
|
|
59
|
+
</template>
|
|
60
|
+
|
|
61
|
+
<template #actions="{ item }">
|
|
62
|
+
<wt-icon-action
|
|
63
|
+
action="delete"
|
|
64
|
+
@click="
|
|
65
|
+
changeAccessMode({
|
|
66
|
+
item,
|
|
67
|
+
ruleName: AccessRuleName.R,
|
|
68
|
+
mode: { id: AccessMode.Forbidden },
|
|
69
|
+
})
|
|
70
|
+
"
|
|
71
|
+
/>
|
|
72
|
+
</template>
|
|
73
|
+
</wt-table>
|
|
74
|
+
</div>
|
|
75
|
+
|
|
76
|
+
<slot name="pagination" />
|
|
77
|
+
</div>
|
|
78
|
+
</section>
|
|
79
|
+
</template>
|
|
80
|
+
|
|
81
|
+
<script setup lang="ts">
|
|
82
|
+
import {
|
|
83
|
+
AccessMode,
|
|
84
|
+
AccessRuleColumn,
|
|
85
|
+
AccessRuleName,
|
|
86
|
+
} from '@webitel/api-services/enums';
|
|
87
|
+
import { IconAction } from '@webitel/ui-sdk/enums';
|
|
88
|
+
import { useTableEmpty } from '@webitel/ui-sdk/src/modules/TableComponentModule/composables/useTableEmpty';
|
|
89
|
+
import { computed } from 'vue';
|
|
90
|
+
import { useRoute, useRouter } from 'vue-router';
|
|
91
|
+
|
|
92
|
+
import type { DatalistTableHeader } from '../../../types/tableStore.types';
|
|
93
|
+
import { useAccessModeOptions } from '../../composables/useAccessModeOptions';
|
|
94
|
+
import type {
|
|
95
|
+
ChangeAccessModePayload,
|
|
96
|
+
PermissionEntity,
|
|
97
|
+
PermissionGrantee,
|
|
98
|
+
} from '../../types/Permission.types';
|
|
99
|
+
import {
|
|
100
|
+
DEFAULT_PERMISSIONS_USER_ACCESS,
|
|
101
|
+
type PermissionsUserAccess,
|
|
102
|
+
} from '../../types/PermissionsUserAccess';
|
|
103
|
+
import PermissionsRoleRow from './permissions-role-row.vue';
|
|
104
|
+
import PermissionsTabRolePopup from './permissions-tab-role-popup.vue';
|
|
105
|
+
|
|
106
|
+
const props = withDefaults(
|
|
107
|
+
defineProps<{
|
|
108
|
+
dataList: PermissionEntity[];
|
|
109
|
+
isLoading?: boolean;
|
|
110
|
+
headers: DatalistTableHeader[];
|
|
111
|
+
error?: unknown;
|
|
112
|
+
refresh: () => unknown;
|
|
113
|
+
sort: (column: DatalistTableHeader) => unknown;
|
|
114
|
+
changeAccessMode: (payload: ChangeAccessModePayload) => unknown;
|
|
115
|
+
existingGranteeIds?: PermissionGrantee['id'][];
|
|
116
|
+
addRolePermissions: (role: PermissionGrantee) => Promise<unknown>;
|
|
117
|
+
access?: PermissionsUserAccess;
|
|
118
|
+
}>(),
|
|
119
|
+
{
|
|
120
|
+
isLoading: false,
|
|
121
|
+
existingGranteeIds: () => [],
|
|
122
|
+
access: () => DEFAULT_PERMISSIONS_USER_ACCESS,
|
|
123
|
+
},
|
|
124
|
+
);
|
|
125
|
+
|
|
126
|
+
const { accessOptions, localizedDataList } = useAccessModeOptions(
|
|
127
|
+
() => props.dataList,
|
|
128
|
+
);
|
|
129
|
+
|
|
130
|
+
const route = useRoute();
|
|
131
|
+
const router = useRouter();
|
|
132
|
+
|
|
133
|
+
/** [Claude] the role popup is opened by the route, so it survives a reload */
|
|
134
|
+
const openRolePopup = () =>
|
|
135
|
+
router.push({
|
|
136
|
+
name: route.name,
|
|
137
|
+
query: route.query,
|
|
138
|
+
hash: route.hash,
|
|
139
|
+
params: {
|
|
140
|
+
...route.params,
|
|
141
|
+
permissionId: 'new',
|
|
142
|
+
},
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
const {
|
|
146
|
+
showEmpty,
|
|
147
|
+
image: imageEmpty,
|
|
148
|
+
text: textEmpty,
|
|
149
|
+
} = useTableEmpty({
|
|
150
|
+
dataList: computed(() => props.dataList),
|
|
151
|
+
error: computed(() => props.error),
|
|
152
|
+
isLoading: computed(() => props.isLoading),
|
|
153
|
+
});
|
|
154
|
+
</script>
|
|
155
|
+
|
|
156
|
+
<style scoped>
|
|
157
|
+
/* [Claude] no title in the header, so push the action bar to the right */
|
|
158
|
+
.permissions-tab-content__header {
|
|
159
|
+
justify-content: flex-end;
|
|
160
|
+
}
|
|
161
|
+
</style>
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<wt-popup
|
|
3
|
+
:shown="shown"
|
|
4
|
+
overflow
|
|
5
|
+
size="sm"
|
|
6
|
+
@close="close"
|
|
7
|
+
>
|
|
8
|
+
<template #title>
|
|
9
|
+
{{ `${t('reusable.new')} ${t('objects.grantee', 1).toLowerCase()}` }}
|
|
10
|
+
</template>
|
|
11
|
+
<template #main>
|
|
12
|
+
<permissions-role-select
|
|
13
|
+
v-model:model-value="grantee"
|
|
14
|
+
:clearable="false"
|
|
15
|
+
:placeholder="t('objects.role', 1)"
|
|
16
|
+
:search-method="getAvailableGrantees"
|
|
17
|
+
/>
|
|
18
|
+
</template>
|
|
19
|
+
<template #actions>
|
|
20
|
+
<wt-button @click="save(grantee)">
|
|
21
|
+
{{ t('reusable.add') }}
|
|
22
|
+
</wt-button>
|
|
23
|
+
<wt-button
|
|
24
|
+
color="secondary"
|
|
25
|
+
@click="close"
|
|
26
|
+
>
|
|
27
|
+
{{ t('reusable.close') }}
|
|
28
|
+
</wt-button>
|
|
29
|
+
</template>
|
|
30
|
+
</wt-popup>
|
|
31
|
+
</template>
|
|
32
|
+
|
|
33
|
+
<script setup lang="ts">
|
|
34
|
+
import { RolesAPI } from '@webitel/api-services/api';
|
|
35
|
+
import { computed, ref } from 'vue';
|
|
36
|
+
import { useI18n } from 'vue-i18n';
|
|
37
|
+
import { useRoute, useRouter } from 'vue-router';
|
|
38
|
+
|
|
39
|
+
import type { PermissionGrantee } from '../../types/Permission.types';
|
|
40
|
+
import PermissionsRoleSelect from './permissions-role-select.vue';
|
|
41
|
+
|
|
42
|
+
const props = withDefaults(
|
|
43
|
+
defineProps<{
|
|
44
|
+
existingGranteeIds?: PermissionGrantee['id'][];
|
|
45
|
+
addRolePermissions: (role: PermissionGrantee) => Promise<unknown>;
|
|
46
|
+
}>(),
|
|
47
|
+
{
|
|
48
|
+
existingGranteeIds: () => [],
|
|
49
|
+
},
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
const { t } = useI18n();
|
|
53
|
+
const router = useRouter();
|
|
54
|
+
const route = useRoute();
|
|
55
|
+
|
|
56
|
+
const grantee = ref<PermissionGrantee | null>(null);
|
|
57
|
+
|
|
58
|
+
/** [Claude] opened by the route, the tab's "add" action sets `permissionId` */
|
|
59
|
+
const shown = computed(() => !!route.params.permissionId);
|
|
60
|
+
|
|
61
|
+
const close = () => {
|
|
62
|
+
const { query, hash, name } = route;
|
|
63
|
+
const { permissionId, ...params } = route.params;
|
|
64
|
+
|
|
65
|
+
grantee.value = null;
|
|
66
|
+
|
|
67
|
+
return router.push({
|
|
68
|
+
query,
|
|
69
|
+
hash,
|
|
70
|
+
name,
|
|
71
|
+
params,
|
|
72
|
+
});
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
const getAvailableGrantees = async (params: Record<string, unknown>) => {
|
|
76
|
+
const { items, ...rest } = await RolesAPI.getLookup(params);
|
|
77
|
+
return {
|
|
78
|
+
/** [Claude] acl grantee ids come as strings, role ids as numbers */
|
|
79
|
+
items: (items as PermissionGrantee[]).filter(
|
|
80
|
+
(role) =>
|
|
81
|
+
!props.existingGranteeIds.some((id) => String(id) === String(role.id)),
|
|
82
|
+
),
|
|
83
|
+
...rest,
|
|
84
|
+
};
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
const save = async (newGrantee: PermissionGrantee | null) => {
|
|
88
|
+
if (!newGrantee) return;
|
|
89
|
+
await props.addRolePermissions(newGrantee);
|
|
90
|
+
return close();
|
|
91
|
+
};
|
|
92
|
+
</script>
|
|
93
|
+
|
|
94
|
+
<style lang="scss" scoped></style>
|
|
@@ -15,15 +15,15 @@
|
|
|
15
15
|
</template>
|
|
16
16
|
|
|
17
17
|
<script setup lang="ts">
|
|
18
|
-
import {
|
|
19
|
-
DEFAULT_PERMISSIONS_USER_ACCESS,
|
|
20
|
-
PermissionsTabContent,
|
|
21
|
-
type PermissionsUserAccess,
|
|
22
|
-
} from '@webitel/ui-sdk/modules/ObjectPermissions';
|
|
23
18
|
import type { Id } from '@webitel/ui-sdk/src/api/types/ApiModule';
|
|
24
19
|
import { storeToRefs } from 'pinia';
|
|
25
20
|
import { computed, onUnmounted } from 'vue';
|
|
26
21
|
import type { PermissionsPiniaStore } from '../stores/createPermissionsStore';
|
|
22
|
+
import {
|
|
23
|
+
DEFAULT_PERMISSIONS_USER_ACCESS,
|
|
24
|
+
type PermissionsUserAccess,
|
|
25
|
+
} from '../types/PermissionsUserAccess';
|
|
26
|
+
import PermissionsTabContent from './_internal/permissions-tab-content.vue';
|
|
27
27
|
|
|
28
28
|
const props = withDefaults(
|
|
29
29
|
defineProps<{
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { AccessMode } from '@webitel/api-services/enums';
|
|
2
|
+
import { computed, type MaybeRefOrGetter, toValue } from 'vue';
|
|
3
|
+
import { useI18n } from 'vue-i18n';
|
|
4
|
+
|
|
5
|
+
interface AccessModeRow {
|
|
6
|
+
access: Record<
|
|
7
|
+
string,
|
|
8
|
+
{
|
|
9
|
+
id: number;
|
|
10
|
+
}
|
|
11
|
+
>;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/** [Claude] access mode select options, and the rows with a localized name on every rule */
|
|
15
|
+
export const useAccessModeOptions = <Row extends AccessModeRow>(
|
|
16
|
+
dataList: MaybeRefOrGetter<Row[]>,
|
|
17
|
+
) => {
|
|
18
|
+
const { t } = useI18n();
|
|
19
|
+
|
|
20
|
+
const getAccessModeName = (mode: number) => t(`access.accessMode.${mode}`);
|
|
21
|
+
|
|
22
|
+
const accessOptions = computed(() =>
|
|
23
|
+
Object.values(AccessMode).map((mode) => ({
|
|
24
|
+
id: mode,
|
|
25
|
+
name: getAccessModeName(mode),
|
|
26
|
+
})),
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
const localizedDataList = computed(() =>
|
|
30
|
+
toValue(dataList).map((item) => ({
|
|
31
|
+
...item,
|
|
32
|
+
access: Object.fromEntries(
|
|
33
|
+
Object.entries(item.access).map(([rule, value]) => [
|
|
34
|
+
rule,
|
|
35
|
+
{
|
|
36
|
+
...value,
|
|
37
|
+
name: getAccessModeName(value.id),
|
|
38
|
+
},
|
|
39
|
+
]),
|
|
40
|
+
),
|
|
41
|
+
})),
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
return {
|
|
45
|
+
accessOptions,
|
|
46
|
+
localizedDataList,
|
|
47
|
+
};
|
|
48
|
+
};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import PermissionsRoleRow from './components/_internal/permissions-role-row.vue';
|
|
2
|
+
import PermissionsRoleSelect from './components/_internal/permissions-role-select.vue';
|
|
3
|
+
import PermissionsTabContent from './components/_internal/permissions-tab-content.vue';
|
|
4
|
+
import PermissionsRolePopup from './components/_internal/permissions-tab-role-popup.vue';
|
|
5
|
+
import PermissionsTab from './components/permissions-tab.vue';
|
|
6
|
+
|
|
7
|
+
/** [Claude] the acl enums and grants logic live in api-services; re-exported to keep permissions in one place */
|
|
8
|
+
export {
|
|
9
|
+
AccessMode,
|
|
10
|
+
AccessRuleColumn,
|
|
11
|
+
AccessRuleName,
|
|
12
|
+
} from '@webitel/api-services/enums';
|
|
13
|
+
export type { ResolveGrantsParams } from '@webitel/api-services/scripts';
|
|
14
|
+
export { resolveGrants } from '@webitel/api-services/scripts';
|
|
15
|
+
|
|
16
|
+
export { useAccessModeOptions } from './composables/useAccessModeOptions';
|
|
17
|
+
export { headers, headersWithCreate } from './stores/_internals/headers';
|
|
18
|
+
export type { PermissionsPiniaStore } from './stores/createPermissionsStore';
|
|
19
|
+
export {
|
|
20
|
+
createPermissionsStore,
|
|
21
|
+
permissionsStoreBody,
|
|
22
|
+
} from './stores/createPermissionsStore';
|
|
23
|
+
export type {
|
|
24
|
+
ChangeAccessModePayload,
|
|
25
|
+
PermissionAccessRule,
|
|
26
|
+
PermissionEntity,
|
|
27
|
+
PermissionGrantee,
|
|
28
|
+
PermissionsChange,
|
|
29
|
+
RawPermissionsApiModule,
|
|
30
|
+
} from './types/Permission.types';
|
|
31
|
+
export type { PermissionsUserAccess } from './types/PermissionsUserAccess';
|
|
32
|
+
export { DEFAULT_PERMISSIONS_USER_ACCESS } from './types/PermissionsUserAccess';
|
|
33
|
+
|
|
34
|
+
export {
|
|
35
|
+
PermissionsRolePopup,
|
|
36
|
+
PermissionsRoleRow,
|
|
37
|
+
PermissionsRoleSelect,
|
|
38
|
+
PermissionsTab,
|
|
39
|
+
PermissionsTabContent,
|
|
40
|
+
};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { SortSymbols } from '@webitel/ui-sdk/src/scripts/sortQueryAdapters';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* [Claude] Each rule column keeps its own `field` (`r`, `w`, `d`), so sorting
|
|
5
|
+
* one marks only that column and sends `sort=+r` / `+w` / `+d`. `GET
|
|
6
|
+
* <object>/:id/acl` has no such attributes in `fields` though — it returns the
|
|
7
|
+
* three rules merged into one `granted` string — so `PermissionsApiModule`
|
|
8
|
+
* asks for `granted` in their place.
|
|
9
|
+
*/
|
|
10
|
+
export const headers = [
|
|
11
|
+
{
|
|
12
|
+
value: 'grantee',
|
|
13
|
+
locale: 'reusable.name',
|
|
14
|
+
field: 'grantee',
|
|
15
|
+
show: true,
|
|
16
|
+
sort: SortSymbols.NONE,
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
value: 'read',
|
|
20
|
+
locale: 'reusable.read',
|
|
21
|
+
field: 'r',
|
|
22
|
+
show: true,
|
|
23
|
+
sort: SortSymbols.NONE,
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
value: 'edit',
|
|
27
|
+
locale: 'reusable.edit',
|
|
28
|
+
field: 'w',
|
|
29
|
+
show: true,
|
|
30
|
+
sort: SortSymbols.NONE,
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
value: 'delete',
|
|
34
|
+
locale: 'reusable.delete',
|
|
35
|
+
field: 'd',
|
|
36
|
+
show: true,
|
|
37
|
+
sort: SortSymbols.NONE,
|
|
38
|
+
},
|
|
39
|
+
];
|
|
40
|
+
|
|
41
|
+
/** [Claude] object classes OBAC also grants "create" (`x`), right after the grantee */
|
|
42
|
+
export const headersWithCreate = [
|
|
43
|
+
headers[0],
|
|
44
|
+
{
|
|
45
|
+
value: 'create',
|
|
46
|
+
locale: 'reusable.create',
|
|
47
|
+
field: 'granted',
|
|
48
|
+
show: true,
|
|
49
|
+
sort: SortSymbols.NONE,
|
|
50
|
+
},
|
|
51
|
+
...headers.slice(1),
|
|
52
|
+
];
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { AccessRuleName } from '@webitel/api-services/enums';
|
|
2
|
+
import { resolveGrants } from '@webitel/api-services/scripts';
|
|
3
3
|
import type { Id } from '@webitel/ui-sdk/src/api/types/ApiModule';
|
|
4
4
|
import type { StoreGeneric } from 'pinia';
|
|
5
5
|
import { ref } from 'vue';
|
|
@@ -9,49 +9,19 @@ import {
|
|
|
9
9
|
} from '../../_shared/createDatalistStore';
|
|
10
10
|
import { tableStoreBody } from '../../table/createTableStore.store';
|
|
11
11
|
import type { useTableStoreConfig } from '../../types/tableStore.types';
|
|
12
|
-
import { PermissionsApiModule } from '../scripts/PermissionsApiModule';
|
|
13
12
|
import type {
|
|
14
13
|
ChangeAccessModePayload,
|
|
15
14
|
PermissionEntity,
|
|
16
15
|
PermissionsChange,
|
|
17
16
|
RawPermissionsApiModule,
|
|
18
17
|
} from '../types/Permission.types';
|
|
19
|
-
|
|
20
|
-
const resolveModeId = (mode: ChangeAccessModePayload['mode']) =>
|
|
21
|
-
typeof mode === 'number' ? mode : mode?.id;
|
|
22
|
-
|
|
23
|
-
/*
|
|
24
|
-
has | patch | got
|
|
25
|
-
-----+-------+-----
|
|
26
|
-
- | w | w
|
|
27
|
-
w | w | -
|
|
28
|
-
- | ww | ww
|
|
29
|
-
w | ww | ww
|
|
30
|
-
ww | ww | w
|
|
31
|
-
ww | w | -
|
|
32
|
-
*/
|
|
33
|
-
const resolveGrants = ({
|
|
34
|
-
item,
|
|
35
|
-
ruleName,
|
|
36
|
-
mode,
|
|
37
|
-
}: ChangeAccessModePayload): string | null => {
|
|
38
|
-
const have = item.access[ruleName];
|
|
39
|
-
|
|
40
|
-
switch (resolveModeId(mode)) {
|
|
41
|
-
case AccessMode.Forbidden:
|
|
42
|
-
return ruleName;
|
|
43
|
-
case AccessMode.Allow:
|
|
44
|
-
return have.rule || ruleName;
|
|
45
|
-
case AccessMode.Manage:
|
|
46
|
-
return `${ruleName}${ruleName}`;
|
|
47
|
-
default:
|
|
48
|
-
return null;
|
|
49
|
-
}
|
|
50
|
-
};
|
|
18
|
+
import { headers } from './_internals/headers';
|
|
51
19
|
|
|
52
20
|
export const permissionsStoreBody = (
|
|
53
21
|
namespace: string,
|
|
54
22
|
config: useTableStoreConfig<PermissionEntity>,
|
|
23
|
+
/** [Claude] the entity api, whose `patchPermissions` takes acl changes, not a row patch */
|
|
24
|
+
permissionsApi: RawPermissionsApiModule,
|
|
55
25
|
) => {
|
|
56
26
|
const tableStore = tableStoreBody<PermissionEntity>(namespace, config);
|
|
57
27
|
const { dataList, selected, error, isLoading } = makeThisToRefs(
|
|
@@ -78,13 +48,10 @@ export const permissionsStoreBody = (
|
|
|
78
48
|
};
|
|
79
49
|
|
|
80
50
|
const patchPermissions = async (changes: PermissionsChange[]) => {
|
|
51
|
+
if (parentId.value === undefined) return;
|
|
52
|
+
|
|
81
53
|
try {
|
|
82
|
-
await (
|
|
83
|
-
config.apiModule.patch as unknown as (payload: {
|
|
84
|
-
id: Id | undefined;
|
|
85
|
-
changes: PermissionsChange[];
|
|
86
|
-
}) => Promise<unknown>
|
|
87
|
-
)({
|
|
54
|
+
await permissionsApi.patchPermissions({
|
|
88
55
|
id: parentId.value,
|
|
89
56
|
changes,
|
|
90
57
|
});
|
|
@@ -96,7 +63,11 @@ export const permissionsStoreBody = (
|
|
|
96
63
|
};
|
|
97
64
|
|
|
98
65
|
const changeAccessMode = async (payload: ChangeAccessModePayload) => {
|
|
99
|
-
const grants = resolveGrants(
|
|
66
|
+
const grants = resolveGrants({
|
|
67
|
+
have: payload.item.access[payload.ruleName],
|
|
68
|
+
ruleName: payload.ruleName,
|
|
69
|
+
mode: payload.mode,
|
|
70
|
+
});
|
|
100
71
|
if (!grants) return;
|
|
101
72
|
|
|
102
73
|
return patchPermissions([
|
|
@@ -152,12 +123,16 @@ export const createPermissionsStore = (
|
|
|
152
123
|
saved by an older version would keep being sent to the api */
|
|
153
124
|
disablePersistence: true,
|
|
154
125
|
...config,
|
|
155
|
-
|
|
126
|
+
/* [Claude] card apis carry their acl as `getPermissionsList`/`patchPermissions` (generatePermissionsApi); the table only lists it */
|
|
127
|
+
apiModule: {
|
|
128
|
+
getList: config.apiModule.getPermissionsList,
|
|
129
|
+
},
|
|
156
130
|
headers: config.headers || headers,
|
|
157
131
|
};
|
|
158
132
|
|
|
159
133
|
return createDatalistStore({
|
|
160
|
-
storeBody: () =>
|
|
134
|
+
storeBody: () =>
|
|
135
|
+
permissionsStoreBody(namespace, normalizedConfig, config.apiModule),
|
|
161
136
|
namespace,
|
|
162
137
|
config: normalizedConfig,
|
|
163
138
|
});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AccessRuleName } from '@webitel/
|
|
1
|
+
import type { AccessRuleName } from '@webitel/api-services/enums';
|
|
2
2
|
import type { ApiModule, Id } from '@webitel/ui-sdk/src/api/types/ApiModule';
|
|
3
3
|
|
|
4
4
|
export interface PermissionGrantee {
|
|
@@ -29,7 +29,7 @@ export interface PermissionsChange {
|
|
|
29
29
|
* spread into every card API module (e.g. `...generatePermissionsApi(baseUrl)`).
|
|
30
30
|
*/
|
|
31
31
|
export interface RawPermissionsApiModule {
|
|
32
|
-
getPermissionsList: ApiModule<PermissionEntity>['getList']
|
|
32
|
+
getPermissionsList: NonNullable<ApiModule<PermissionEntity>['getList']>;
|
|
33
33
|
patchPermissions: (payload: {
|
|
34
34
|
id: Id;
|
|
35
35
|
changes: PermissionsChange[];
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { CrudAction } from '@webitel/ui-sdk/enums';
|
|
2
|
+
|
|
3
|
+
export type PermissionsUserAccess = Record<CrudAction, boolean>;
|
|
4
|
+
|
|
5
|
+
export const DEFAULT_PERMISSIONS_USER_ACCESS: PermissionsUserAccess = {
|
|
6
|
+
[CrudAction.Read]: false,
|
|
7
|
+
[CrudAction.Create]: false,
|
|
8
|
+
[CrudAction.Update]: false,
|
|
9
|
+
[CrudAction.Delete]: false,
|
|
10
|
+
};
|