Skip to content

Commit 00c847d

Browse files
committed
feat(ACL): link to new Access section
1 parent 5352b24 commit 00c847d

File tree

3 files changed

+25
-231
lines changed

3 files changed

+25
-231
lines changed

src/containers/Tenant/Acl/Acl.scss

Lines changed: 0 additions & 27 deletions
This file was deleted.

src/containers/Tenant/Acl/Acl.tsx

Lines changed: 23 additions & 199 deletions
Original file line numberDiff line numberDiff line change
@@ -1,208 +1,32 @@
1-
import React from 'react';
1+
import {Button, Flex, Icon, Text} from '@gravity-ui/uikit';
22

3-
import {DefinitionList} from '@gravity-ui/components';
4-
import type {DefinitionListItem} from '@gravity-ui/components';
5-
import {SquareCheck} from '@gravity-ui/icons';
6-
import {Icon} from '@gravity-ui/uikit';
7-
8-
import {ResponseError} from '../../../components/Errors/ResponseError';
9-
import {Loader} from '../../../components/Loader';
10-
import {schemaAclApi} from '../../../store/reducers/schemaAcl/schemaAcl';
11-
import type {TACE} from '../../../types/api/acl';
12-
import {valueIsDefined} from '../../../utils';
13-
import {cn} from '../../../utils/cn';
3+
import {
4+
TENANT_DIAGNOSTICS_TABS_IDS,
5+
TENANT_PAGES_IDS,
6+
} from '../../../store/reducers/tenant/constants';
7+
import {setDiagnosticsTab, setTenantPage} from '../../../store/reducers/tenant/tenant';
8+
import {useTypedDispatch} from '../../../utils/hooks';
149

1510
import i18n from './i18n';
1611

17-
import './Acl.scss';
18-
19-
const b = cn('ydb-acl');
20-
21-
const prepareLogin = (value: string | undefined) => {
22-
if (value && value.endsWith('@staff') && !value.startsWith('svc_')) {
23-
const login = value.split('@')[0];
24-
return login;
25-
}
26-
27-
return value;
28-
};
29-
30-
const aclParams = ['access', 'type', 'inheritance'] as const;
31-
32-
type AclParameter = (typeof aclParams)[number];
33-
34-
const aclParamToName: Record<AclParameter, string> = {
35-
access: 'Access',
36-
type: 'Access type',
37-
inheritance: 'Inheritance type',
38-
};
39-
40-
const defaultInheritanceType = ['Object', 'Container'];
41-
const defaultAccessType = 'Allow';
42-
43-
const defaultInheritanceTypeSet = new Set(defaultInheritanceType);
44-
45-
function normalizeAcl(acl: TACE[]) {
46-
return acl.map((ace) => {
47-
const {AccessRules = [], AccessRights = [], AccessType, InheritanceType, Subject} = ace;
48-
const access = AccessRules.concat(AccessRights);
49-
//"Allow" is default access type. We want to show it only if it isn't default
50-
const type = AccessType === defaultAccessType ? undefined : AccessType;
51-
let inheritance;
52-
// ['Object', 'Container'] - is default inheritance type. We want to show it only if it isn't default
53-
if (
54-
InheritanceType?.length !== defaultInheritanceTypeSet.size ||
55-
InheritanceType.some((t) => !defaultInheritanceTypeSet.has(t))
56-
) {
57-
inheritance = InheritanceType;
58-
}
59-
return {
60-
access: access.length ? access : undefined,
61-
type,
62-
inheritance,
63-
Subject,
64-
};
65-
});
66-
}
12+
import ArrowRightFromSquareIcon from '@gravity-ui/icons/svgs/arrow-right-from-square.svg';
6713

