@@ -26,6 +26,12 @@ export const RBACManagementModal = ({ open, handleClose, currentRole, createNoti
2626 const [ labels , setLabels ] = useState ( [ ] ) ;
2727 const [ allowList , setAllowList ] = useState ( [ ] ) ;
2828 const [ denyList , setDenyList ] = useState ( [ ] ) ;
29+ const [ fixedAllowList , setFixedAllowList ] = useState ( [ ] ) ;
30+ const [ fixedDenyList , setFixedDenyList ] = useState ( [ ] ) ;
31+ const [ denyCompleted , setDenyCompleted ] = useState ( false ) ;
32+ const [ allowCompleted , setAllowCompleted ] = useState ( false ) ;
33+ const [ usersCompleted , setUsersCompleted ] = useState ( false ) ;
34+ const [ failed , setFailed ] = useState ( false ) ;
2935
3036 useEffect ( ( ) => {
3137 if ( ! open ) {
@@ -35,10 +41,23 @@ export const RBACManagementModal = ({ open, handleClose, currentRole, createNoti
3541 setSelectedDatabase ( '' ) ;
3642 return ;
3743 }
44+ setDenyCompleted ( false ) ;
45+ setAllowCompleted ( false ) ;
46+ setUsersCompleted ( false ) ;
47+ setFailed ( false ) ;
3848 retrieveDatabaseList ( driver , setDatabases ) ;
3949 retrieveNeo4jUsers ( driver , currentRole , setNeo4jUsers , setSelectedUsers ) ;
4050 } , [ open ] ) ;
4151
52+ useEffect ( ( ) => {
53+ console . log ( [ denyCompleted , allowCompleted , usersCompleted , failed ] ) ;
54+ if ( failed !== false ) {
55+ createNotification ( 'Unable to update privileges' , `${ failed } ` ) ;
56+ } else if ( denyCompleted && allowCompleted && usersCompleted ) {
57+ createNotification ( 'Success' , `Access for role '${ currentRole } ' updated.` ) ;
58+ }
59+ } , [ denyCompleted , allowCompleted , usersCompleted , failed ] ) ;
60+
4261 const parseLabelsList = ( database , records ) => {
4362 const allLabels = records . map ( ( record ) => record . _fields [ 0 ] ) . filter ( ( l ) => l !== '_Neodash_Dashboard' ) ;
4463 retrieveAllowAndDenyLists (
@@ -49,6 +68,8 @@ export const RBACManagementModal = ({ open, handleClose, currentRole, createNoti
4968 setLabels ,
5069 setAllowList ,
5170 setDenyList ,
71+ setFixedAllowList ,
72+ setFixedDenyList ,
5273 setLoaded
5374 ) ;
5475 } ;
@@ -58,16 +79,49 @@ export const RBACManagementModal = ({ open, handleClose, currentRole, createNoti
5879 retrieveLabelsList ( driver , selectedOption . value , ( records ) => parseLabelsList ( selectedOption . value , records ) ) ;
5980 } ;
6081
61- const handleSave = ( ) => {
62- updateUsers ( driver , currentRole , neo4jUsers , selectedUsers ) ;
82+ const handleSave = async ( ) => {
83+ createNotification ( 'Updating' , `Access for role '${ currentRole } ' is being updated, please wait...` ) ;
84+ console . log ( selectedUsers ) ;
85+ updateUsers (
86+ driver ,
87+ currentRole ,
88+ neo4jUsers ,
89+ selectedUsers ,
90+ ( ) => setUsersCompleted ( true ) ,
91+ ( failReason ) => setFailed ( `Operation 'ROLE-USER ASSIGNMENT' failed.\n Reason: ${ failReason } ` )
92+ ) ;
93+
6394 if ( selectedDatabase ) {
64- createNotification ( 'Updating' , `Access for role '${ currentRole } ' is being updated, please wait...` ) ;
65- updatePrivileges ( driver , selectedDatabase , currentRole , labels , denyList , Operation . DENY , createNotification ) ;
66- updatePrivileges ( driver , selectedDatabase , currentRole , labels , allowList , Operation . GRANT , createNotification ) ;
95+ const nonFixedDenyList = denyList . filter ( ( n ) => ! fixedDenyList . includes ( n ) ) ;
96+ const nonFixedAllowList = allowList . filter ( ( n ) => ! fixedDenyList . includes ( n ) ) ;
97+ updatePrivileges (
98+ driver ,
99+ selectedDatabase ,
100+ currentRole ,
101+ labels ,
102+ nonFixedDenyList ,
103+ Operation . DENY ,
104+ ( ) => setDenyCompleted ( true ) ,
105+ ( failReason ) => setFailed ( `Operation 'DENY LABEL ACCESS' failed.\n Reason: ${ failReason } ` )
106+ ) . then ( ( ) => {
107+ updatePrivileges (
108+ driver ,
109+ selectedDatabase ,
110+ currentRole ,
111+ labels ,
112+ nonFixedAllowList ,
113+ Operation . GRANT ,
114+ ( ) => setAllowCompleted ( true ) ,
115+ ( failReason ) => setFailed ( `Operation 'ALLOW LABEL ACCESS' failed.\n Reason: ${ failReason } ` )
116+ ) ;
117+ } ) ;
67118 } else {
68- createNotification ( 'Success' , `Users have been updated for role '${ currentRole } '.` ) ;
119+ // Since there is no database selected, we don't run the DENY/ALLOW queries.
120+ // We just mark them as completed so the success message shows up.
121+ setDenyCompleted ( true ) ;
122+ setAllowCompleted ( true ) ;
69123 }
70-
124+ console . log ( [ denyCompleted , allowCompleted , usersCompleted , failed ] ) ;
71125 handleClose ( ) ;
72126 } ;
73127
@@ -138,7 +192,17 @@ export const RBACManagementModal = ({ open, handleClose, currentRole, createNoti
138192 value : allowList . map ( ( nodelabel ) => ( { value : nodelabel , label : nodelabel } ) ) ,
139193 options : labels . map ( ( nodelabel ) => ( { value : nodelabel , label : nodelabel } ) ) ,
140194 isMulti : true ,
141- onChange : ( val ) => setAllowList ( val . map ( ( v ) => v . value ) ) ,
195+ onChange : ( val ) => {
196+ // Make sure that only database-specific label access rules can be changed from this UI.
197+ if ( fixedAllowList . every ( ( v ) => val . map ( ( selected ) => selected . value ) . includes ( v ) ) ) {
198+ setAllowList ( val . map ( ( v ) => v . value ) ) ;
199+ } else {
200+ createNotification (
201+ 'Label cannot be removed' ,
202+ 'The selected label is allowed access across all databases. You cannot remove this privilege using this interface.'
203+ ) ;
204+ }
205+ } ,
142206 } }
143207 />
144208 </ div >
@@ -154,9 +218,21 @@ export const RBACManagementModal = ({ open, handleClose, currentRole, createNoti
154218 placeholder : 'Select labels' ,
155219 isClearable : false ,
156220 value : denyList . map ( ( nodelabel ) => ( { value : nodelabel , label : nodelabel } ) ) ,
157- options : labels . map ( ( nodelabel ) => ( { value : nodelabel , label : nodelabel } ) ) ,
221+ options : labels
222+ . filter ( ( l ) => l !== '*' )
223+ . map ( ( nodelabel ) => ( { value : nodelabel , label : nodelabel } ) ) ,
158224 isMulti : true ,
159- onChange : ( val ) => setDenyList ( val . map ( ( v ) => v . value ) ) ,
225+ onChange : ( val ) => {
226+ // Make sure that only database-specific label access rules can be changed from this UI.
227+ if ( fixedDenyList . every ( ( v ) => val . map ( ( selected ) => selected . value ) . includes ( v ) ) ) {
228+ setDenyList ( val . map ( ( v ) => v . value ) ) ;
229+ } else {
230+ createNotification (
231+ 'Label cannot be removed' ,
232+ 'The selected label is denied access across all databases. You cannot remove this privilege using this interface.'
233+ ) ;
234+ }
235+ } ,
160236 } }
161237 />
162238 </ div >
0 commit comments