11import React from 'react' ;
22
3- import type { Column } from '@gravity-ui/react-data-table' ;
3+ import type { DefinitionListItem } from '@gravity-ui/components' ;
4+ import { DefinitionList } from '@gravity-ui/components' ;
5+ //TODO: fix import
6+ import type { DefinitionListSingleItem } from '@gravity-ui/components/build/esm/components/DefinitionList/types' ;
47
58import { ResponseError } from '../../../components/Errors/ResponseError' ;
69import { Loader } from '../../../components/Loader' ;
7- import { ResizeableDataTable } from '../../../components/ResizeableDataTable/ResizeableDataTable' ;
810import { schemaAclApi } from '../../../store/reducers/schemaAcl/schemaAcl' ;
911import type { TACE } from '../../../types/api/acl' ;
1012import { cn } from '../../../utils/cn' ;
11- import { DEFAULT_TABLE_SETTINGS } from '../../../utils/constants' ;
1213import i18n from '../i18n' ;
1314
1415import './Acl.scss' ;
1516
1617const b = cn ( 'ydb-acl' ) ;
1718
18- const ACL_COLUMNS_WIDTH_LS_KEY = 'aclTableColumnsWidth' ;
19-
20- const TABLE_SETTINGS = {
21- ...DEFAULT_TABLE_SETTINGS ,
22- dynamicRender : false ,
23- stickyTop : 36 ,
24- } ;
25-
2619const prepareLogin = ( value : string | undefined ) => {
2720 if ( value && value . endsWith ( '@staff' ) && ! value . startsWith ( 'svc_' ) ) {
2821 const login = value . split ( '@' ) [ 0 ] ;
@@ -32,76 +25,117 @@ const prepareLogin = (value: string | undefined) => {
3225 return value ;
3326} ;
3427
35- const columns : Column < TACE > [ ] = [
36- {
37- name : 'AccessType' ,
38- header : 'Access Type' ,
39- sortable : false ,
40- render : ( { row} ) => row . AccessType ,
41- } ,
42- {
43- name : 'AccessRights' ,
44- header : 'Access Rights' ,
45- render : ( { row} ) => {
46- return row . AccessRights ?. map ( ( item , index ) => {
47- return < div key = { index } > { item } </ div > ;
48- } ) ;
49- } ,
50- sortable : false ,
51- } ,
52- {
53- name : 'Subject' ,
54- sortable : false ,
55- render : ( { row} ) => {
56- return prepareLogin ( row . Subject ) ;
57- } ,
58- width : 140 ,
59- } ,
60- {
61- name : 'InheritanceType' ,
62- header : 'Inheritance Type' ,
63- render : ( { row} ) => {
64- return row . InheritanceType ?. map ( ( item , index ) => {
65- return < div key = { index } > { item } </ div > ;
66- } ) ;
28+ const aclParams = [ 'access' , 'type' , 'inheritance' ] as const ;
29+
30+ type AclParameter = ( typeof aclParams ) [ number ] ;
31+
32+ const aclParamToName : Record < AclParameter , string > = {
33+ access : 'Access' ,
34+ type : 'Access type' ,
35+ inheritance : 'Inheritance type' ,
36+ } ;
37+
38+ const defaultInheritanceType = [ 'Object' , 'Container' ] ;
39+ const defaultAccessType = 'Allow' ;
40+
41+ const defaultInheritanceTypeSet = new Set ( defaultInheritanceType ) ;
42+
43+ function normalizeAcl ( acl : TACE [ ] ) {
44+ return acl . map ( ( ace ) => {
45+ const { AccessRules = [ ] , AccessRights = [ ] , AccessType, InheritanceType, Subject} = ace ;
46+ const access = AccessRules . concat ( AccessRights ) ;
47+ //"Allow" is default access type. We want to show it only if it isn't default
48+ const type = AccessType === defaultAccessType ? undefined : AccessType ;
49+ let inheritance ;
50+ // ['Object', 'Container'] - is default inheritance type. We want to show it only if it isn't default
51+ if (
52+ InheritanceType ?. length !== defaultInheritanceTypeSet . size ||
53+ InheritanceType . some ( ( t ) => ! defaultInheritanceTypeSet . has ( t ) )
54+ ) {
55+ inheritance = InheritanceType ;
56+ }
57+ return {
58+ access : access . length ? access : undefined ,
59+ type,
60+ inheritance,
61+ Subject,
62+ } ;
63+ } ) ;
64+ }
65+
66+ interface DefinitionValueProps {
67+ value : string | string [ ] ;
68+ }
69+
70+ function DefinitionValue ( { value} : DefinitionValueProps ) {
71+ const normalizedValue = typeof value === 'string' ? [ value ] : value ;
72+ return (
73+ < div className = { b ( 'definition-content' ) } >
74+ { normalizedValue . map ( ( el ) => (
75+ < span key = { el } > { el } </ span >
76+ ) ) }
77+ </ div >
78+ ) ;
79+ }
80+
81+ function getAclListItems ( acl ?: TACE [ ] ) : DefinitionListItem [ ] {
82+ if ( ! acl || ! acl . length ) {
83+ return [ ] ;
84+ }
85+
86+ const normalizedAcl = normalizeAcl ( acl ) ;
87+
88+ return normalizedAcl . map ( ( { Subject, ...data } ) => {
89+ const definedDataEntries = Object . entries ( data ) . filter ( ( [ _key , value ] ) =>
90+ Boolean ( value ) ,
91+ ) as [ AclParameter , string | string [ ] ] [ ] ;
92+
93+ if ( definedDataEntries . length === 1 && definedDataEntries [ 0 ] [ 0 ] === 'access' ) {
94+ return {
95+ name : Subject ,
96+ content : < DefinitionValue value = { definedDataEntries [ 0 ] [ 1 ] } /> ,
97+ } ;
98+ }
99+ return {
100+ label : < span className = { b ( 'group-label' ) } > { Subject } </ span > ,
101+ items : aclParams
102+ . map ( ( key ) => {
103+ const value = data [ key ] ;
104+ if ( value ) {
105+ return {
106+ name : aclParamToName [ key ] ,
107+ content : < DefinitionValue value = { value } /> ,
108+ } ;
109+ }
110+ return undefined ;
111+ } )
112+ . filter ( Boolean ) as DefinitionListSingleItem [ ] ,
113+ } ;
114+ } ) ;
115+ }
116+
117+ function getOwnerItem ( owner ?: string ) {
118+ const preparedOwner = prepareLogin ( owner ) ;
119+ if ( ! preparedOwner ) {
120+ return [ ] ;
121+ }
122+ return [
123+ {
124+ name : < span className = { b ( 'owner' ) } > { preparedOwner } </ span > ,
125+ content : < span className = { b ( 'owner' ) } > { i18n ( 'acl.owner' ) } </ span > ,
67126 } ,
68- sortable : false ,
69- } ,
70- ] ;
127+ ] as DefinitionListItem [ ] ;
128+ }
71129
72130export const Acl = ( { path} : { path : string } ) => {
73131 const { currentData, isFetching, error} = schemaAclApi . useGetSchemaAclQuery ( { path} ) ;
74132
75133 const loading = isFetching && ! currentData ;
76134 const { acl, owner} = currentData || { } ;
77135
78- const renderTable = ( ) => {
79- if ( ! acl || ! acl . length ) {
80- return null ;
81- }
82-
83- return (
84- < ResizeableDataTable
85- columnsWidthLSKey = { ACL_COLUMNS_WIDTH_LS_KEY }
86- columns = { columns }
87- data = { acl }
88- settings = { TABLE_SETTINGS }
89- />
90- ) ;
91- } ;
92-
93- const renderOwner = ( ) => {
94- if ( ! owner ) {
95- return null ;
96- }
136+ const aclListItems = getAclListItems ( acl ) ;
97137
98- return (
99- < div className = { b ( 'owner-container' ) } >
100- < span className = { b ( 'owner-label' ) } > { `${ i18n ( 'acl.owner' ) } : ` } </ span >
101- { prepareLogin ( owner ) }
102- </ div >
103- ) ;
104- } ;
138+ const ownerItem = getOwnerItem ( owner ) ;
105139
106140 if ( loading ) {
107141 return < Loader /> ;
@@ -117,10 +151,16 @@ export const Acl = ({path}: {path: string}) => {
117151
118152 return (
119153 < div className = { b ( ) } >
120- < div className = { b ( 'result' ) } >
121- { renderOwner ( ) }
122- { renderTable ( ) }
123- </ div >
154+ { ownerItem . length ? (
155+ < DefinitionList
156+ items = { ownerItem }
157+ nameMaxWidth = { 200 }
158+ className = { b ( 'owner-container' ) }
159+ />
160+ ) : null }
161+ { aclListItems . length ? (
162+ < DefinitionList items = { aclListItems } nameMaxWidth = { 200 } className = { b ( 'result' ) } />
163+ ) : null }
124164 </ div >
125165 ) ;
126166} ;
0 commit comments