68-
interface DefinitionValueProps {
69-
value: string | string[];
70-
}
14+
export const Acl = () => {
15+
const dispatch = useTypedDispatch();
7116

72-
function DefinitionValue({value}: DefinitionValueProps) {
73-
const normalizedValue = typeof value === 'string' ? [value] : value;
7417
return (
75-
<div className={b('definition-content')}>
76-
{normalizedValue.map((el) => (
77-
<span key={el}>{el}</span>
78-
))}
79-
</div>
80-
);
81-
}
82-
83-
function getAclListItems(acl?: TACE[]): DefinitionListItem[] {
84-
if (!acl || !acl.length) {
85-
return [];
86-
}
87-
88-
const normalizedAcl = normalizeAcl(acl);
89-
90-
return normalizedAcl.map(({Subject, ...data}) => {
91-
const definedDataEntries = Object.entries(data).filter(([_key, value]) =>
92-
Boolean(value),
93-
) as [AclParameter, string | string[]][];
94-
95-
if (definedDataEntries.length === 1 && definedDataEntries[0][0] === 'access') {
96-
return {
97-
name: Subject,
98-
content: <DefinitionValue value={definedDataEntries[0][1]} />,
99-
multilineName: true,
100-
};
101-
}
102-
return {
103-
label: <span className={b('group-label')}>{Subject}</span>,
104-
items: aclParams
105-
.map((key) => {
106-
const value = data[key];
107-
if (value) {
108-
return {
109-
name: aclParamToName[key],
110-
content: <DefinitionValue value={value} />,
111-
multilineName: true,
112-
};
113-
}
114-
return undefined;
115-
})
116-
.filter(valueIsDefined),
117-
};
118-
});
119-
}
120-
121-
function getOwnerItem(owner?: string): DefinitionListItem[] {
122-
const preparedOwner = prepareLogin(owner);
123-
if (!preparedOwner) {
124-
return [];
125-
}
126-
return [
127-
{
128-
name: preparedOwner,
129-
content: i18n('title_owner'),
130-
multilineName: true,
131-
},
132-
];
133-
}
134-
135-
function getInterruptInheritanceItem(flag?: boolean): DefinitionListItem[] {
136-
if (!flag) {
137-
return [];
138-
}
139-
return [
140-
{
141-
name: i18n('title_interupt-inheritance'),
142-
content: <Icon data={SquareCheck} size={20} />,
143-
multilineName: true,
144-
},
145-
];
146-
}
147-
148-
export const Acl = ({path, database}: {path: string; database: string}) => {
149-
const {currentData, isFetching, error} = schemaAclApi.useGetSchemaAclQuery({path, database});
150-
151-
const loading = isFetching && !currentData;
152-
153-
const {acl, effectiveAcl, owner, interruptInheritance} = currentData || {};
154-
155-
const aclListItems = getAclListItems(acl);
156-
const effectiveAclListItems = getAclListItems(effectiveAcl);
157-
158-
const ownerItem = getOwnerItem(owner);
159-
160-
const interruptInheritanceItem = getInterruptInheritanceItem(interruptInheritance);
161-
162-
if (loading) {
163-
return <Loader />;
164-
}
165-
166-
if (error) {
167-
return <ResponseError error={error} />;
168-
}
169-
170-
if (!acl && !owner && !effectiveAcl) {
171-
return <React.Fragment>{i18n('description_empty')}</React.Fragment>;
172-
}
173-
174-
const accessRightsItems = ownerItem.concat(aclListItems);
175-
176-
return (
177-
<div className={b()}>
178-
<AclDefinitionList items={interruptInheritanceItem} />
179-
<AclDefinitionList items={accessRightsItems} title={i18n('title_rights')} />
180-
<AclDefinitionList
181-
items={effectiveAclListItems}
182-
title={i18n('title_effective-rights')}
183-
/>
184-
</div>
18+
<Flex gap={2} alignItems="center">
19+
<Text variant="body-2">{i18n('description_section-moved')}</Text>
20+
<Button
21+
title={i18n('action-open-in-diagnostics')}
22+
onClick={() => {
23+
dispatch(setTenantPage(TENANT_PAGES_IDS.diagnostics));
24+
dispatch(setDiagnosticsTab(TENANT_DIAGNOSTICS_TABS_IDS.access));
25+
}}
26+
size="s"
27+
>
28+
<Icon data={ArrowRightFromSquareIcon} size={14} />
29+
</Button>
30+
</Flex>
18531
);
18632
};
187-
188-
interface AclDefinitionListProps {
189-
items: DefinitionListItem[];
190-
title?: string;
191-
}
192-
193-
function AclDefinitionList({items, title}: AclDefinitionListProps) {
194-
if (!items.length) {
195-
return null;
196-
}
197-
return (
198-
<React.Fragment>
199-
{title && <div className={b('list-title')}>{title}</div>}
200-
<DefinitionList
201-
items={items}
202-
nameMaxWidth={200}
203-
className={b('result', {'no-title': !title})}
204-
responsive
205-
/>
206-
</React.Fragment>
207-
);
208-
}
Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,4 @@
11
{
2-
"title_rights": "Access Rights",
3-
"title_effective-rights": "Effective Access Rights",
4-
"title_owner": "Owner",
5-
"title_interupt-inheritance": "Interrupt inheritance",
6-
"description_empty": "No Acl data"
2+
"description_section-moved": "Section was moved to Diagnostics",
3+
"action-open-in-diagnostics": "Open in Diagnostics"
74
}

0 commit comments

Comments
 (0)