2021-09-20 13:02:41 +05:30
/////////////////////////////////////////////////////////////
//
// pgAdmin 4 - PostgreSQL Tools
//
2024-01-01 14:13:48 +05:30
// Copyright (C) 2013 - 2024, The pgAdmin Development Team
2021-09-20 13:02:41 +05:30
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////
import gettext from 'sources/gettext' ;
import _ from 'lodash' ;
import url _for from 'sources/url_for' ;
2024-05-07 16:31:04 +05:30
import React , { useEffect } from 'react' ;
2024-04-09 08:21:14 +05:30
import { Box } from '@mui/material' ;
2021-12-16 18:29:44 +05:30
import Wizard from '../../../../static/js/helpers/wizard/Wizard' ;
import WizardStep from '../../../../static/js/helpers/wizard/WizardStep' ;
2021-09-23 14:40:38 +05:30
import PgTable from 'sources/components/PgTable' ;
2021-12-16 18:29:44 +05:30
import { getNodePrivilegeRoleSchema } from '../../../../../pgadmin/browser/server_groups/servers/static/js/privilege.ui.js' ;
2022-03-30 12:06:59 +05:30
import { InputSQL , FormFooterMessage , MESSAGE _TYPE } from '../../../../static/js/components/FormComponents' ;
2021-12-16 18:29:44 +05:30
import getApiInstance from '../../../../static/js/api_instance' ;
import SchemaView from '../../../../static/js/SchemaView' ;
2021-09-20 13:02:41 +05:30
import PropTypes from 'prop-types' ;
2021-12-16 18:29:44 +05:30
import PrivilegeSchema from './privilege_schema.ui' ;
2024-12-16 14:52:56 +05:30
import { usePgAdmin } from '../../../../static/js/PgAdminProvider' ;
2021-09-20 13:02:41 +05:30
2022-07-28 10:14:04 +05:30
export default function GrantWizard ( { sid , did , nodeInfo , nodeData , onClose } ) {
2024-06-06 17:13:12 +05:30
2022-09-08 15:16:48 +05:30
let columns = [
2021-09-20 13:02:41 +05:30
{
2024-05-07 16:31:04 +05:30
header : 'Object Type' ,
accessorKey : 'object_type' ,
enableSorting : true ,
enableResizing : false ,
enableFilters : false
2021-09-20 13:02:41 +05:30
} ,
{
2024-05-07 16:31:04 +05:30
header : 'Schema' ,
accessorKey : 'nspname' ,
enableSorting : true ,
enableResizing : false ,
enableFilters : false
2021-09-20 13:02:41 +05:30
} ,
{
2024-05-07 16:31:04 +05:30
header : 'Name' ,
accessorKey : 'name_with_args' ,
enableSorting : true ,
enableResizing : true ,
enableFilters : true ,
minSize : 280
2021-09-30 10:56:51 +05:30
} ,
{
2024-05-07 16:31:04 +05:30
header : 'parameters' ,
accessorKey : 'proargs' ,
enableSorting : false ,
enableResizing : false ,
enableFilters : true ,
enableVisibility : false ,
2021-09-30 10:56:51 +05:30
minWidth : 280 ,
} ,
{
2024-05-07 16:31:04 +05:30
header : 'Name' ,
accessorKey : 'name' ,
enableSorting : false ,
enableResizing : false ,
enableFilters : true ,
enableVisibility : false ,
2021-09-30 10:56:51 +05:30
minWidth : 280 ,
} ,
{
2024-05-07 16:31:04 +05:30
header : 'ID' ,
accessorKey : 'oid' ,
enableSorting : false ,
enableResizing : false ,
enableFilters : true ,
enableVisibility : false ,
2021-09-30 10:56:51 +05:30
minWidth : 280 ,
2021-09-20 13:02:41 +05:30
}
] ;
2022-09-08 15:16:48 +05:30
let steps = [ gettext ( 'Object Selection' ) , gettext ( 'Privilege Selection' ) , gettext ( 'Review' ) ] ;
2024-05-07 16:31:04 +05:30
const [ selectedRows , setSelectedRows ] = React . useState ( { } ) ;
2021-09-20 13:02:41 +05:30
const [ selectedAcl , setSelectedAcl ] = React . useState ( { } ) ;
2024-04-09 19:18:56 +05:30
const [ msqlData , setMSQLData ] = React . useState ( '' ) ;
2021-09-20 13:02:41 +05:30
const [ loaderText , setLoaderText ] = React . useState ( '' ) ;
2024-04-09 19:18:56 +05:30
const [ tableData , setTableData ] = React . useState ( [ ] ) ;
2021-09-20 13:02:41 +05:30
const [ privOptions , setPrivOptions ] = React . useState ( { } ) ;
2024-05-07 16:31:04 +05:30
const selectedObject = React . useRef ( [ ] ) ;
const privileges = React . useRef ( [ ] ) ;
2021-09-20 13:02:41 +05:30
const [ privSchemaInstance , setPrivSchemaInstance ] = React . useState ( ) ;
const [ errMsg , setErrMsg ] = React . useState ( '' ) ;
2023-10-23 17:43:17 +05:30
const pgAdmin = usePgAdmin ( ) ;
2021-09-20 13:02:41 +05:30
const api = getApiInstance ( ) ;
const validatePrivilege = ( ) => {
2022-09-08 15:16:48 +05:30
let isValid = true ;
2021-09-20 13:02:41 +05:30
selectedAcl . privilege . forEach ( ( priv ) => {
if ( ( _ . isUndefined ( priv . grantee ) || _ . isUndefined ( priv . privileges ) || priv . privileges . length === 0 ) && isValid ) {
isValid = false ;
}
} ) ;
return ! isValid ;
} ;
React . useEffect ( ( ) => {
2022-01-21 18:53:48 +05:30
const privSchema = new PrivilegeSchema ( ( privs ) => getNodePrivilegeRoleSchema ( '' , nodeInfo , nodeData , privs ) ) ;
2021-09-20 13:02:41 +05:30
setPrivSchemaInstance ( privSchema ) ;
setLoaderText ( 'Loading...' ) ;
api . get ( url _for (
'grant_wizard.acl' , {
'sid' : encodeURI ( sid ) ,
'did' : encodeURI ( did ) ,
}
) ) . then ( res => {
setPrivOptions ( res . data ) ;
} ) ;
2022-09-08 15:16:48 +05:30
let node _type = nodeData . _type . replace ( 'coll-' , '' ) . replace (
2021-09-20 13:02:41 +05:30
'materialized_' , ''
) ;
2022-09-08 15:16:48 +05:30
let _url = url _for (
2021-09-20 13:02:41 +05:30
'grant_wizard.objects' , {
'sid' : encodeURI ( sid ) ,
'did' : encodeURI ( did ) ,
'node_id' : encodeURI ( nodeData . _id ) ,
'node_type' : encodeURI ( node _type ) ,
} ) ;
api . get ( _url )
. then ( res => {
2022-09-08 15:16:48 +05:30
let data = res . data . result ;
2021-09-20 13:02:41 +05:30
data . forEach ( element => {
if ( element . icon )
element [ 'icon' ] = {
'object_type' : element . icon
} ;
2021-09-30 10:56:51 +05:30
if ( element . object _type === 'Function' ) {
element . name _with _args = element . name + '(' + ( typeof ( element . proargs ) != 'undefined' ? element . proargs : '' ) + ')' ;
} else {
element . name _with _args = element . name ;
}
2021-09-20 13:02:41 +05:30
} ) ;
setTableData ( data ) ;
setLoaderText ( '' ) ;
} )
. catch ( ( ) => {
2023-10-23 17:43:17 +05:30
pgAdmin . Browser . notifier . error ( gettext ( 'Error while fetching grant wizard data.' ) ) ;
2021-09-20 13:02:41 +05:30
setLoaderText ( '' ) ;
} ) ;
} , [ nodeData ] ) ;
const wizardStepChange = ( data ) => {
2022-01-20 16:58:21 +05:30
if ( data . currentStep == 2 ) {
2021-09-20 13:02:41 +05:30
setLoaderText ( 'Loading SQL ...' ) ;
2022-09-08 15:16:48 +05:30
let msql _url = url _for (
2021-09-20 13:02:41 +05:30
'grant_wizard.modified_sql' , {
'sid' : encodeURI ( sid ) ,
'did' : encodeURI ( did ) ,
} ) ;
2022-09-08 15:16:48 +05:30
let post _data = {
2021-09-20 13:02:41 +05:30
acl : selectedAcl . privilege ,
2024-05-07 16:31:04 +05:30
objects : selectedObject . current
2021-09-20 13:02:41 +05:30
} ;
api . post ( msql _url , post _data )
. then ( res => {
2024-04-09 19:18:56 +05:30
setMSQLData ( res . data . data ) ;
2021-09-20 13:02:41 +05:30
setLoaderText ( '' ) ;
} )
. catch ( ( ) => {
2023-10-23 17:43:17 +05:30
pgAdmin . Browser . notifier . error ( gettext ( 'Error while fetching SQL.' ) ) ;
2021-09-20 13:02:41 +05:30
} ) ;
}
} ;
const onSave = ( ) => {
setLoaderText ( 'Saving...' ) ;
2022-09-08 15:16:48 +05:30
let _url = url _for (
2021-09-20 13:02:41 +05:30
'grant_wizard.apply' , {
'sid' : encodeURI ( sid ) ,
'did' : encodeURI ( did ) ,
} ) ;
const post _data = {
acl : selectedAcl . privilege ,
2024-05-07 16:31:04 +05:30
objects : selectedObject . current
2021-09-20 13:02:41 +05:30
} ;
api . post ( _url , post _data )
. then ( ( ) => {
setLoaderText ( '' ) ;
2022-07-28 10:14:04 +05:30
onClose ( ) ;
2021-09-20 13:02:41 +05:30
} )
2021-09-23 14:40:38 +05:30
. catch ( ( error ) => {
2021-09-20 13:02:41 +05:30
setLoaderText ( '' ) ;
2023-10-23 17:43:17 +05:30
pgAdmin . Browser . notifier . error ( gettext ( ` Error while saving grant wizard data: ${ error . response . data . errormsg } ` ) ) ;
2021-09-20 13:02:41 +05:30
} ) ;
} ;
2021-12-22 18:26:21 +05:30
const disableNextCheck = ( stepId ) => {
2024-05-07 16:31:04 +05:30
if ( Object . keys ( selectedRows ) . length > 0 && stepId === 0 ) {
2022-01-18 14:49:54 +05:30
return false ;
}
return selectedAcl ? . privilege ? . length > 0 && stepId === 1 ? validatePrivilege ( ) : true ;
2021-09-20 13:02:41 +05:30
} ;
const onDialogHelp = ( ) => {
window . open ( url _for ( 'help.static' , { 'filename' : 'grant_wizard.html' } ) , 'pgadmin_help' ) ;
} ;
2024-05-07 16:31:04 +05:30
useEffect ( ( ) => {
2022-09-08 15:16:48 +05:30
let selObj = [ ] ;
let objectTypes = new Set ( ) ;
2024-05-07 16:31:04 +05:30
if ( Object . keys ( selectedRows ) . length > 0 ) {
Object . keys ( selectedRows ) . forEach ( ( rowId ) => {
const row = tableData [ rowId ] ;
2022-09-08 15:16:48 +05:30
let object _type = '' ;
2024-05-07 16:31:04 +05:30
switch ( row . object _type ) {
2021-09-20 13:02:41 +05:30
case 'Function' :
object _type = 'function' ;
break ;
case 'Trigger Function' :
object _type = 'function' ;
break ;
case 'Procedure' :
object _type = 'procedure' ;
break ;
case 'Table' :
object _type = 'table' ;
break ;
case 'Sequence' :
object _type = 'sequence' ;
break ;
case 'View' :
object _type = 'table' ;
break ;
case 'Materialized View' :
object _type = 'table' ;
break ;
case 'Foreign Table' :
object _type = 'foreign_table' ;
break ;
case 'Package' :
object _type = 'package' ;
break ;
default :
break ;
}
objectTypes . add ( object _type ) ;
2024-05-07 16:31:04 +05:30
selObj . push ( row ) ;
2021-09-20 13:02:41 +05:30
} ) ;
}
2022-09-08 15:16:48 +05:30
let privs = new Set ( ) ;
2021-09-20 13:02:41 +05:30
objectTypes . forEach ( ( objType ) => {
privOptions [ objType ] ? . acl . forEach ( ( priv ) => {
2022-01-21 18:53:48 +05:30
privs . add ( priv ) ;
2021-09-20 13:02:41 +05:30
} ) ;
} ) ;
2024-05-07 16:31:04 +05:30
privileges . current = Array . from ( privs ) ;
selectedObject . current = selObj ;
privSchemaInstance ? . privilegeRoleSchema . updateSupportedPrivs ( privileges . current ) ;
2021-09-20 13:02:41 +05:30
setErrMsg ( selObj . length === 0 ? gettext ( 'Please select any database object.' ) : '' ) ;
2024-05-07 16:31:04 +05:30
} , [ selectedRows ] ) ;
2021-09-20 13:02:41 +05:30
const onErrClose = React . useCallback ( ( ) => {
setErrMsg ( '' ) ;
} ) ;
return (
2021-12-31 14:16:50 +05:30
< Wizard
title = { gettext ( 'Grant Wizard' ) }
stepList = { steps }
disableNextStep = { disableNextCheck }
onStepChange = { wizardStepChange }
onSave = { onSave }
onHelp = { onDialogHelp }
loaderText = { loaderText }
>
< WizardStep stepId = { 0 } >
2024-06-06 17:13:12 +05:30
< Box sx = { { flexGrow : 1 , minHeight : 0 } } >
2021-12-31 14:16:50 +05:30
< PgTable
2022-04-04 19:03:50 +05:30
caveTable = { false }
2024-05-07 16:31:04 +05:30
tableNoBorder = { false }
2021-12-31 14:16:50 +05:30
height = { window . innerHeight - 450 }
columns = { columns }
2024-04-09 19:18:56 +05:30
data = { tableData }
2024-05-07 16:31:04 +05:30
hasSelectRow = { true }
selectedRows = { selectedRows }
setSelectedRows = { setSelectedRows }
/ >
2021-12-31 14:16:50 +05:30
< / Box >
< FormFooterMessage type = { MESSAGE _TYPE . ERROR } message = { errMsg } onClose = { onErrClose } / >
< / WizardStep >
< WizardStep
stepId = { 1 }
2024-06-06 17:13:12 +05:30
sx = { { height : '100%' , overflow : 'auto' } } >
2021-12-31 14:16:50 +05:30
{ privSchemaInstance &&
2024-05-07 16:31:04 +05:30
< SchemaView
formType = { 'dialog' }
getInitData = { ( ) => { /*This is intentional (SonarQube)*/ } }
viewHelperProps = { { mode : 'create' } }
schema = { privSchemaInstance }
showFooter = { false }
isTabView = { false }
onDataChange = { ( isChanged , changedData ) => {
setSelectedAcl ( changedData ) ;
} }
/ >
2021-12-31 14:16:50 +05:30
}
< / WizardStep >
< WizardStep
stepId = { 2 } >
< Box > { gettext ( 'The SQL below will be executed on the database server to grant the selected privileges. Please click on Finish to complete the process.' ) } < / Box >
< InputSQL
onLable = { true }
readonly = { true }
value = { msqlData . toString ( ) } / >
< / WizardStep >
< / Wizard >
2021-09-20 13:02:41 +05:30
) ;
}
GrantWizard . propTypes = {
sid : PropTypes . string ,
did : PropTypes . number ,
nodeInfo : PropTypes . object ,
nodeData : PropTypes . object ,
2022-07-28 10:14:04 +05:30
onClose : PropTypes . func
2021-09-20 13:02:41 +05:30
} ;