├── .babelrc
├── .gitignore
├── .prettierignore
├── .prettierrc.js
├── .vscode
└── launch.json
├── LICENSE
├── _from-postgraphile
├── PgIntrospectionPlugin.js
└── introspectionQuery.js
├── _tmp
├── intro.sql
├── ownership.sql
├── roles.sql
└── usage.sql
├── bin
├── pgdbi
│ ├── __test
│ │ └── test_helper.ts
│ ├── dist
│ │ ├── be8c8ec05b6dad115347.worker.js
│ │ ├── be8c8ec05b6dad115347.worker.js.map
│ │ ├── css
│ │ │ ├── app.89ce3cd1.css
│ │ │ └── chunk-vendors.89bed726.css
│ │ ├── favicon.ico
│ │ ├── index.html
│ │ ├── js
│ │ │ ├── about.5bee4903.js
│ │ │ ├── about.5bee4903.js.map
│ │ │ ├── app.0637cf86.js
│ │ │ ├── app.0637cf86.js.map
│ │ │ ├── chunk-vendors.13f58bb9.js
│ │ │ ├── chunk-vendors.13f58bb9.js.map
│ │ │ ├── pdfjsWorker.157d1873.js
│ │ │ └── pdfjsWorker.157d1873.js.map
│ │ └── logo.png
│ ├── graphile-extensions
│ │ ├── dbSchema
│ │ │ ├── index.js
│ │ │ ├── introspection.js
│ │ │ ├── pgdbiOptions.js
│ │ │ └── resolvers
│ │ │ │ ├── checkConstraint
│ │ │ │ └── tableConstraint.js
│ │ │ │ ├── column
│ │ │ │ └── keyColumnUsage.js
│ │ │ │ ├── enabledRole
│ │ │ │ └── applicableRoles.js
│ │ │ │ ├── function
│ │ │ │ ├── functionById.js
│ │ │ │ └── searchFunctions.js
│ │ │ │ ├── keyColumnUsage
│ │ │ │ └── referentialConstraints.js
│ │ │ │ ├── referentialConstraint
│ │ │ │ ├── referencedColumnUsage.js
│ │ │ │ └── referencingColumnUsage.js
│ │ │ │ ├── schema
│ │ │ │ ├── id.js
│ │ │ │ ├── schemaEnums.js
│ │ │ │ ├── schemaFunctions.js
│ │ │ │ ├── schemaTables.js
│ │ │ │ └── schemaTreeBySchemaName.js
│ │ │ │ ├── table
│ │ │ │ ├── checkConstraints.js
│ │ │ │ ├── id.js
│ │ │ │ ├── indices.js
│ │ │ │ ├── policies.js
│ │ │ │ ├── primaryKeyConstraints.js
│ │ │ │ ├── psqlDescription.js
│ │ │ │ ├── referentialConstraints.js
│ │ │ │ ├── roleColumnGrants.js
│ │ │ │ ├── roleTableGrants.js
│ │ │ │ ├── tableById.js
│ │ │ │ ├── tableColumns.js
│ │ │ │ ├── tableConstraints.js
│ │ │ │ ├── triggers.js
│ │ │ │ └── uniqueConstraints.js
│ │ │ │ ├── tableConstraint
│ │ │ │ └── keyColumnUsage.js
│ │ │ │ └── trigger
│ │ │ │ ├── id.js
│ │ │ │ └── triggerFunction.js
│ │ ├── execSql.js
│ │ ├── pgIntrospectionResultsByKind.js
│ │ ├── pgdbirc-default.js
│ │ ├── pgdbirc.js
│ │ ├── pglint.js
│ │ ├── pglintrc-default.js
│ │ ├── project.js
│ │ └── writeArtifacts.js
│ ├── index.js
│ ├── pg10IntrospectionQuery.js
│ ├── pg11IntrospectionQuery.js
│ └── transformBuild.js
└── sql
│ └── schema_usage.sql
├── build.sh
├── columns.sql
├── evals.json
├── exampleScript-terse.sql
├── exampleScript-verbose.sql
├── index.js
├── introResult.json
├── meh.sql
├── package-lock.json
├── package.json
├── pglint-bash.sh
├── pglint-npx.sh
├── pglint.sh
├── project.md
├── readme.md
├── roadmap.md
├── src
├── dbDev
│ ├── constraints.sql
│ ├── execute.sh
│ ├── functions.sql
│ ├── indices.sql
│ ├── inheritance.sql
│ ├── intro.json
│ ├── pgdbi-dev.sql
│ ├── samp.sql
│ ├── schemaTree.sql
│ ├── scratch.sql
│ ├── testSchema.sql
│ └── udt.sql
├── devServer
│ ├── index.js
│ ├── phile.js
│ ├── sqitch.conf
│ ├── tasks
│ │ └── testTask.js
│ ├── voyager.worker.js
│ └── worker.js
├── pgdbi
│ ├── __test
│ │ └── test_helper.ts
│ ├── dist
│ │ ├── be8c8ec05b6dad115347.worker.js
│ │ ├── be8c8ec05b6dad115347.worker.js.map
│ │ ├── css
│ │ │ ├── app.89ce3cd1.css
│ │ │ └── chunk-vendors.89bed726.css
│ │ ├── favicon.ico
│ │ ├── index.html
│ │ ├── js
│ │ │ ├── about.5bee4903.js
│ │ │ ├── about.5bee4903.js.map
│ │ │ ├── app.0637cf86.js
│ │ │ ├── app.0637cf86.js.map
│ │ │ ├── chunk-vendors.13f58bb9.js
│ │ │ ├── chunk-vendors.13f58bb9.js.map
│ │ │ ├── pdfjsWorker.157d1873.js
│ │ │ └── pdfjsWorker.157d1873.js.map
│ │ └── logo.png
│ ├── graphile-extensions
│ │ ├── dbSchema
│ │ │ ├── index.js
│ │ │ ├── introspection.js
│ │ │ ├── pgdbiOptions.js
│ │ │ └── resolvers
│ │ │ │ ├── checkConstraint
│ │ │ │ └── tableConstraint.js
│ │ │ │ ├── column
│ │ │ │ └── keyColumnUsage.js
│ │ │ │ ├── enabledRole
│ │ │ │ └── applicableRoles.js
│ │ │ │ ├── function
│ │ │ │ ├── functionById.js
│ │ │ │ └── searchFunctions.js
│ │ │ │ ├── keyColumnUsage
│ │ │ │ └── referentialConstraints.js
│ │ │ │ ├── referentialConstraint
│ │ │ │ ├── referencedColumnUsage.js
│ │ │ │ └── referencingColumnUsage.js
│ │ │ │ ├── schema
│ │ │ │ ├── id.js
│ │ │ │ ├── schemaEnums.js
│ │ │ │ ├── schemaFunctions.js
│ │ │ │ ├── schemaTables.js
│ │ │ │ └── schemaTreeBySchemaName.js
│ │ │ │ ├── table
│ │ │ │ ├── checkConstraints.js
│ │ │ │ ├── id.js
│ │ │ │ ├── indices.js
│ │ │ │ ├── policies.js
│ │ │ │ ├── primaryKeyConstraints.js
│ │ │ │ ├── psqlDescription.js
│ │ │ │ ├── referentialConstraints.js
│ │ │ │ ├── roleColumnGrants.js
│ │ │ │ ├── roleTableGrants.js
│ │ │ │ ├── tableById.js
│ │ │ │ ├── tableColumns.js
│ │ │ │ ├── tableConstraints.js
│ │ │ │ ├── triggers.js
│ │ │ │ └── uniqueConstraints.js
│ │ │ │ ├── tableConstraint
│ │ │ │ └── keyColumnUsage.js
│ │ │ │ └── trigger
│ │ │ │ ├── id.js
│ │ │ │ └── triggerFunction.js
│ │ ├── execSql.js
│ │ ├── pgIntrospectionResultsByKind.js
│ │ ├── pgdbirc-default.js
│ │ ├── pgdbirc.js
│ │ ├── pglint.js
│ │ ├── pglintrc-default.js
│ │ ├── project.js
│ │ └── writeArtifacts.js
│ ├── index.js
│ ├── pg10IntrospectionQuery.js
│ ├── pg11IntrospectionQuery.js
│ └── transformBuild.js
└── web-vue
│ ├── .gitignore
│ ├── README.md
│ ├── babel.config.js
│ ├── delete
│ ├── EnabledRoleListMixin.vue
│ ├── RoleFilterFunctionsMixin.vue
│ ├── RoleList.vue
│ ├── SchemaFilter copy.vue
│ ├── SchemaFilter.vue
│ ├── SchemaTree copy.vue
│ └── Table copy.vue
│ ├── package-lock.json
│ ├── package.json
│ ├── public
│ ├── favicon.ico
│ ├── index.html
│ └── logo.png
│ ├── src
│ ├── App.vue
│ ├── AppBus.js
│ ├── assets
│ │ └── logo.svg
│ ├── components
│ │ ├── Enum
│ │ │ └── Enum.vue
│ │ ├── ForeignKeyIndex
│ │ │ ├── Constraints
│ │ │ │ └── CheckConstraints.vue
│ │ │ ├── ConstraintsAndIndices.vue
│ │ │ ├── ConstraintsAndIndicesManager.vue
│ │ │ ├── FkIndexConstraints.vue
│ │ │ ├── GenericIndexDetail.vue
│ │ │ ├── GenericIndexSet.vue
│ │ │ └── UqIndexSet.vue
│ │ ├── Function
│ │ │ ├── Function.vue
│ │ │ ├── FunctionList.vue
│ │ │ └── FunctionSearch.vue
│ │ ├── FunctionSecurity
│ │ │ ├── Assignment
│ │ │ │ ├── FunctionPolicyAssignment.vue
│ │ │ │ ├── FunctionPolicyAssignmentByPolicy.vue
│ │ │ │ ├── FunctionPolicyAssignmentBySchema.vue
│ │ │ │ ├── FunctionPolicyAssignmentDialog.vue
│ │ │ │ ├── FunctionPolicyAssignmentPolicy.vue
│ │ │ │ └── FunctionPolicyAssignmentSchema.vue
│ │ │ ├── Definition
│ │ │ │ ├── FunctionPolicyDefinition.vue
│ │ │ │ ├── FunctionPolicyDefinitionGrantGrid copy.vue
│ │ │ │ └── FunctionPolicyDefinitionGrantGrid.vue
│ │ │ ├── FunctionPolicyManager.vue
│ │ │ └── Realization
│ │ │ │ ├── FunctionPolicyRealization.vue
│ │ │ │ └── FunctionSchemaSecurityScripts.vue
│ │ ├── Help
│ │ │ └── Help.vue
│ │ ├── PgLint
│ │ │ └── PgLintResult.vue
│ │ ├── Project
│ │ │ ├── ProjectExport.vue
│ │ │ ├── ProjectImport.vue
│ │ │ ├── ProjectNavigator.vue
│ │ │ └── ProjectResetDialog.vue
│ │ ├── Role
│ │ │ ├── ChooseRoleSet.vue
│ │ │ ├── CreateRolesRealization.vue
│ │ │ └── Roles.vue
│ │ ├── Schema
│ │ │ ├── SchemaNavigator.vue
│ │ │ ├── SchemaTree.vue
│ │ │ └── SchemaUsageRealization.vue
│ │ ├── Security
│ │ │ ├── MasterSecurityPolicyRealization.vue
│ │ │ └── OwnershipPolicyRealization.vue
│ │ ├── Settings
│ │ │ ├── DefaultRlsUsing.vue
│ │ │ ├── SecurityPolicySettings.vue
│ │ │ └── Settings.vue
│ │ ├── SmartCommentManager
│ │ │ └── SmartCommentManager.vue
│ │ ├── Table
│ │ │ ├── ColumnDetail.vue
│ │ │ ├── Constraints
│ │ │ │ ├── TableCheckConstraints.vue
│ │ │ │ ├── TableKeyColumnUsage.vue
│ │ │ │ ├── TableReferentialConstraints.vue
│ │ │ │ └── TableUniqueConstraints.vue
│ │ │ ├── Table.vue
│ │ │ ├── TableColumnGrants.vue
│ │ │ ├── TableColumns copy.vue
│ │ │ ├── TableColumns.vue
│ │ │ ├── TableConstraints.vue
│ │ │ ├── TableDetail.vue
│ │ │ ├── TableFkIndices.vue
│ │ │ ├── TableGenericIndexDetail.vue
│ │ │ ├── TableGenericIndices.vue
│ │ │ ├── TableGrants.vue
│ │ │ ├── TableIndices copy.vue
│ │ │ ├── TableIndices.vue
│ │ │ ├── TablePolicies.vue
│ │ │ ├── TableScripts.vue
│ │ │ ├── TableUqIndices.vue
│ │ │ └── Triggers
│ │ │ │ ├── TableTriggerSet.vue
│ │ │ │ └── TableTriggers.vue
│ │ ├── TableSecurity copy
│ │ │ ├── Assignment
│ │ │ │ ├── TablePolicyAssignment.vue
│ │ │ │ ├── TablePolicyAssignmentByPolicy.vue
│ │ │ │ ├── TablePolicyAssignmentBySchema.vue
│ │ │ │ ├── TablePolicyAssignmentDialog.vue
│ │ │ │ ├── TablePolicyAssignmentPolicy.vue
│ │ │ │ └── TablePolicyAssignmentSchema.vue
│ │ │ ├── Definition
│ │ │ │ ├── Grants
│ │ │ │ │ ├── ColumnExclusions
│ │ │ │ │ │ ├── ColumnExclusionSet.vue
│ │ │ │ │ │ ├── TablePolicyColumnExclusionDialog.vue
│ │ │ │ │ │ └── TablePolicyDefinitionColumnExclusions.vue
│ │ │ │ │ ├── TablePolicyDefinitionGrantGrid.vue
│ │ │ │ │ └── TablePolicyDefinitionGrants.vue
│ │ │ │ ├── TablePolicyDefinition.vue
│ │ │ │ ├── TablePolicyRlsAction.vue
│ │ │ │ └── TablePolicyRlsQualifierGrid.vue
│ │ │ ├── Dialogs
│ │ │ │ ├── RlsPolicyDialog.vue
│ │ │ │ ├── TablePolicyCustomizeDialog.vue
│ │ │ │ ├── TablePolicyDeleteDialog.vue
│ │ │ │ ├── TablePolicyMakeGlobalDialog.vue
│ │ │ │ └── TablePolicyRenameDialog.vue
│ │ │ ├── Evaluation
│ │ │ │ ├── TablePolicyEvaluatorCalculatorMixin.vue
│ │ │ │ ├── TablePolicyEvaluatorDetail.vue
│ │ │ │ └── TablePolicyEvaluatorSummary.vue
│ │ │ ├── Realization
│ │ │ │ ├── SchemaSecurityScripts.vue
│ │ │ │ └── TablePolicyRealization.vue
│ │ │ └── TablePolicyManager.vue
│ │ ├── TableSecurity-next
│ │ │ ├── Assignment
│ │ │ │ ├── TablePolicyAssignment.vue
│ │ │ │ ├── TablePolicyAssignmentByPolicy.vue
│ │ │ │ ├── TablePolicyAssignmentBySchema.vue
│ │ │ │ ├── TablePolicyAssignmentDialog.vue
│ │ │ │ ├── TablePolicyAssignmentPolicy.vue
│ │ │ │ └── TablePolicyAssignmentSchema.vue
│ │ │ ├── Definition
│ │ │ │ ├── Grants
│ │ │ │ │ ├── ColumnExclusions
│ │ │ │ │ │ ├── ColumnExclusionSet.vue
│ │ │ │ │ │ ├── TablePolicyColumnExclusionDialog.vue
│ │ │ │ │ │ └── TablePolicyDefinitionColumnExclusions.vue
│ │ │ │ │ ├── TablePolicyDefinitionGrantGrid.vue
│ │ │ │ │ └── TablePolicyDefinitionGrants.vue
│ │ │ │ ├── TableGrantGrid.vue
│ │ │ │ ├── TablePolicyDefinition.vue
│ │ │ │ ├── TablePolicyRlsAction.vue
│ │ │ │ ├── TablePolicyRlsQualifierGrid.vue
│ │ │ │ ├── TableSecurityProfile.vue
│ │ │ │ └── TableSecurityProfileManager.vue
│ │ │ ├── Dialogs
│ │ │ │ ├── RlsPolicyDialog.vue
│ │ │ │ ├── TablePolicyCustomizeDialog.vue
│ │ │ │ ├── TablePolicyDeleteDialog.vue
│ │ │ │ ├── TablePolicyMakeGlobalDialog.vue
│ │ │ │ └── TablePolicyRenameDialog.vue
│ │ │ ├── Evaluation
│ │ │ │ ├── TablePolicyEvaluatorCalculatorMixin.vue
│ │ │ │ ├── TablePolicyEvaluatorDetail.vue
│ │ │ │ └── TablePolicyEvaluatorSummary.vue
│ │ │ ├── Realization
│ │ │ │ ├── SchemaSecurityScripts.vue
│ │ │ │ └── TablePolicyRealization.vue
│ │ │ ├── Rls
│ │ │ │ ├── CurrentRlsPolicies.vue
│ │ │ │ ├── TableGrantGrid.vue
│ │ │ │ └── TableSecurityProfile.vue
│ │ │ └── TablePolicyManager.vue
│ │ ├── TableSecurity
│ │ │ ├── Assignment
│ │ │ │ ├── TablePolicyAssignment.vue
│ │ │ │ ├── TablePolicyAssignmentByPolicy.vue
│ │ │ │ ├── TablePolicyAssignmentBySchema.vue
│ │ │ │ ├── TablePolicyAssignmentDialog.vue
│ │ │ │ ├── TablePolicyAssignmentPolicy.vue
│ │ │ │ └── TablePolicyAssignmentSchema.vue
│ │ │ ├── Definition
│ │ │ │ ├── Grants
│ │ │ │ │ ├── ColumnExclusions
│ │ │ │ │ │ ├── ColumnExclusionSet.vue
│ │ │ │ │ │ ├── TablePolicyColumnExclusionDialog.vue
│ │ │ │ │ │ └── TablePolicyDefinitionColumnExclusions.vue
│ │ │ │ │ ├── TablePolicyDefinitionGrantGrid.vue
│ │ │ │ │ └── TablePolicyDefinitionGrants.vue
│ │ │ │ ├── TableGrantGrid.vue
│ │ │ │ ├── TablePolicyDefinition.vue
│ │ │ │ ├── TablePolicyRlsAction.vue
│ │ │ │ ├── TablePolicyRlsQualifierGrid.vue
│ │ │ │ ├── TableSecurityProfile.vue
│ │ │ │ └── TableSecurityProfileDefinitions.vue
│ │ │ ├── Dialogs
│ │ │ │ ├── RlsPolicyDialog.vue
│ │ │ │ ├── TablePolicyCustomizeDialog.vue
│ │ │ │ ├── TablePolicyDeleteDialog.vue
│ │ │ │ ├── TablePolicyMakeGlobalDialog.vue
│ │ │ │ ├── TablePolicyRenameDialog.vue
│ │ │ │ └── TableRlsPolicyDialog.vue
│ │ │ ├── Evaluation
│ │ │ │ ├── TablePolicyEvaluatorCalculatorMixin.vue
│ │ │ │ ├── TablePolicyEvaluatorDetail.vue
│ │ │ │ └── TablePolicyEvaluatorSummary.vue
│ │ │ └── Realization
│ │ │ │ ├── SchemaSecurityScripts.vue
│ │ │ │ └── TablePolicyRealization.vue
│ │ ├── Udt
│ │ │ └── Udt.vue
│ │ ├── View
│ │ │ ├── View.vue
│ │ │ ├── ViewColumns.vue
│ │ │ └── ViewSearch.vue
│ │ └── _common
│ │ │ └── ScriptViewer.vue
│ ├── gql
│ │ ├── mutation
│ │ │ ├── execSql.graphql
│ │ │ ├── pgLint.graphql
│ │ │ ├── searchFunctions.graphql
│ │ │ └── writeArtifacts.graphql
│ │ └── query
│ │ │ ├── allEnabledRoles.graphql
│ │ │ ├── dbIntrospection.graphql
│ │ │ ├── functionById.graphql
│ │ │ ├── getDbSchemaList.graphql
│ │ │ ├── getDbSchemaTree.graphql
│ │ │ ├── getDbSchemaTreeBySchemaName.graphql
│ │ │ ├── getDbSecurityTree.graphql
│ │ │ ├── getDbSecurityTreeFiltered.graphql
│ │ │ ├── pgdbirc.graphql
│ │ │ ├── pglintrc.graphql
│ │ │ ├── project.graphql
│ │ │ ├── tableById-not.graphql
│ │ │ └── tableById.graphql
│ ├── main.js
│ ├── plugins
│ │ └── vuetify.js
│ ├── router.js
│ ├── scriptCompute
│ │ ├── computeAllSchemaFunctionPolicies.js
│ │ ├── computeAllSchemaTablePolicies.js
│ │ ├── computeFunctionPolicy.js
│ │ ├── computeMasterFunctionPolicy.js
│ │ ├── computeMasterSecurityPolicy.js
│ │ ├── computeMasterTablePolicy.js
│ │ ├── computeOwnershipPolicy.js
│ │ ├── computeRemoveRls.js
│ │ ├── computeRolesSql.js
│ │ ├── computeSchemaFunctionPolicy.js
│ │ ├── computeSchemaTablePolicy.js
│ │ ├── computeSchemaUsageSql.js
│ │ ├── computeTablePolicy.js
│ │ └── index.js
│ ├── store
│ │ ├── actions
│ │ │ ├── index.js
│ │ │ ├── loadFromDisk.js
│ │ │ ├── pgdbirc.js
│ │ │ ├── resetDefaultState.js
│ │ │ ├── setManagedSchemata.js
│ │ │ ├── setProjectRoleSet.js
│ │ │ └── writeToDisk.js
│ │ ├── defaultState.js
│ │ ├── mutations
│ │ │ ├── assignFunctionPolicy.js
│ │ │ ├── assignTablePolicy.js
│ │ │ ├── createRlsPolicy.js
│ │ │ ├── customizeTablePolicy.js
│ │ │ ├── defaultRlsUsing.js
│ │ │ ├── defaultRlsWithCheck.js
│ │ │ ├── deleteRlsPolicy.js
│ │ │ ├── deleteTablePolicy.js
│ │ │ ├── evaluate
│ │ │ │ ├── evaluateAll.js
│ │ │ │ ├── evaluateEnumScripts.js
│ │ │ │ ├── evaluateFkIndexes.js
│ │ │ │ ├── evaluateGenericIndices.js
│ │ │ │ ├── evaluateUdtScripts.js
│ │ │ │ ├── evaluateUqIndexes.js
│ │ │ │ └── storeEvaluations.js
│ │ │ ├── filterSchemata.js
│ │ │ ├── importProject.js
│ │ │ ├── makeGlobalTablePolicy.js
│ │ │ ├── mutations.js
│ │ │ ├── newFunctionPolicy.js
│ │ │ ├── newPolicy.js
│ │ │ ├── projectRoles.js
│ │ │ ├── renameTablePolicy.js
│ │ │ ├── resetDefaultState.js
│ │ │ ├── saveFunctionPolicy.js
│ │ │ ├── savePgLintResult.js
│ │ │ ├── savePolicy.js
│ │ │ ├── selectedRoleFamilies.js
│ │ │ ├── setAllRoleSets.js
│ │ │ ├── setEnabledRoles.js
│ │ │ ├── setExistingRlsPolicies.js
│ │ │ ├── setManagedSchemata.js
│ │ │ ├── setPgdbiOptions.js
│ │ │ ├── setProjectRoleSet.js
│ │ │ ├── toggleIgnoreRole.js
│ │ │ ├── toggleIndexForDrop.js
│ │ │ ├── updateDefaultRlsUsing.js
│ │ │ └── updateTablePolicyTemplate.js
│ │ ├── store.js
│ │ └── templates
│ │ │ ├── policyFooterTemplate.js
│ │ │ ├── policyHeaderTemplate.js
│ │ │ └── roleTableGrantTemplate.js
│ ├── views
│ │ ├── About.vue
│ │ ├── ForeignKeyIndexView.vue
│ │ ├── FunctionSecurityView.vue
│ │ ├── Home.vue
│ │ ├── Initialize.vue
│ │ ├── PgLintView.vue
│ │ ├── RoleManagerView.vue
│ │ ├── SearchView.vue
│ │ ├── SecurityScriptsSummaryView.vue
│ │ ├── SecurityView.vue
│ │ ├── SqitchView.vue
│ │ ├── TableSecurityProfileDefinitionView.vue
│ │ ├── TableSecurityProfileView.vue
│ │ ├── TableSecurityView copy.vue
│ │ ├── TableSecurityView-next.vue
│ │ ├── TableSecurityView.vue
│ │ └── WorkerView.vue
│ └── vue-apollo.js
│ ├── test
│ └── blah.spec.js
│ ├── tsconfigs.json
│ └── vue.config.js
├── tsconfig.json
└── yarn.lock
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | [
4 | "@babel/preset-env", {
5 | "targets": {
6 | "node": "current"
7 | }
8 | }
9 | ],
10 | [
11 | "@babel/typescript", {
12 | "targets": {
13 | "node": "current"
14 | }
15 | }
16 | ]
17 | ]
18 | }
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # pde-directory
2 | pde-directory
3 | .pgdbi
4 |
5 | # Logs
6 | logs
7 | *.log
8 | npm-debug.log*
9 | yarn-debug.log*
10 | yarn-error.log*
11 |
12 | # Runtime data
13 | pids
14 | *.pid
15 | *.seed
16 | *.pid.lock
17 |
18 | # Directory for instrumented libs generated by jscoverage/JSCover
19 | lib-cov
20 |
21 | # Coverage directory used by tools like istanbul
22 | coverage
23 |
24 | # nyc test coverage
25 | .nyc_output
26 |
27 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
28 | .grunt
29 |
30 | # Bower dependency directory (https://bower.io/)
31 | bower_components
32 |
33 | # node-waf configuration
34 | .lock-wscript
35 |
36 | # Compiled binary addons (https://nodejs.org/api/addons.html)
37 | build/Release
38 |
39 | # Dependency directories
40 | node_modules/
41 | jspm_packages/
42 |
43 | # TypeScript v1 declaration files
44 | typings/
45 |
46 | # Optional npm cache directory
47 | .npm
48 |
49 | # Optional eslint cache
50 | .eslintcache
51 |
52 | # Optional REPL history
53 | .node_repl_history
54 |
55 | # Output of 'npm pack'
56 | *.tgz
57 |
58 | # Yarn Integrity file
59 | .yarn-integrity
60 |
61 | # dotenv environment variables file
62 | .env
63 |
64 | # next.js build output
65 | .next
66 |
--------------------------------------------------------------------------------
/.prettierignore:
--------------------------------------------------------------------------------
1 | src/devServer/voyager.worker.js
2 | src/pgdbi/dist/
3 |
--------------------------------------------------------------------------------
/.prettierrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | trailingComma: 'all',
3 | singleQuote: true,
4 | };
5 |
--------------------------------------------------------------------------------
/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | {
2 | // Use IntelliSense to learn about possible attributes.
3 | // Hover to view descriptions of existing attributes.
4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5 | "version": "0.2.0",
6 | "configurations": [
7 | {
8 | "type": "node",
9 | "request": "launch",
10 | "name": "Launch Program",
11 | "program": "${workspaceFolder}/index.js"
12 | }
13 | ]
14 | }
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 stlbucket
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/bin/pgdbi/dist/css/app.89ce3cd1.css:
--------------------------------------------------------------------------------
1 | @-webkit-keyframes shadow-pulse{0%{-webkit-box-shadow:0 0 0 0 rgba(182,179,26,.253);box-shadow:0 0 0 0 rgba(182,179,26,.253)}to{-webkit-box-shadow:0 0 0 15px rgba(182,179,26,.253);box-shadow:0 0 0 15px rgba(182,179,26,.253)}}@keyframes shadow-pulse{0%{-webkit-box-shadow:0 0 0 0 rgba(182,179,26,.253);box-shadow:0 0 0 0 rgba(182,179,26,.253)}to{-webkit-box-shadow:0 0 0 15px rgba(182,179,26,.253);box-shadow:0 0 0 15px rgba(182,179,26,.253)}}.refreshBtnInitializing{-webkit-animation:shadow-pulse 2s infinite;animation:shadow-pulse 2s infinite}.blah{color:red}.norm-text{text-transform:none!important}
--------------------------------------------------------------------------------
/bin/pgdbi/dist/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/graphile-contrib/pgdbi/47d3b0454fde69836e99a388f88b00a8463f4285/bin/pgdbi/dist/favicon.ico
--------------------------------------------------------------------------------
/bin/pgdbi/dist/index.html:
--------------------------------------------------------------------------------
1 |
pg-db-inspector
--------------------------------------------------------------------------------
/bin/pgdbi/dist/js/about.5bee4903.js:
--------------------------------------------------------------------------------
1 | (window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["about"],{f820:function(t,e,n){"use strict";n.r(e);var a=function(){var t=this,e=t.$createElement;t._self._c;return t._m(0)},s=[function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{staticClass:"about"},[n("h1",[t._v("This is an about page")])])}],u=n("2877"),c={},i=Object(u["a"])(c,a,s,!1,null,null,null);e["default"]=i.exports}}]);
2 | //# sourceMappingURL=about.5bee4903.js.map
--------------------------------------------------------------------------------
/bin/pgdbi/dist/js/about.5bee4903.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":["webpack:///./src/views/About.vue?05f7","webpack:///./src/views/About.vue"],"names":["render","_vm","this","_h","$createElement","_self","_c","_m","staticRenderFns","staticClass","_v","script","component"],"mappings":"8GAAA,IAAIA,EAAS,WAAa,IAAIC,EAAIC,KAASC,EAAGF,EAAIG,eAAsBH,EAAII,MAAMC,GAAO,OAAOL,EAAIM,GAAG,IACnGC,EAAkB,CAAC,WAAa,IAAIP,EAAIC,KAASC,EAAGF,EAAIG,eAAmBE,EAAGL,EAAII,MAAMC,IAAIH,EAAG,OAAOG,EAAG,MAAM,CAACG,YAAY,SAAS,CAACH,EAAG,KAAK,CAACL,EAAIS,GAAG,+B,YCAtJC,EAAS,GAKTC,EAAY,eACdD,EACAX,EACAQ,GACA,EACA,KACA,KACA,MAIa,aAAAI,E","file":"js/about.5bee4903.js","sourcesContent":["var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _vm._m(0)}\nvar staticRenderFns = [function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{staticClass:\"about\"},[_c('h1',[_vm._v(\"This is an about page\")])])}]\n\nexport { render, staticRenderFns }","import { render, staticRenderFns } from \"./About.vue?vue&type=template&id=1ae8a7be&\"\nvar script = {}\n\n\n/* normalize component */\nimport normalizer from \"!../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n null,\n null\n \n)\n\nexport default component.exports"],"sourceRoot":""}
--------------------------------------------------------------------------------
/bin/pgdbi/dist/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/graphile-contrib/pgdbi/47d3b0454fde69836e99a388f88b00a8463f4285/bin/pgdbi/dist/logo.png
--------------------------------------------------------------------------------
/bin/pgdbi/graphile-extensions/dbSchema/introspection.js:
--------------------------------------------------------------------------------
1 | const util = require('util')
2 | const pgdbiApp = require('../../index')
3 |
4 | module.exports = build => {
5 | return async (_schema, args, context, resolveInfo) => {
6 | return pgdbiApp.schemaTree()
7 | };
8 | };
9 |
--------------------------------------------------------------------------------
/bin/pgdbi/graphile-extensions/dbSchema/pgdbiOptions.js:
--------------------------------------------------------------------------------
1 | const util = require('util')
2 | const pgdbiApp = require('../../index')
3 |
4 | module.exports = build => {
5 | return async (_schema, args, context, resolveInfo) => {
6 | return pgdbiApp.pdgbiOptions()
7 | };
8 | };
9 |
--------------------------------------------------------------------------------
/bin/pgdbi/graphile-extensions/dbSchema/resolvers/checkConstraint/tableConstraint.js:
--------------------------------------------------------------------------------
1 | const clog = require('fbkt-clog');
2 |
3 | module.exports = build => {
4 | return async (_checkConstraint, args, context, resolveInfo) => {
5 | const { pgSql: sql } = build;
6 | try {
7 | const constraintSchema = _checkConstraint.constraintSchema;
8 | const constraintName = _checkConstraint.constraintName;
9 |
10 | const rows = await resolveInfo.graphile.selectGraphQLResultFromTable(
11 | sql.fragment`information_schema.table_constraints`,
12 | (tableAlias, sqlBuilder) => {
13 | sqlBuilder.where(
14 | sql.fragment`${tableAlias}.constraint_schema = ${sql.value(
15 | constraintSchema,
16 | )}`,
17 | );
18 | sqlBuilder.where(
19 | sql.fragment`${tableAlias}.constraint_name = ${sql.value(
20 | constraintName,
21 | )}`,
22 | );
23 | },
24 | );
25 |
26 | return rows;
27 | } catch (e) {
28 | throw e;
29 | }
30 | };
31 | };
32 |
--------------------------------------------------------------------------------
/bin/pgdbi/graphile-extensions/dbSchema/resolvers/column/keyColumnUsage.js:
--------------------------------------------------------------------------------
1 | const clog = require('fbkt-clog');
2 |
3 | module.exports = build => {
4 | return async (_column, args, context, resolveInfo) => {
5 | const { pgSql: sql } = build;
6 | try {
7 | const tableSchema = _column.tableSchema;
8 | const tableName = _column.tableName;
9 | const columnName = _column.columnName;
10 |
11 | const rows = await resolveInfo.graphile.selectGraphQLResultFromTable(
12 | sql.fragment`information_schema.key_column_usage`,
13 | (tableAlias, sqlBuilder) => {
14 | sqlBuilder.where(
15 | sql.fragment`${tableAlias}.table_schema = ${sql.value(
16 | tableSchema,
17 | )}`,
18 | );
19 | sqlBuilder.where(
20 | sql.fragment`${tableAlias}.table_name = ${sql.value(tableName)}`,
21 | );
22 | sqlBuilder.where(
23 | sql.fragment`${tableAlias}.column_name = ${sql.value(columnName)}`,
24 | );
25 | },
26 | );
27 |
28 | return rows;
29 | } catch (e) {
30 | throw e;
31 | }
32 | };
33 | };
34 |
--------------------------------------------------------------------------------
/bin/pgdbi/graphile-extensions/dbSchema/resolvers/enabledRole/applicableRoles.js:
--------------------------------------------------------------------------------
1 | const clog = require('fbkt-clog');
2 |
3 | module.exports = build => {
4 | return async (_enabledRole, args, context, resolveInfo) => {
5 | const { pgSql: sql } = build;
6 | try {
7 | const roleName = _enabledRole.roleName;
8 |
9 | const rows = await resolveInfo.graphile.selectGraphQLResultFromTable(
10 | sql.fragment`information_schema.applicable_roles`,
11 | (tableAlias, sqlBuilder) => {
12 | sqlBuilder.where(
13 | sql.fragment`${tableAlias}.grantee = ${sql.value(roleName)}`,
14 | );
15 | },
16 | );
17 |
18 | return rows;
19 | } catch (e) {
20 | throw e;
21 | }
22 | };
23 | };
24 |
--------------------------------------------------------------------------------
/bin/pgdbi/graphile-extensions/dbSchema/resolvers/function/functionById.js:
--------------------------------------------------------------------------------
1 | module.exports = build => {
2 | return async (_schema, args, context, resolveInfo) => {
3 | const { pgClient } = context;
4 | try {
5 | const schemaName = args.id.split(':')[1].split('.')[0];
6 | const functionName = args.id.split(':')[1].split('.')[1];
7 |
8 | const sql = `
9 | select
10 | jsonb_build_object(
11 | 'functionById', (
12 | jsonb_build_object(
13 | 'id', 'function:' || n.nspname || '.' || p.proname
14 | ,'functionName', p.proname
15 | ,'functionSchema', n.nspname
16 | ,'resultDataType', coalesce(pg_catalog.pg_get_function_result(p.oid), 'N/A')
17 | ,'argumentDataTypes', coalesce(pg_catalog.pg_get_function_arguments(p.oid), 'N/A')
18 | ,'definition', coalesce(pg_catalog.pg_get_functiondef(p.oid)::text, 'N/A')
19 | )
20 | )
21 | )
22 | from pg_catalog.pg_proc p
23 | left join pg_catalog.pg_namespace n ON n.oid = p.pronamespace
24 | where n.nspname = '${schemaName}'
25 | and p.proname = '${functionName}'
26 | ;
27 | `;
28 |
29 | const result = await pgClient.query(sql, []);
30 |
31 | return result.rows[0].jsonb_build_object.functionById;
32 | } catch (e) {
33 | throw e;
34 | }
35 | };
36 | };
37 |
--------------------------------------------------------------------------------
/bin/pgdbi/graphile-extensions/dbSchema/resolvers/function/searchFunctions.js:
--------------------------------------------------------------------------------
1 | module.exports = build => {
2 | return async (_schema, args, context, resolveInfo) => {
3 | const { pgClient } = context;
4 | try {
5 | const searchTerm = args.searchTerm;
6 |
7 | const sql = `
8 | with procs as (
9 | select
10 | p.oid
11 | ,p.proname
12 | ,n.nspname
13 | from pg_proc p
14 | join pg_catalog.pg_namespace n ON n.oid = p.pronamespace
15 | where lower(p.prosrc) like '%${searchTerm}%'
16 | or lower(p.proname) like '%%${searchTerm}%'
17 | )
18 | select
19 | jsonb_build_object(
20 | 'searchFunctions', (
21 | coalesce(
22 | array_agg(
23 | jsonb_build_object(
24 | 'id', 'function:' || p.nspname || '.' || p.proname
25 | ,'functionName', p.proname
26 | ,'functionSchema', p.nspname
27 | ,'resultDataType', coalesce(pg_catalog.pg_get_function_result(p.oid), 'N/A')
28 | ,'argumentDataTypes', coalesce(pg_catalog.pg_get_function_arguments(p.oid), 'N/A')
29 | ,'definition', coalesce(pg_catalog.pg_get_functiondef(p.oid)::text, 'N/A')
30 | )
31 | )
32 | )
33 | )
34 | )
35 | from procs p
36 | ;
37 | `;
38 |
39 | const result = await pgClient.query(sql, []);
40 |
41 | return result.rows[0].jsonb_build_object.searchFunctions;
42 | } catch (e) {
43 | throw e;
44 | }
45 | };
46 | };
47 |
--------------------------------------------------------------------------------
/bin/pgdbi/graphile-extensions/dbSchema/resolvers/keyColumnUsage/referentialConstraints.js:
--------------------------------------------------------------------------------
1 | const clog = require('fbkt-clog');
2 |
3 | module.exports = build => {
4 | return async (_keyColumnUsage, args, context, resolveInfo) => {
5 | const { pgSql: sql } = build;
6 | try {
7 | const constraintSchema = _keyColumnUsage.tableSchema;
8 | const constraintName = _keyColumnUsage.constraintName;
9 |
10 | const rows = await resolveInfo.graphile.selectGraphQLResultFromTable(
11 | sql.fragment`information_schema.referential_constraints`,
12 | (tableAlias, sqlBuilder) => {
13 | sqlBuilder.where(
14 | sql.fragment`${tableAlias}.constraint_schema = ${sql.value(
15 | constraintSchema,
16 | )}`,
17 | );
18 | sqlBuilder.where(
19 | sql.fragment`${tableAlias}.constraint_name = ${sql.value(
20 | constraintName,
21 | )}`,
22 | );
23 | },
24 | );
25 |
26 | return rows;
27 | } catch (e) {
28 | throw e;
29 | }
30 | };
31 | };
32 |
--------------------------------------------------------------------------------
/bin/pgdbi/graphile-extensions/dbSchema/resolvers/referentialConstraint/referencedColumnUsage.js:
--------------------------------------------------------------------------------
1 | const clog = require('fbkt-clog');
2 |
3 | module.exports = build => {
4 | return async (_referentialConstraint, args, context, resolveInfo) => {
5 | const { pgSql: sql } = build;
6 | try {
7 | const constraintSchema = _referentialConstraint.uniqueConstraintSchema;
8 | const constraintName = _referentialConstraint.uniqueConstraintName;
9 |
10 | const rows = await resolveInfo.graphile.selectGraphQLResultFromTable(
11 | sql.fragment`information_schema.key_column_usage`,
12 | (tableAlias, sqlBuilder) => {
13 | sqlBuilder.where(
14 | sql.fragment`${tableAlias}.constraint_schema = ${sql.value(
15 | constraintSchema,
16 | )}`,
17 | );
18 | sqlBuilder.where(
19 | sql.fragment`${tableAlias}.constraint_name = ${sql.value(
20 | constraintName,
21 | )}`,
22 | );
23 | },
24 | );
25 |
26 | return rows;
27 | } catch (e) {
28 | throw e;
29 | }
30 | };
31 | };
32 |
--------------------------------------------------------------------------------
/bin/pgdbi/graphile-extensions/dbSchema/resolvers/referentialConstraint/referencingColumnUsage.js:
--------------------------------------------------------------------------------
1 | const clog = require('fbkt-clog');
2 |
3 | module.exports = build => {
4 | return async (_referentialConstraint, args, context, resolveInfo) => {
5 | const { pgSql: sql } = build;
6 | try {
7 | const constraintSchema = _referentialConstraint.constraintSchema;
8 | const constraintName = _referentialConstraint.constraintName;
9 |
10 | const rows = await resolveInfo.graphile.selectGraphQLResultFromTable(
11 | sql.fragment`information_schema.key_column_usage`,
12 | (tableAlias, sqlBuilder) => {
13 | sqlBuilder.where(
14 | sql.fragment`${tableAlias}.constraint_schema = ${sql.value(
15 | constraintSchema,
16 | )}`,
17 | );
18 | sqlBuilder.where(
19 | sql.fragment`${tableAlias}.constraint_name = ${sql.value(
20 | constraintName,
21 | )}`,
22 | );
23 | },
24 | );
25 |
26 | return rows;
27 | } catch (e) {
28 | throw e;
29 | }
30 | };
31 | };
32 |
--------------------------------------------------------------------------------
/bin/pgdbi/graphile-extensions/dbSchema/resolvers/schema/id.js:
--------------------------------------------------------------------------------
1 | const clog = require('fbkt-clog');
2 |
3 | module.exports = build => {
4 | return async (_schema, args, context, resolveInfo) => {
5 | const { pgSql: sql } = build;
6 | try {
7 | const schemaName = _schema.schemaName;
8 |
9 | return `schema:${schemaName}`;
10 | } catch (e) {
11 | throw e;
12 | }
13 | };
14 | };
15 |
--------------------------------------------------------------------------------
/bin/pgdbi/graphile-extensions/dbSchema/resolvers/schema/schemaEnums.js:
--------------------------------------------------------------------------------
1 | const clog = require('fbkt-clog');
2 |
3 | module.exports = build => {
4 | return async (_schema, args, context, resolveInfo) => {
5 | const { pgClient } = context;
6 | try {
7 | const schemaName = _schema.schemaName;
8 |
9 | const sql = `
10 | select jsonb_build_object(
11 | 'id', 'enum:' || n.nspname || '.' || t.typname
12 | ,'enumName', t.typname
13 | ,'enumSchema', n.nspname
14 | ,'enumValues', (
15 | with vals as(
16 | select e.enumlabel
17 | from pg_enum e
18 | where e.enumtypid = t.oid
19 | order by e.enumlabel
20 | )
21 | select array_agg(enumlabel)
22 | from vals
23 | )
24 | )
25 | from pg_type t
26 | join pg_catalog.pg_namespace n ON n.oid = t.typnamespace
27 | where t.oid in (select enumtypid from pg_enum)
28 | and n.nspname = '${schemaName}'
29 | group by
30 | n.nspname
31 | ,t.typname
32 | ,t.oid
33 | order by
34 | t.typname
35 | ;
36 | `;
37 |
38 | const result = await pgClient.query(sql, []);
39 |
40 | return result.rows.map(r => {
41 | return r.jsonb_build_object;
42 | });
43 | } catch (e) {
44 | throw e;
45 | }
46 | };
47 | };
48 |
--------------------------------------------------------------------------------
/bin/pgdbi/graphile-extensions/dbSchema/resolvers/schema/schemaFunctions.js:
--------------------------------------------------------------------------------
1 | module.exports = build => {
2 | return async (_schema, args, context, resolveInfo) => {
3 | const { pgClient } = context;
4 | try {
5 | const schemaName = _schema.schemaName;
6 |
7 | const sql = `
8 | select
9 | jsonb_build_object(
10 | 'schemaFunctions', (
11 | coalesce(
12 | array_agg(
13 | jsonb_build_object(
14 | 'id', 'function:' || n.nspname || '.' || p.proname
15 | ,'functionName', p.proname
16 | ,'functionSchema', n.nspname
17 | )
18 | )
19 | , '{}')
20 | )
21 | )
22 | from pg_catalog.pg_proc p
23 | left join pg_catalog.pg_namespace n ON n.oid = p.pronamespace
24 | where n.nspname = '${schemaName}'
25 | -- group by p.proname
26 | -- order by p.proname
27 | ;
28 | `;
29 |
30 | const result = await pgClient.query(sql, []);
31 | return result.rows[0].jsonb_build_object.schemaFunctions;
32 | } catch (e) {
33 | console.log('err', e);
34 | throw e;
35 | }
36 | };
37 | };
38 |
--------------------------------------------------------------------------------
/bin/pgdbi/graphile-extensions/dbSchema/resolvers/schema/schemaTables.js:
--------------------------------------------------------------------------------
1 | module.exports = build => {
2 | return async (_schema, args, context, resolveInfo) => {
3 | const { pgSql: sql } = build;
4 | try {
5 | const schemaName = _schema.schemaName;
6 |
7 | const rows = await resolveInfo.graphile.selectGraphQLResultFromTable(
8 | sql.fragment`information_schema.tables`,
9 | (tableAlias, sqlBuilder) => {
10 | sqlBuilder.where(
11 | sql.fragment`${tableAlias}.table_schema = ${sql.value(schemaName)}`,
12 | );
13 | sqlBuilder.where(
14 | sql.fragment`${tableAlias}.table_type = 'BASE TABLE'`,
15 | );
16 | sqlBuilder.orderBy(() => sql.fragment`table_name`, true);
17 | },
18 | );
19 |
20 | return rows;
21 | } catch (e) {
22 | throw e;
23 | }
24 | };
25 | };
26 |
--------------------------------------------------------------------------------
/bin/pgdbi/graphile-extensions/dbSchema/resolvers/schema/schemaTreeBySchemaName.js:
--------------------------------------------------------------------------------
1 | module.exports = build => {
2 | return async (_schema, args, context, resolveInfo) => {
3 | const { pgSql: sql } = build;
4 | try {
5 | const schemaName = _schema.schemaName;
6 |
7 | const rows = await resolveInfo.graphile.selectGraphQLResultFromTable(
8 | sql.fragment`information_schema.tables`,
9 | (tableAlias, sqlBuilder) => {
10 | sqlBuilder.where(
11 | sql.fragment`${tableAlias}.table_schema = ${sql.value(schemaName)}`,
12 | );
13 | sqlBuilder.where(
14 | sql.fragment`${tableAlias}.table_type = 'BASE TABLE'`,
15 | );
16 | sqlBuilder.orderBy(() => sql.fragment`table_name`, true);
17 | },
18 | );
19 |
20 | return rows;
21 | } catch (e) {
22 | throw e;
23 | }
24 | };
25 | };
26 |
--------------------------------------------------------------------------------
/bin/pgdbi/graphile-extensions/dbSchema/resolvers/table/checkConstraints.js:
--------------------------------------------------------------------------------
1 | const clog = require('fbkt-clog');
2 |
3 | module.exports = build => {
4 | return async (_table, args, context, resolveInfo) => {
5 | const { pgSql: sql } = build;
6 | try {
7 | const constraintSchema = _table.tableSchema;
8 | const tableName = _table.tableName;
9 |
10 | const rows = await resolveInfo.graphile.selectGraphQLResultFromTable(
11 | sql.fragment`information_schema.check_constraints`,
12 | (tableAlias, sqlBuilder) => {
13 | sqlBuilder.where(
14 | sql.fragment`${tableAlias}.constraint_schema = ${sql.value(
15 | constraintSchema,
16 | )}`,
17 | );
18 | sqlBuilder.where(
19 | sql.fragment`${tableAlias}.constraint_name in (
20 | SELECT constraint_name
21 | from information_schema.table_constraints
22 | where table_name = ${sql.value(tableName)}
23 | )`,
24 | );
25 | },
26 | );
27 |
28 | return rows;
29 | } catch (e) {
30 | throw e;
31 | }
32 | };
33 | };
34 |
--------------------------------------------------------------------------------
/bin/pgdbi/graphile-extensions/dbSchema/resolvers/table/id.js:
--------------------------------------------------------------------------------
1 | const clog = require('fbkt-clog');
2 |
3 | module.exports = build => {
4 | return async (_table, args, context, resolveInfo) => {
5 | const { pgSql: sql } = build;
6 | try {
7 | const tableSchema = _table.tableSchema;
8 | const tableName = _table.tableName;
9 |
10 | return `table:${tableSchema}.${tableName}`;
11 | } catch (e) {
12 | throw e;
13 | }
14 | };
15 | };
16 |
--------------------------------------------------------------------------------
/bin/pgdbi/graphile-extensions/dbSchema/resolvers/table/indices.js:
--------------------------------------------------------------------------------
1 | module.exports = build => {
2 | return async (_table, args, context, resolveInfo) => {
3 | const { pgClient } = context;
4 | try {
5 | const tableSchema = _table.tableSchema;
6 | const tableName = _table.tableName;
7 |
8 | const sql = `
9 | select
10 | ns.nspname || '.' || t.relname id
11 | ,t.relname "tableName"
12 | ,ns.nspname "tableSchema"
13 | ,a.attname "columnName"
14 | ,i.relname "indexName"
15 | from
16 | pg_index ix
17 | join pg_class t on t.oid = ix.indrelid
18 | join pg_class i on i.oid = ix.indexrelid
19 | join pg_namespace ns on t.relnamespace = ns.oid
20 | join pg_attribute a on a.attrelid = t.oid and a.attnum = ANY(ix.indkey)
21 | where
22 | ns.nspname = '${tableSchema}'
23 | and
24 | t.relname = '${tableName}'
25 | group by
26 | ns.nspname,
27 | t.relname,
28 | a.attname,
29 | i.relname
30 | order by
31 | ns.nspname,
32 | t.relname,
33 | a.attname,
34 | i.relname
35 | ;
36 | `;
37 |
38 | const result = await pgClient.query(sql, []);
39 | return result.rows;
40 | } catch (e) {
41 | throw e;
42 | }
43 | };
44 | };
45 |
46 | // select
47 | // jsonb_build_object(
48 | // 'tableIndices', (
49 | // coalesce(
50 | // array_agg(
51 | // jsonb_build_object(
52 | // 'id', 'index:' || ns.nspname || '.' || t.relname
53 | // ,'tableName', t.relname
54 | // ,'tableSchema', ns.nspname
55 | // ,'columnName', a.attname
56 | // ,'indexName', i.relname
57 | // )
58 | // )
59 | // , '{}')
60 | // )
61 | // )
62 |
--------------------------------------------------------------------------------
/bin/pgdbi/graphile-extensions/dbSchema/resolvers/table/policies.js:
--------------------------------------------------------------------------------
1 | module.exports = build => {
2 | return async (_table, args, context, resolveInfo) => {
3 | const { pgClient } = context;
4 | try {
5 | const tableSchema = _table.tableSchema;
6 | const tableName = _table.tableName;
7 |
8 | const sql = `
9 | select
10 | jsonb_build_object(
11 | 'tablePolicies', (
12 | coalesce(
13 | array_agg(
14 | jsonb_build_object(
15 | 'schemaName', p.schemaname
16 | ,'tableName', p.tablename
17 | ,'policyName', p.policyname
18 | ,'roles', p.roles
19 | ,'cmd', p.cmd
20 | ,'qual', p.qual
21 | ,'withCheck', p.with_check
22 | )
23 | )
24 | , '{}')
25 | )
26 | )
27 | FROM pg_policies p
28 | where
29 | p.schemaname = '${tableSchema}'
30 | and
31 | p.tablename = '${tableName}'
32 | ;
33 | `;
34 |
35 | const result = await pgClient.query(sql, []);
36 | return result.rows[0].jsonb_build_object.tablePolicies;
37 | } catch (e) {
38 | throw e;
39 | }
40 | };
41 | };
42 |
--------------------------------------------------------------------------------
/bin/pgdbi/graphile-extensions/dbSchema/resolvers/table/primaryKeyConstraints.js:
--------------------------------------------------------------------------------
1 | const clog = require('fbkt-clog');
2 |
3 | module.exports = build => {
4 | return async (_table, args, context, resolveInfo) => {
5 | const { pgSql: sql } = build;
6 | try {
7 | const tableSchema = _table.tableSchema;
8 | const tableName = _table.tableName;
9 |
10 | const rows = await resolveInfo.graphile.selectGraphQLResultFromTable(
11 | sql.fragment`information_schema.table_constraints`,
12 | (tableAlias, sqlBuilder) => {
13 | sqlBuilder.where(
14 | sql.fragment`${tableAlias}.table_name = ${sql.value(tableName)}`,
15 | );
16 | sqlBuilder.where(
17 | sql.fragment`${tableAlias}.table_schema = ${sql.value(
18 | tableSchema,
19 | )}`,
20 | );
21 |
22 | sqlBuilder.where(
23 | sql.fragment`${tableAlias}.constraint_type = ${sql.value(
24 | 'PRIMARY KEY',
25 | )}`,
26 | );
27 | },
28 | );
29 |
30 | return rows;
31 | } catch (e) {
32 | throw e;
33 | }
34 | };
35 | };
36 |
--------------------------------------------------------------------------------
/bin/pgdbi/graphile-extensions/dbSchema/resolvers/table/psqlDescription.js:
--------------------------------------------------------------------------------
1 | module.exports = build => {
2 | return async (_table, args, context, resolveInfo) => {
3 | const { pgClient } = context;
4 | try {
5 | console.log('_table', _table)
6 | const tableSchema = _table.tableSchema;
7 | const tableName = _table.tableName;
8 |
9 | const sql = `\d+ ${tableSchema}.${tableName};`;
10 | console.log('sql', sql)
11 |
12 | const result = await pgClient.query(sql, []);
13 | return result.rows[0].jsonb_build_object.tablePolicies;
14 | } catch (e) {
15 | throw e;
16 | }
17 | };
18 | };
19 |
--------------------------------------------------------------------------------
/bin/pgdbi/graphile-extensions/dbSchema/resolvers/table/referentialConstraints.js:
--------------------------------------------------------------------------------
1 | const clog = require('fbkt-clog');
2 |
3 | module.exports = build => {
4 | return async (_table, args, context, resolveInfo) => {
5 | const { pgSql: sql } = build;
6 | try {
7 | const constraintSchema = _table.tableSchema;
8 | const tableName = _table.tableName;
9 |
10 | const rows = await resolveInfo.graphile.selectGraphQLResultFromTable(
11 | sql.fragment`information_schema.referential_constraints`,
12 | (tableAlias, sqlBuilder) => {
13 | sqlBuilder.where(
14 | sql.fragment`${tableAlias}.constraint_schema = ${sql.value(
15 | constraintSchema,
16 | )}`,
17 | );
18 | sqlBuilder.where(
19 | sql.fragment`${tableAlias}.constraint_name in (
20 | SELECT constraint_name
21 | from information_schema.table_constraints
22 | where table_name = ${sql.value(tableName)}
23 | )`,
24 | );
25 | },
26 | );
27 |
28 | return rows;
29 | } catch (e) {
30 | throw e;
31 | }
32 | };
33 | };
34 |
--------------------------------------------------------------------------------
/bin/pgdbi/graphile-extensions/dbSchema/resolvers/table/roleColumnGrants.js:
--------------------------------------------------------------------------------
1 | const clog = require('fbkt-clog');
2 |
3 | module.exports = build => {
4 | return async (_table, args, context, resolveInfo) => {
5 | const { pgSql: sql } = build;
6 | try {
7 | const tableSchema = _table.tableSchema;
8 | const tableName = _table.tableName;
9 |
10 | const rows = await resolveInfo.graphile.selectGraphQLResultFromTable(
11 | sql.fragment`information_schema.role_column_grants`,
12 | (tableAlias, sqlBuilder) => {
13 | sqlBuilder.where(
14 | sql.fragment`${tableAlias}.table_schema = ${sql.value(
15 | tableSchema,
16 | )}`,
17 | );
18 | sqlBuilder.where(
19 | sql.fragment`${tableAlias}.table_name = ${sql.value(tableName)}`,
20 | );
21 | },
22 | );
23 |
24 | return rows;
25 | } catch (e) {
26 | throw e;
27 | }
28 | };
29 | };
30 |
--------------------------------------------------------------------------------
/bin/pgdbi/graphile-extensions/dbSchema/resolvers/table/roleTableGrants.js:
--------------------------------------------------------------------------------
1 | const clog = require('fbkt-clog');
2 |
3 | module.exports = build => {
4 | return async (_table, args, context, resolveInfo) => {
5 | const { pgSql: sql } = build;
6 | try {
7 | const tableSchema = _table.tableSchema;
8 | const tableName = _table.tableName;
9 |
10 | const rows = await resolveInfo.graphile.selectGraphQLResultFromTable(
11 | sql.fragment`information_schema.role_table_grants`,
12 | (tableAlias, sqlBuilder) => {
13 | sqlBuilder.where(
14 | sql.fragment`${tableAlias}.table_schema = ${sql.value(
15 | tableSchema,
16 | )}`,
17 | );
18 | sqlBuilder.where(
19 | sql.fragment`${tableAlias}.table_name = ${sql.value(tableName)}`,
20 | );
21 | sqlBuilder.where(sql.fragment`${tableAlias}.grantee != 'postgres'`);
22 | },
23 | );
24 |
25 | return rows;
26 | } catch (e) {
27 | throw e;
28 | }
29 | };
30 | };
31 |
--------------------------------------------------------------------------------
/bin/pgdbi/graphile-extensions/dbSchema/resolvers/table/tableById.js:
--------------------------------------------------------------------------------
1 | module.exports = build => {
2 | return async (_schema, args, context, resolveInfo) => {
3 | const { pgSql: sql } = build;
4 | try {
5 | const tableSchema = args.id.split(':')[1].split('.')[0];
6 | const tableName = args.id.split(':')[1].split('.')[1];
7 |
8 | // console.log('args', args)
9 | // console.log('tableSchema', tableSchema)
10 | // console.log('tableName', tableName)
11 |
12 | const rows = await resolveInfo.graphile.selectGraphQLResultFromTable(
13 | sql.fragment`information_schema.tables`,
14 | (tableAlias, sqlBuilder) => {
15 | sqlBuilder.where(
16 | sql.fragment`${tableAlias}.table_schema = ${sql.value(
17 | tableSchema,
18 | )}`,
19 | );
20 | sqlBuilder.where(
21 | sql.fragment`${tableAlias}.table_name = ${sql.value(tableName)}`,
22 | );
23 | },
24 | );
25 |
26 | return rows[0];
27 | } catch (e) {
28 | throw e;
29 | }
30 | };
31 | };
32 |
--------------------------------------------------------------------------------
/bin/pgdbi/graphile-extensions/dbSchema/resolvers/table/tableColumns.js:
--------------------------------------------------------------------------------
1 | module.exports = build => {
2 | return async (_table, args, context, resolveInfo) => {
3 | const { pgSql: sql } = build;
4 | try {
5 | const tableSchema = _table.tableSchema;
6 | const tableName = _table.tableName;
7 |
8 | const rows = await resolveInfo.graphile.selectGraphQLResultFromTable(
9 | sql.fragment`information_schema.columns`,
10 | (tableAlias, sqlBuilder) => {
11 | sqlBuilder.where(
12 | sql.fragment`${tableAlias}.table_schema = ${sql.value(
13 | tableSchema,
14 | )}`,
15 | );
16 | sqlBuilder.where(
17 | sql.fragment`${tableAlias}.table_name = ${sql.value(tableName)}`,
18 | );
19 | },
20 | );
21 |
22 | return rows;
23 | } catch (e) {
24 | throw e;
25 | }
26 | };
27 | };
28 |
--------------------------------------------------------------------------------
/bin/pgdbi/graphile-extensions/dbSchema/resolvers/table/tableConstraints.js:
--------------------------------------------------------------------------------
1 | module.exports = build => {
2 | return async (_table, args, context, resolveInfo) => {
3 | const { pgSql: sql } = build;
4 | try {
5 | const tableSchema = _table.tableSchema;
6 | const tableName = _table.tableName;
7 |
8 | const rows = await resolveInfo.graphile.selectGraphQLResultFromTable(
9 | sql.fragment`information_schema.constraint_table_usage`,
10 | (tableAlias, sqlBuilder) => {
11 | sqlBuilder.where(
12 | sql.fragment`${tableAlias}.table_schema = ${sql.value(
13 | tableSchema,
14 | )}`,
15 | );
16 | sqlBuilder.where(
17 | sql.fragment`${tableAlias}.table_name = ${sql.value(tableName)}`,
18 | );
19 | },
20 | );
21 |
22 | return rows;
23 | } catch (e) {
24 | throw e;
25 | }
26 | };
27 | };
28 |
--------------------------------------------------------------------------------
/bin/pgdbi/graphile-extensions/dbSchema/resolvers/table/triggers.js:
--------------------------------------------------------------------------------
1 | module.exports = build => {
2 | return async (_table, args, context, resolveInfo) => {
3 | const { pgSql: sql } = build;
4 | try {
5 | const tableSchema = _table.tableSchema;
6 | const tableName = _table.tableName;
7 |
8 | const rows = await resolveInfo.graphile.selectGraphQLResultFromTable(
9 | sql.fragment`information_schema.triggers`,
10 | (tableAlias, sqlBuilder) => {
11 | sqlBuilder.where(
12 | sql.fragment`${tableAlias}.event_object_schema = ${sql.value(
13 | tableSchema,
14 | )}`,
15 | );
16 | sqlBuilder.where(
17 | sql.fragment`${tableAlias}.event_object_table = ${sql.value(
18 | tableName,
19 | )}`,
20 | );
21 | },
22 | );
23 |
24 | return rows;
25 | } catch (e) {
26 | throw e;
27 | }
28 | };
29 | };
30 |
--------------------------------------------------------------------------------
/bin/pgdbi/graphile-extensions/dbSchema/resolvers/table/uniqueConstraints.js:
--------------------------------------------------------------------------------
1 | const clog = require('fbkt-clog');
2 |
3 | module.exports = build => {
4 | return async (_table, args, context, resolveInfo) => {
5 | const { pgSql: sql } = build;
6 | try {
7 | const tableSchema = _table.tableSchema;
8 | const tableName = _table.tableName;
9 |
10 | const rows = await resolveInfo.graphile.selectGraphQLResultFromTable(
11 | sql.fragment`information_schema.table_constraints`,
12 | (tableAlias, sqlBuilder) => {
13 | sqlBuilder.where(
14 | sql.fragment`${tableAlias}.table_name = ${sql.value(tableName)}`,
15 | );
16 | sqlBuilder.where(
17 | sql.fragment`${tableAlias}.table_schema = ${sql.value(
18 | tableSchema,
19 | )}`,
20 | );
21 |
22 | sqlBuilder.where(
23 | sql.fragment`${tableAlias}.constraint_type = ${sql.value(
24 | 'UNIQUE',
25 | )}`,
26 | );
27 | },
28 | );
29 |
30 | return rows;
31 | } catch (e) {
32 | throw e;
33 | }
34 | };
35 | };
36 |
--------------------------------------------------------------------------------
/bin/pgdbi/graphile-extensions/dbSchema/resolvers/tableConstraint/keyColumnUsage.js:
--------------------------------------------------------------------------------
1 | const clog = require('fbkt-clog');
2 |
3 | module.exports = build => {
4 | return async (_tableConstraint, args, context, resolveInfo) => {
5 | const { pgSql: sql } = build;
6 | try {
7 | const constraintSchema = _tableConstraint.constraintSchema;
8 | const constraintName = _tableConstraint.constraintName;
9 |
10 | const rows = await resolveInfo.graphile.selectGraphQLResultFromTable(
11 | sql.fragment`information_schema.key_column_usage`,
12 | (tableAlias, sqlBuilder) => {
13 | sqlBuilder.where(
14 | sql.fragment`${tableAlias}.constraint_schema = ${sql.value(
15 | constraintSchema,
16 | )}`,
17 | );
18 | sqlBuilder.where(
19 | sql.fragment`${tableAlias}.constraint_name = ${sql.value(
20 | constraintName,
21 | )}`,
22 | );
23 | },
24 | );
25 |
26 | return rows;
27 | } catch (e) {
28 | throw e;
29 | }
30 | };
31 | };
32 |
--------------------------------------------------------------------------------
/bin/pgdbi/graphile-extensions/dbSchema/resolvers/trigger/id.js:
--------------------------------------------------------------------------------
1 | const clog = require('fbkt-clog');
2 |
3 | module.exports = build => {
4 | return async (_trigger, args, context, resolveInfo) => {
5 | const { pgSql: sql } = build;
6 | try {
7 | const eventManipulation = _trigger.eventManipulation;
8 | const eventObjectSchema = _trigger.eventObjectSchema;
9 | const eventObjectTable = _trigger.eventObjectTable;
10 | const actionTiming = _trigger.actionTiming;
11 |
12 | return `trigger:${actionTiming}.${eventManipulation}.${eventObjectSchema}.${eventObjectTable}`;
13 | } catch (e) {
14 | throw e;
15 | }
16 | };
17 | };
18 |
--------------------------------------------------------------------------------
/bin/pgdbi/graphile-extensions/dbSchema/resolvers/trigger/triggerFunction.js:
--------------------------------------------------------------------------------
1 | module.exports = build => {
2 | return async (_trigger, args, context, resolveInfo) => {
3 | const { pgClient } = context;
4 | try {
5 | // assumes action statement of the form: 'EXECUTE PROCEDURE schema_name.function_name()'
6 | const schemaName = _trigger.actionStatement.split(' ')[2].split('.')[0];
7 | const functionName = _trigger.actionStatement
8 | .split(' ')[2]
9 | .split('.')[1]
10 | .split('(')[0];
11 |
12 | const sql = `
13 | select
14 | jsonb_build_object(
15 | 'triggerFunction', (
16 | jsonb_build_object(
17 | 'id', 'function:' || n.nspname || '.' || p.proname
18 | ,'functionName', p.proname
19 | ,'functionSchema', n.nspname
20 | ,'resultDataType', coalesce(pg_catalog.pg_get_function_result(p.oid), 'N/A')
21 | ,'argumentDataTypes', coalesce(pg_catalog.pg_get_function_arguments(p.oid), 'N/A')
22 | ,'definition', coalesce(pg_catalog.pg_get_functiondef(p.oid)::text, 'N/A')
23 | )
24 | )
25 | )
26 | from pg_catalog.pg_proc p
27 | left join pg_catalog.pg_namespace n ON n.oid = p.pronamespace
28 | where n.nspname = '${schemaName}'
29 | and p.proname = '${functionName}'
30 | ;
31 | `;
32 | // console.log('sql',sql)
33 | const result = await pgClient.query(sql, []);
34 | // console.log('result',result)
35 | return result.rows[0].jsonb_build_object.triggerFunction;
36 | } catch (e) {
37 | throw e;
38 | }
39 | };
40 | };
41 |
--------------------------------------------------------------------------------
/bin/pgdbi/graphile-extensions/execSql.js:
--------------------------------------------------------------------------------
1 | const { makeExtendSchemaPlugin, gql } = require("graphile-utils");
2 |
3 | const ExecSqlPlugin = makeExtendSchemaPlugin(build => {
4 | const { pgSql: sql } = build;
5 | return {
6 | typeDefs: gql`
7 | input ExecSqlInput {
8 | clientMutationId: String
9 | sql: String!
10 | }
11 |
12 | type ExecSqlPayload {
13 | sql: String!
14 | result: JSON!
15 | }
16 |
17 | extend type Mutation {
18 | ExecSql(input: ExecSqlInput!): ExecSqlPayload
19 | }
20 | `,
21 | resolvers: {
22 | Mutation: {
23 | ExecSql: async (
24 | _mutation,
25 | args,
26 | context,
27 | resolveInfo,
28 | { selectGraphQLResultFromTable }
29 | ) => {
30 | const { pgClient } = context;
31 | // Start a sub-transaction
32 | await pgClient.query("SAVEPOINT graphql_mutation");
33 | try {
34 |
35 | // clog('LET US EXEC SQL', pgClient)
36 | const result = await pgClient.query(args.input.sql, []);
37 |
38 | await pgClient.query("RELEASE SAVEPOINT graphql_mutation");
39 |
40 | return {
41 | sql: args.input.sql,
42 | result: result
43 | };
44 | } catch (e) {
45 | // Oh noes! If at first you don't succeed,
46 | // destroy all evidence you ever tried.
47 | await pgClient.query("ROLLBACK TO SAVEPOINT graphql_mutation");
48 | throw e;
49 | }
50 | },
51 | },
52 | },
53 | };
54 | });
55 |
56 | module.exports = ExecSqlPlugin
57 |
58 |
59 | // the above was built from the below
60 | // https://www.graphile.org/postgraphile/make-extend-schema-plugin/
61 |
--------------------------------------------------------------------------------
/bin/pgdbi/graphile-extensions/pgIntrospectionResultsByKind.js:
--------------------------------------------------------------------------------
1 | module.exports = callback => builder => builder.hook('build', (build) =>{callback(build.pgIntrospectionResultsByKind); return build})
2 |
--------------------------------------------------------------------------------
/bin/pgdbi/graphile-extensions/pgdbirc-default.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | defaultRlsUsing: '( owner_id = viewer_id() )',
3 | allRoleSets: [
4 | {
5 | name: 'graphile-visitor',
6 | dbOwnerRole: {
7 | roleName: 'app_owner',
8 | applicableRoles: []
9 | },
10 | dbAuthenticatorRole: {
11 | roleName: 'app_authenticator',
12 | applicableRoles: [ {roleName: 'app_visitor'}, {roleName: 'app_anonymous'} ]
13 | },
14 | dbUserRoles: [
15 | {
16 | roleName: 'app_visitor',
17 | applicableRoles: [ {roleName: 'app_anonymous'} ]
18 | },
19 | {
20 | roleName: 'app_anonymous',
21 | applicableRoles: []
22 | }
23 | ],
24 | },
25 | {
26 | name: 'multi-user',
27 | dbOwnerRole: {
28 | roleName: 'app_owner',
29 | applicableRoles: []
30 | },
31 | dbAuthenticatorRole: {
32 | roleName: 'app_authenticator',
33 | applicableRoles: [ {roleName: 'app_super_admin'}, {roleName: 'app_admin'}, {roleName: 'app_user'}, {roleName: 'app_anonymous'} ]
34 | },
35 | dbUserRoles: [
36 | {
37 | roleName: 'app_super_admin',
38 | applicableRoles: [ {roleName: 'app_admin'}, {roleName: 'app_user'}, {roleName: 'app_anonymous'} ]
39 | },
40 | {
41 | roleName: 'app_admin',
42 | applicableRoles: [ {roleName: 'app_user'}, {roleName: 'app_anonymous'} ]
43 | },
44 | {
45 | roleName: 'app_user',
46 | applicableRoles: [ {roleName: 'app_anonymous'} ]
47 | },
48 | {
49 | roleName: 'app_anonymous',
50 | applicableRoles: []
51 | }
52 | ]
53 | }
54 | ]
55 | }
56 |
--------------------------------------------------------------------------------
/bin/pgdbi/graphile-extensions/pgdbirc.js:
--------------------------------------------------------------------------------
1 | const { makeExtendSchemaPlugin, gql } = require("graphile-utils");
2 | const fs = require('fs')
3 | const defaultPgdbirc = require('./pgdbirc-default')
4 |
5 | const PGDBIRCPlugin = makeExtendSchemaPlugin(build => {
6 | const { pgSql: sql } = build;
7 | const pgdbiDir = `${process.cwd()}/.pgdbi`
8 | const pgdbircPath = `${pgdbiDir}/.pgdbirc.json`
9 |
10 | fs.mkdirSync(pgdbiDir, {recursive: true})
11 |
12 | const exists = fs.existsSync(pgdbircPath)
13 | if (!exists) {
14 | fs.writeFileSync(pgdbircPath, JSON.stringify(defaultPgdbirc,0,2))
15 | }
16 |
17 | return {
18 | typeDefs: gql`
19 | type PGDBIRCPayload {
20 | pgdbirc: JSON!
21 | }
22 |
23 | extend type Query {
24 | PGDBIRC: PGDBIRCPayload
25 | }
26 | `,
27 | resolvers: {
28 | Query: {
29 | PGDBIRC: async (
30 | _query,
31 | args,
32 | context,
33 | resolveInfo,
34 | { selectGraphQLResultFromTable }
35 | ) => {
36 | try {
37 | const pgdbirc = fs.readFileSync(pgdbircPath)
38 |
39 | return {
40 | pgdbirc: JSON.parse(pgdbirc)
41 | };
42 | } catch (e) {
43 | // Oh noes! If at first you don't succeed,
44 | // destroy all evidence you ever tried.
45 | throw e;
46 | }
47 | },
48 | },
49 | },
50 | };
51 | });
52 |
53 | module.exports = PGDBIRCPlugin
54 |
--------------------------------------------------------------------------------
/bin/pgdbi/graphile-extensions/pglintrc-default.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | project: null,
3 | token: null
4 | }
5 |
--------------------------------------------------------------------------------
/bin/pgdbi/graphile-extensions/project.js:
--------------------------------------------------------------------------------
1 | const { makeExtendSchemaPlugin, gql } = require("graphile-utils");
2 | const fs = require('fs')
3 |
4 | const PGDBIRCPlugin = makeExtendSchemaPlugin(build => {
5 | const { pgSql: sql } = build;
6 | const pgdbiDir = `${process.cwd()}/.pgdbi`
7 | const projectPath = `${pgdbiDir}/project.json`
8 |
9 | return {
10 | typeDefs: gql`
11 | type ProjectPayload {
12 | project: JSON!
13 | }
14 |
15 | extend type Query {
16 | project: ProjectPayload
17 | }
18 | `,
19 | resolvers: {
20 | Query: {
21 | project: async (
22 | _query,
23 | args,
24 | context,
25 | resolveInfo,
26 | { selectGraphQLResultFromTable }
27 | ) => {
28 | try {
29 | const exists = fs.existsSync(projectPath)
30 | if (!exists) {
31 | throw new Error('Project file does not exist')
32 | }
33 |
34 | const project = fs.readFileSync(projectPath)
35 |
36 | return {
37 | project: JSON.parse(project)
38 | };
39 | } catch (e) {
40 | // Oh noes! If at first you don't succeed,
41 | // destroy all evidence you ever tried.
42 | throw e;
43 | }
44 | },
45 | },
46 | },
47 | };
48 | });
49 |
50 | module.exports = PGDBIRCPlugin
51 |
--------------------------------------------------------------------------------
/bin/pgdbi/transformBuild.js:
--------------------------------------------------------------------------------
1 | const camelCaseKeys = require('camelcase-keys')
2 | const pg10IntrospectionQuery = require('./pg10IntrospectionQuery')
3 |
4 | const queryBuilderMap = {
5 | "10": require('./pg10IntrospectionQuery'),
6 | "11": require('./pg11IntrospectionQuery'),
7 | "12": require('./pg11IntrospectionQuery')
8 | }
9 |
10 | async function transformBuild(build, pgPool) {
11 | try {
12 | const version = (await pgPool.query('SHOW server_version;')).rows[0].server_version.split('.')[0];
13 | console.log('version', version)
14 | // console.log('build.options', build.options)
15 | const schemas = build.options.pgSchemas.join("','");
16 | console.log('schemas', schemas)
17 | const querySql = await queryBuilderMap[version](schemas)
18 | const schemaTree = camelCaseKeys((await pgPool.query(querySql)).rows[0], {deep:true})
19 | return schemaTree
20 |
21 | } catch (e) {
22 | console.log('CAUGHT ERROR', e.toString())
23 | throw e;
24 | }
25 | }
26 |
27 | module.exports = transformBuild
--------------------------------------------------------------------------------
/bin/sql/schema_usage.sql:
--------------------------------------------------------------------------------
1 | WITH "names"("name") AS (
2 | SELECT n.nspname AS "name"
3 | FROM pg_catalog.pg_namespace n
4 | WHERE n.nspname !~ '^pg_'
5 | AND n.nspname <> 'information_schema'
6 | ) SELECT "name",
7 | pg_catalog.has_schema_privilege(current_user, "name", 'CREATE') AS "create",
8 | pg_catalog.has_schema_privilege(current_user, "name", 'USAGE') AS "usage"
9 | FROM "names";
10 |
--------------------------------------------------------------------------------
/build.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | rm -rf ./src/pgdbi/dist
4 | rm -rf ./bin/pgdbi
5 |
6 | cd ./src/web-vue
7 | yarn build
8 | cd ../..
9 | cp -R ./src/web-vue/dist ./src/pgdbi/dist/
10 | cp -R ./src/pgdbi ./bin/pgdbi/
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | module.exports = require('./bin/pgdbi');
2 |
--------------------------------------------------------------------------------
/introResult.json:
--------------------------------------------------------------------------------
1 | [object Object]
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@graphile-contrib/pgdbi",
3 | "version": "1.0.9-alpha.111",
4 | "main": "index.js",
5 | "repository": {
6 | "type": "git",
7 | "url": "https://github.com/graphile-contrib/pgdbi"
8 | },
9 | "license": "MIT",
10 | "scripts": {
11 | "dev-server": "node -r dotenv/config --inspect src/devServer",
12 | "dev-web-vue": "cd ./src/web-vue && yarn serve",
13 | "prettier:fix": "prettier --write 'src/**/*.{js,md,json}' '*.{js,md,json}'",
14 | "prod-build": "cd ./src/web-vue && yarn build"
15 | },
16 | "files": [
17 | "bin/**/*"
18 | ],
19 | "dependencies": {
20 | "@types/jest": "^24.0.16",
21 | "camelcase-keys": "^6.0.1",
22 | "compressed-json": "^1.0.15",
23 | "dotenv": "^8.1.0",
24 | "express": "^4.16.4",
25 | "fbkt-clog": "^1.0.5",
26 | "flatted": "^2.0.1",
27 | "graphile-utils": "^4.2.1",
28 | "graphile-worker": "^0.1.0-alpha.0",
29 | "handlebars": "^4.3.0",
30 | "pglint": "^1.1.0",
31 | "postgraphile": "^4.4.0",
32 | "postgraphile-plugin-connection-filter": "^1.0.1",
33 | "rimraf": "^3.0.2"
34 | },
35 | "devDependencies": {
36 | "@babel/cli": "^7.4.4",
37 | "@babel/core": "^7.4.5",
38 | "@babel/node": "^7.4.5",
39 | "@babel/preset-env": "^7.4.5",
40 | "@babel/preset-typescript": "^7.3.3",
41 | "babel-jest": "^24.8.0",
42 | "jest": "^24.8.0",
43 | "nodemon": "^1.19.1",
44 | "typescript": "^3.5.2"
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/pglint-bash.sh:
--------------------------------------------------------------------------------
1 | bash pglint.sh "0dc056d563216b428314add7" "stlbucket/pgdbi-try" "postgres://postgres:1234@0.0.0.0/lcb"
--------------------------------------------------------------------------------
/pglint-npx.sh:
--------------------------------------------------------------------------------
1 | npx pglint --token "0dc056d563216b428314add7" --project "stlbucket/pgdbi-try" --connection "postgres://postgres:1234@0.0.0.0/lcb"
--------------------------------------------------------------------------------
/project.md:
--------------------------------------------------------------------------------
1 | ### phase the now
2 |
3 | - [X] upgrade to latest vuetify 2
4 | - [X] hopefully vuetify 2 fixes the panel expansion problem
5 | - [X] update search page to do front-end search
6 | - [X] improve UI feedback during schema refresh
7 | - [ ] build new table detail: https://github.com/graphile-contrib/pgdbi/issues/8
8 | - [ ] add ignore role feature
9 | - [ ] rethink tools menu, move away from top level buttons
10 | - [ ] refactor store structure for modular rule management
11 | - [ ] improve the build/publish process
12 |
13 | ### phase the next
14 |
15 | - [ ] add enums/types browser
16 | - [ ] implement index page
17 | - [ ] settings page
18 | - [ ] function component needs to be spiffed up
19 | - [ ] finish policy evaluation components
20 | - [ ] create by-policy view: basically a pivot on policy assignment
21 | - [ ] make a better color scheme. maybe something close to: https://www.graphile.org
22 |
--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
1 | # @graphile-contrib/pgdbi
2 |
3 | ## Installation
4 |
5 | ```
6 | yarn add @graphile-contrib/pgdbi
7 | ```
8 |
9 | ## Usage
10 |
11 | Currently recommended for development only; to disable in production, do not
12 | load this plugin.
13 |
14 | This is a [PostGraphile Server Plugin](https://www.graphile.org/postgraphile/plugins/) so you can follow the standard server plugin instructions, namely:
15 |
16 | For the CLI, use `--plugins` to load the plugin (and remember this flag must come at the very start!)
17 |
18 | ```
19 | postgraphile --plugins @graphile-contrib/pgdbis -c my_db
20 | ```
21 |
22 | For PostGraphile as a library/middleware, you must use the plugin hook functionality:
23 |
24 | ```js
25 | const pgdbi = require('@graphile-contrib/pgdbi');
26 | const { postgraphile, makePluginHook } = require('postgraphile');
27 |
28 | const pluginHook = makePluginHook([
29 | pgdbi,
30 | /* other server plugins can be added here */
31 | ]);
32 |
33 | app.use(
34 | postgraphile(connectionString, schemas, {
35 | pluginHook,
36 | }),
37 | );
38 | ```
39 |
40 | You can access pgdbi at the `/pgdbi` sub path, e.g. [http://localhost:5000/pgdbi](http://localhost:5000/pgdbi).
41 |
--------------------------------------------------------------------------------
/src/dbDev/constraints.sql:
--------------------------------------------------------------------------------
1 | select
2 | c.*
3 | ,'unique_constraint' __typename
4 | -- ,s.schema_name || '.' || t.table_name || '.' || c.constraint_name id
5 | ,(
6 | select (array_to_json(array_agg(row_to_json(kcu))))::jsonb
7 | from (
8 | select
9 | kcu.*
10 | from information_schema.key_column_usage kcu
11 | where kcu.constraint_schema = c.constraint_schema
12 | and kcu.constraint_name = c.constraint_name
13 | ) kcu
14 | ) key_column_usage
15 | ,pg_get_constraintdef(pgc.oid) constraint_definition
16 | from information_schema.table_constraints c
17 | join pg_catalog.pg_constraint pgc on pgc.conname = c.constraint_name
18 | -- join pg_catalog.pg_namespace pgn on pgn.nspname = 'pgdbi_dev'
19 | -- join pg_catalog.pg_class tbl on tbl.relnamespace = pgn.oid and tbl.relname = 'contrived_sink_reference'
20 | where c.table_schema = 'pgdbi_dev'
21 | and c.table_name = 'contrived_sink_reference'
22 | and c.constraint_type = 'UNIQUE'
23 | ;
24 |
25 | select oid, relname from pg_class where relname = 'contrived_sink_reference';
26 |
27 | select pg_get_tabledef(574884);
--------------------------------------------------------------------------------
/src/dbDev/execute.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | echo -d pg_phile_starter -h 0.0.0.0
3 | echo script: $1
4 | psql -U postgres -f $1 -d pg_phile_starter -h 0.0.0.0
5 |
--------------------------------------------------------------------------------
/src/dbDev/functions.sql:
--------------------------------------------------------------------------------
1 | select
2 | 'function' __typename
3 | ,'public' || '.' || p.proname || '--' || replace(replace(coalesce(pg_catalog.pg_get_function_identity_arguments(p.oid), 'N/A'),', ','_'),' ',':') id
4 | ,p.proname function_name
5 | ,n.nspname function_schema
6 | -- ,coalesce(pg_catalog.pg_get_function_result(p.oid), 'N/A') result_data_type
7 | -- ,coalesce(pg_catalog.pg_get_function_arguments(p.oid), 'N/A') argument_data_types
8 | -- ,coalesce(pg_catalog.pg_get_functiondef(p.oid)::text, 'N/A') definition
9 | from pg_catalog.pg_proc p
10 | left join pg_catalog.pg_namespace n ON n.oid = p.pronamespace
11 | where n.nspname = 'public'
12 | and p.proisagg = false
13 | order by p.proname
14 |
--------------------------------------------------------------------------------
/src/dbDev/inheritance.sql:
--------------------------------------------------------------------------------
1 |
2 | ALTER TABLE tunz.band_member ADD CONSTRAINT fk_band_member_contact FOREIGN KEY ( musician_id ) REFERENCES org.contact( id );
3 |
--------------------------------------------------------------------------------
/src/devServer/index.js:
--------------------------------------------------------------------------------
1 | const express = require('express');
2 |
3 | const {
4 | PORT = 3000,
5 | } = process.env;
6 |
7 | const port = PORT;
8 | const app = express();
9 | const phile = require('./phile')
10 |
11 | app.use(phile);
12 |
13 | const server = app.listen(port);
14 |
15 | /*
16 | * When being used in nodemon, SIGUSR2 is issued to restart the process. We
17 | * listen for this and shut down cleanly.
18 | */
19 | process.once('SIGUSR2', function() {
20 | server.close();
21 | const t = setTimeout(function() {
22 | process.kill(process.pid, 'SIGUSR2');
23 | }, 200);
24 | // Don't prevent clean shutdown:
25 | t.unref();
26 | });
27 |
28 | console.log(`listening on http://localhost:${port}/graphiql`);
--------------------------------------------------------------------------------
/src/devServer/phile.js:
--------------------------------------------------------------------------------
1 | try {
2 | require('./.env');
3 | } catch (e) {
4 | // No envvars 🤷
5 | }
6 | const { postgraphile, makePluginHook } = require('postgraphile');
7 |
8 | const plugins = [
9 | // require('postgraphile-plugin-connection-filter'),
10 | ];
11 |
12 | const isProd = process.env.NODE_ENV === 'production';
13 |
14 | const {
15 | POSTGRES_CONNECTION,
16 | POSTGRAPHILE_SCHEMAS = 'public',
17 | DYNAMIC_JSON = 'true',
18 | DISABLE_DEFAULT_MUTATIONS = null,
19 | WATCH_PG = isProd ? null : 'true',
20 | ENABLE_PGDBI = isProd ? null : 'true',
21 | } = process.env;
22 |
23 | if (!POSTGRES_CONNECTION) {
24 | throw new Error(
25 | "No 'POSTGRES_CONNECTION' envvar found, we don't know which database to connect to.",
26 | );
27 | }
28 | console.log('POSTGRES_CONNECTION', POSTGRES_CONNECTION)
29 | const identity = _ => _;
30 |
31 | const connection = POSTGRES_CONNECTION;
32 | const schemas = POSTGRAPHILE_SCHEMAS.split(',');
33 | const dynamicJson = DYNAMIC_JSON === 'true';
34 | const disableDefaultMutations = DISABLE_DEFAULT_MUTATIONS === 'true';
35 | const watchPg = WATCH_PG === 'true';
36 | const enablePgdbi = ENABLE_PGDBI === 'true';
37 |
38 | const pluginHook = makePluginHook(
39 | [enablePgdbi ? require('../pgdbi') : null].filter(identity),
40 | );
41 |
42 | const phile = postgraphile(connection, schemas, {
43 | pluginHook,
44 | dynamicJson: dynamicJson,
45 | showErrorStack: true,
46 | extendedErrors: [
47 | 'severity',
48 | 'code',
49 | 'detail',
50 | 'hint',
51 | 'positon',
52 | 'internalPosition',
53 | 'internalQuery',
54 | 'where',
55 | 'schema',
56 | 'table',
57 | 'column',
58 | 'dataType',
59 | 'constraint',
60 | 'file',
61 | 'line',
62 | 'routine',
63 | ],
64 | disableDefaultMutations: disableDefaultMutations,
65 | appendPlugins: plugins,
66 | watchPg: watchPg,
67 | graphiql: true,
68 | pgdbi: {
69 | enableSqitch: false,
70 | enableGraphileWorker: false
71 | }
72 | })
73 |
74 | module.exports = phile
--------------------------------------------------------------------------------
/src/devServer/sqitch.conf:
--------------------------------------------------------------------------------
1 | [core]
2 | engine = pg
3 | host = 0.0.0.0
4 | # plan_file = sqitch.plan
5 | # top_dir = .
6 | # [engine "pg"]
7 | # target = db:pg:
8 | # registry = sqitch
9 | # client = psql
10 | [deploy]
11 | verify = false
12 | [target "phile"]
13 | uri = db:pg:phile_test
14 | [engine "pg"]
15 | target = phile_test
16 | [target "phile_test"]
17 | uri = db:pg:phile_test
18 |
--------------------------------------------------------------------------------
/src/devServer/tasks/testTask.js:
--------------------------------------------------------------------------------
1 | // tasks/testTask.js
2 | module.exports = async (payload, { debug }) => {
3 | // async is optional, but best practice
4 | debug(`Received ${JSON.stringify(payload)}`);
5 | };
6 |
--------------------------------------------------------------------------------
/src/devServer/worker.js:
--------------------------------------------------------------------------------
1 | const { Pool } = require("pg");
2 | const { run } = require("graphile-worker");
3 |
4 | const pgPool = new Pool({
5 | connectionString: "postgres://postgres:1234@0.0.0.0/pg_phile_starter",
6 | });
7 |
8 | async function main() {
9 | const runner = await run({
10 | pgPool,
11 | // or: connectionString: process.env.DATABASE_URL,
12 |
13 | concurrency: 1,
14 | pollInterval: 2000,
15 |
16 | taskList: {
17 | testTask: async (payload, { debug }) => {
18 | console.log(`Received ${JSON.stringify(payload)}`);
19 | throw new Error('bad things, man')
20 | },
21 | },
22 | // or: taskDirectory: `${__dirname}/tasks`,
23 | });
24 | // to clean up: runner.stop()
25 | }
26 |
27 | main().catch(err => {
28 | console.error(err);
29 | process.exit(1);
30 | });
31 |
--------------------------------------------------------------------------------
/src/pgdbi/dist/css/app.89ce3cd1.css:
--------------------------------------------------------------------------------
1 | @-webkit-keyframes shadow-pulse{0%{-webkit-box-shadow:0 0 0 0 rgba(182,179,26,.253);box-shadow:0 0 0 0 rgba(182,179,26,.253)}to{-webkit-box-shadow:0 0 0 15px rgba(182,179,26,.253);box-shadow:0 0 0 15px rgba(182,179,26,.253)}}@keyframes shadow-pulse{0%{-webkit-box-shadow:0 0 0 0 rgba(182,179,26,.253);box-shadow:0 0 0 0 rgba(182,179,26,.253)}to{-webkit-box-shadow:0 0 0 15px rgba(182,179,26,.253);box-shadow:0 0 0 15px rgba(182,179,26,.253)}}.refreshBtnInitializing{-webkit-animation:shadow-pulse 2s infinite;animation:shadow-pulse 2s infinite}.blah{color:red}.norm-text{text-transform:none!important}
--------------------------------------------------------------------------------
/src/pgdbi/dist/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/graphile-contrib/pgdbi/47d3b0454fde69836e99a388f88b00a8463f4285/src/pgdbi/dist/favicon.ico
--------------------------------------------------------------------------------
/src/pgdbi/dist/index.html:
--------------------------------------------------------------------------------
1 | pg-db-inspector
--------------------------------------------------------------------------------
/src/pgdbi/dist/js/about.5bee4903.js:
--------------------------------------------------------------------------------
1 | (window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["about"],{f820:function(t,e,n){"use strict";n.r(e);var a=function(){var t=this,e=t.$createElement;t._self._c;return t._m(0)},s=[function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{staticClass:"about"},[n("h1",[t._v("This is an about page")])])}],u=n("2877"),c={},i=Object(u["a"])(c,a,s,!1,null,null,null);e["default"]=i.exports}}]);
2 | //# sourceMappingURL=about.5bee4903.js.map
--------------------------------------------------------------------------------
/src/pgdbi/dist/js/about.5bee4903.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":["webpack:///./src/views/About.vue?05f7","webpack:///./src/views/About.vue"],"names":["render","_vm","this","_h","$createElement","_self","_c","_m","staticRenderFns","staticClass","_v","script","component"],"mappings":"8GAAA,IAAIA,EAAS,WAAa,IAAIC,EAAIC,KAASC,EAAGF,EAAIG,eAAsBH,EAAII,MAAMC,GAAO,OAAOL,EAAIM,GAAG,IACnGC,EAAkB,CAAC,WAAa,IAAIP,EAAIC,KAASC,EAAGF,EAAIG,eAAmBE,EAAGL,EAAII,MAAMC,IAAIH,EAAG,OAAOG,EAAG,MAAM,CAACG,YAAY,SAAS,CAACH,EAAG,KAAK,CAACL,EAAIS,GAAG,+B,YCAtJC,EAAS,GAKTC,EAAY,eACdD,EACAX,EACAQ,GACA,EACA,KACA,KACA,MAIa,aAAAI,E","file":"js/about.5bee4903.js","sourcesContent":["var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _vm._m(0)}\nvar staticRenderFns = [function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{staticClass:\"about\"},[_c('h1',[_vm._v(\"This is an about page\")])])}]\n\nexport { render, staticRenderFns }","import { render, staticRenderFns } from \"./About.vue?vue&type=template&id=1ae8a7be&\"\nvar script = {}\n\n\n/* normalize component */\nimport normalizer from \"!../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n null,\n null\n \n)\n\nexport default component.exports"],"sourceRoot":""}
--------------------------------------------------------------------------------
/src/pgdbi/dist/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/graphile-contrib/pgdbi/47d3b0454fde69836e99a388f88b00a8463f4285/src/pgdbi/dist/logo.png
--------------------------------------------------------------------------------
/src/pgdbi/graphile-extensions/dbSchema/introspection.js:
--------------------------------------------------------------------------------
1 | const util = require('util')
2 | const pgdbiApp = require('../../index')
3 |
4 | module.exports = build => {
5 | return async (_schema, args, context, resolveInfo) => {
6 | return pgdbiApp.schemaTree()
7 | };
8 | };
9 |
--------------------------------------------------------------------------------
/src/pgdbi/graphile-extensions/dbSchema/pgdbiOptions.js:
--------------------------------------------------------------------------------
1 | const util = require('util')
2 | const pgdbiApp = require('../../index')
3 |
4 | module.exports = build => {
5 | return async (_schema, args, context, resolveInfo) => {
6 | return pgdbiApp.pdgbiOptions()
7 | };
8 | };
9 |
--------------------------------------------------------------------------------
/src/pgdbi/graphile-extensions/dbSchema/resolvers/checkConstraint/tableConstraint.js:
--------------------------------------------------------------------------------
1 | const clog = require('fbkt-clog');
2 |
3 | module.exports = build => {
4 | return async (_checkConstraint, args, context, resolveInfo) => {
5 | const { pgSql: sql } = build;
6 | try {
7 | const constraintSchema = _checkConstraint.constraintSchema;
8 | const constraintName = _checkConstraint.constraintName;
9 |
10 | const rows = await resolveInfo.graphile.selectGraphQLResultFromTable(
11 | sql.fragment`information_schema.table_constraints`,
12 | (tableAlias, sqlBuilder) => {
13 | sqlBuilder.where(
14 | sql.fragment`${tableAlias}.constraint_schema = ${sql.value(
15 | constraintSchema,
16 | )}`,
17 | );
18 | sqlBuilder.where(
19 | sql.fragment`${tableAlias}.constraint_name = ${sql.value(
20 | constraintName,
21 | )}`,
22 | );
23 | },
24 | );
25 |
26 | return rows;
27 | } catch (e) {
28 | throw e;
29 | }
30 | };
31 | };
32 |
--------------------------------------------------------------------------------
/src/pgdbi/graphile-extensions/dbSchema/resolvers/column/keyColumnUsage.js:
--------------------------------------------------------------------------------
1 | const clog = require('fbkt-clog');
2 |
3 | module.exports = build => {
4 | return async (_column, args, context, resolveInfo) => {
5 | const { pgSql: sql } = build;
6 | try {
7 | const tableSchema = _column.tableSchema;
8 | const tableName = _column.tableName;
9 | const columnName = _column.columnName;
10 |
11 | const rows = await resolveInfo.graphile.selectGraphQLResultFromTable(
12 | sql.fragment`information_schema.key_column_usage`,
13 | (tableAlias, sqlBuilder) => {
14 | sqlBuilder.where(
15 | sql.fragment`${tableAlias}.table_schema = ${sql.value(
16 | tableSchema,
17 | )}`,
18 | );
19 | sqlBuilder.where(
20 | sql.fragment`${tableAlias}.table_name = ${sql.value(tableName)}`,
21 | );
22 | sqlBuilder.where(
23 | sql.fragment`${tableAlias}.column_name = ${sql.value(columnName)}`,
24 | );
25 | },
26 | );
27 |
28 | return rows;
29 | } catch (e) {
30 | throw e;
31 | }
32 | };
33 | };
34 |
--------------------------------------------------------------------------------
/src/pgdbi/graphile-extensions/dbSchema/resolvers/enabledRole/applicableRoles.js:
--------------------------------------------------------------------------------
1 | const clog = require('fbkt-clog');
2 |
3 | module.exports = build => {
4 | return async (_enabledRole, args, context, resolveInfo) => {
5 | const { pgSql: sql } = build;
6 | try {
7 | const roleName = _enabledRole.roleName;
8 |
9 | const rows = await resolveInfo.graphile.selectGraphQLResultFromTable(
10 | sql.fragment`information_schema.applicable_roles`,
11 | (tableAlias, sqlBuilder) => {
12 | sqlBuilder.where(
13 | sql.fragment`${tableAlias}.grantee = ${sql.value(roleName)}`,
14 | );
15 | },
16 | );
17 |
18 | return rows;
19 | } catch (e) {
20 | throw e;
21 | }
22 | };
23 | };
24 |
--------------------------------------------------------------------------------
/src/pgdbi/graphile-extensions/dbSchema/resolvers/function/functionById.js:
--------------------------------------------------------------------------------
1 | module.exports = build => {
2 | return async (_schema, args, context, resolveInfo) => {
3 | const { pgClient } = context;
4 | try {
5 | const schemaName = args.id.split(':')[1].split('.')[0];
6 | const functionName = args.id.split(':')[1].split('.')[1];
7 |
8 | const sql = `
9 | select
10 | jsonb_build_object(
11 | 'functionById', (
12 | jsonb_build_object(
13 | 'id', 'function:' || n.nspname || '.' || p.proname
14 | ,'functionName', p.proname
15 | ,'functionSchema', n.nspname
16 | ,'resultDataType', coalesce(pg_catalog.pg_get_function_result(p.oid), 'N/A')
17 | ,'argumentDataTypes', coalesce(pg_catalog.pg_get_function_arguments(p.oid), 'N/A')
18 | ,'definition', coalesce(pg_catalog.pg_get_functiondef(p.oid)::text, 'N/A')
19 | )
20 | )
21 | )
22 | from pg_catalog.pg_proc p
23 | left join pg_catalog.pg_namespace n ON n.oid = p.pronamespace
24 | where n.nspname = '${schemaName}'
25 | and p.proname = '${functionName}'
26 | ;
27 | `;
28 |
29 | const result = await pgClient.query(sql, []);
30 |
31 | return result.rows[0].jsonb_build_object.functionById;
32 | } catch (e) {
33 | throw e;
34 | }
35 | };
36 | };
37 |
--------------------------------------------------------------------------------
/src/pgdbi/graphile-extensions/dbSchema/resolvers/function/searchFunctions.js:
--------------------------------------------------------------------------------
1 | module.exports = build => {
2 | return async (_schema, args, context, resolveInfo) => {
3 | const { pgClient } = context;
4 | try {
5 | const searchTerm = args.searchTerm;
6 |
7 | const sql = `
8 | with procs as (
9 | select
10 | p.oid
11 | ,p.proname
12 | ,n.nspname
13 | from pg_proc p
14 | join pg_catalog.pg_namespace n ON n.oid = p.pronamespace
15 | where lower(p.prosrc) like '%${searchTerm}%'
16 | or lower(p.proname) like '%%${searchTerm}%'
17 | )
18 | select
19 | jsonb_build_object(
20 | 'searchFunctions', (
21 | coalesce(
22 | array_agg(
23 | jsonb_build_object(
24 | 'id', 'function:' || p.nspname || '.' || p.proname
25 | ,'functionName', p.proname
26 | ,'functionSchema', p.nspname
27 | ,'resultDataType', coalesce(pg_catalog.pg_get_function_result(p.oid), 'N/A')
28 | ,'argumentDataTypes', coalesce(pg_catalog.pg_get_function_arguments(p.oid), 'N/A')
29 | ,'definition', coalesce(pg_catalog.pg_get_functiondef(p.oid)::text, 'N/A')
30 | )
31 | )
32 | )
33 | )
34 | )
35 | from procs p
36 | ;
37 | `;
38 |
39 | const result = await pgClient.query(sql, []);
40 |
41 | return result.rows[0].jsonb_build_object.searchFunctions;
42 | } catch (e) {
43 | throw e;
44 | }
45 | };
46 | };
47 |
--------------------------------------------------------------------------------
/src/pgdbi/graphile-extensions/dbSchema/resolvers/keyColumnUsage/referentialConstraints.js:
--------------------------------------------------------------------------------
1 | const clog = require('fbkt-clog');
2 |
3 | module.exports = build => {
4 | return async (_keyColumnUsage, args, context, resolveInfo) => {
5 | const { pgSql: sql } = build;
6 | try {
7 | const constraintSchema = _keyColumnUsage.tableSchema;
8 | const constraintName = _keyColumnUsage.constraintName;
9 |
10 | const rows = await resolveInfo.graphile.selectGraphQLResultFromTable(
11 | sql.fragment`information_schema.referential_constraints`,
12 | (tableAlias, sqlBuilder) => {
13 | sqlBuilder.where(
14 | sql.fragment`${tableAlias}.constraint_schema = ${sql.value(
15 | constraintSchema,
16 | )}`,
17 | );
18 | sqlBuilder.where(
19 | sql.fragment`${tableAlias}.constraint_name = ${sql.value(
20 | constraintName,
21 | )}`,
22 | );
23 | },
24 | );
25 |
26 | return rows;
27 | } catch (e) {
28 | throw e;
29 | }
30 | };
31 | };
32 |
--------------------------------------------------------------------------------
/src/pgdbi/graphile-extensions/dbSchema/resolvers/referentialConstraint/referencedColumnUsage.js:
--------------------------------------------------------------------------------
1 | const clog = require('fbkt-clog');
2 |
3 | module.exports = build => {
4 | return async (_referentialConstraint, args, context, resolveInfo) => {
5 | const { pgSql: sql } = build;
6 | try {
7 | const constraintSchema = _referentialConstraint.uniqueConstraintSchema;
8 | const constraintName = _referentialConstraint.uniqueConstraintName;
9 |
10 | const rows = await resolveInfo.graphile.selectGraphQLResultFromTable(
11 | sql.fragment`information_schema.key_column_usage`,
12 | (tableAlias, sqlBuilder) => {
13 | sqlBuilder.where(
14 | sql.fragment`${tableAlias}.constraint_schema = ${sql.value(
15 | constraintSchema,
16 | )}`,
17 | );
18 | sqlBuilder.where(
19 | sql.fragment`${tableAlias}.constraint_name = ${sql.value(
20 | constraintName,
21 | )}`,
22 | );
23 | },
24 | );
25 |
26 | return rows;
27 | } catch (e) {
28 | throw e;
29 | }
30 | };
31 | };
32 |
--------------------------------------------------------------------------------
/src/pgdbi/graphile-extensions/dbSchema/resolvers/referentialConstraint/referencingColumnUsage.js:
--------------------------------------------------------------------------------
1 | const clog = require('fbkt-clog');
2 |
3 | module.exports = build => {
4 | return async (_referentialConstraint, args, context, resolveInfo) => {
5 | const { pgSql: sql } = build;
6 | try {
7 | const constraintSchema = _referentialConstraint.constraintSchema;
8 | const constraintName = _referentialConstraint.constraintName;
9 |
10 | const rows = await resolveInfo.graphile.selectGraphQLResultFromTable(
11 | sql.fragment`information_schema.key_column_usage`,
12 | (tableAlias, sqlBuilder) => {
13 | sqlBuilder.where(
14 | sql.fragment`${tableAlias}.constraint_schema = ${sql.value(
15 | constraintSchema,
16 | )}`,
17 | );
18 | sqlBuilder.where(
19 | sql.fragment`${tableAlias}.constraint_name = ${sql.value(
20 | constraintName,
21 | )}`,
22 | );
23 | },
24 | );
25 |
26 | return rows;
27 | } catch (e) {
28 | throw e;
29 | }
30 | };
31 | };
32 |
--------------------------------------------------------------------------------
/src/pgdbi/graphile-extensions/dbSchema/resolvers/schema/id.js:
--------------------------------------------------------------------------------
1 | const clog = require('fbkt-clog');
2 |
3 | module.exports = build => {
4 | return async (_schema, args, context, resolveInfo) => {
5 | const { pgSql: sql } = build;
6 | try {
7 | const schemaName = _schema.schemaName;
8 |
9 | return `schema:${schemaName}`;
10 | } catch (e) {
11 | throw e;
12 | }
13 | };
14 | };
15 |
--------------------------------------------------------------------------------
/src/pgdbi/graphile-extensions/dbSchema/resolvers/schema/schemaEnums.js:
--------------------------------------------------------------------------------
1 | const clog = require('fbkt-clog');
2 |
3 | module.exports = build => {
4 | return async (_schema, args, context, resolveInfo) => {
5 | const { pgClient } = context;
6 | try {
7 | const schemaName = _schema.schemaName;
8 |
9 | const sql = `
10 | select jsonb_build_object(
11 | 'id', 'enum:' || n.nspname || '.' || t.typname
12 | ,'enumName', t.typname
13 | ,'enumSchema', n.nspname
14 | ,'enumValues', (
15 | with vals as(
16 | select e.enumlabel
17 | from pg_enum e
18 | where e.enumtypid = t.oid
19 | order by e.enumlabel
20 | )
21 | select array_agg(enumlabel)
22 | from vals
23 | )
24 | )
25 | from pg_type t
26 | join pg_catalog.pg_namespace n ON n.oid = t.typnamespace
27 | where t.oid in (select enumtypid from pg_enum)
28 | and n.nspname = '${schemaName}'
29 | group by
30 | n.nspname
31 | ,t.typname
32 | ,t.oid
33 | order by
34 | t.typname
35 | ;
36 | `;
37 |
38 | const result = await pgClient.query(sql, []);
39 |
40 | return result.rows.map(r => {
41 | return r.jsonb_build_object;
42 | });
43 | } catch (e) {
44 | throw e;
45 | }
46 | };
47 | };
48 |
--------------------------------------------------------------------------------
/src/pgdbi/graphile-extensions/dbSchema/resolvers/schema/schemaFunctions.js:
--------------------------------------------------------------------------------
1 | module.exports = build => {
2 | return async (_schema, args, context, resolveInfo) => {
3 | const { pgClient } = context;
4 | try {
5 | const schemaName = _schema.schemaName;
6 |
7 | const sql = `
8 | select
9 | jsonb_build_object(
10 | 'schemaFunctions', (
11 | coalesce(
12 | array_agg(
13 | jsonb_build_object(
14 | 'id', 'function:' || n.nspname || '.' || p.proname
15 | ,'functionName', p.proname
16 | ,'functionSchema', n.nspname
17 | )
18 | )
19 | , '{}')
20 | )
21 | )
22 | from pg_catalog.pg_proc p
23 | left join pg_catalog.pg_namespace n ON n.oid = p.pronamespace
24 | where n.nspname = '${schemaName}'
25 | -- group by p.proname
26 | -- order by p.proname
27 | ;
28 | `;
29 |
30 | const result = await pgClient.query(sql, []);
31 | return result.rows[0].jsonb_build_object.schemaFunctions;
32 | } catch (e) {
33 | console.log('err', e);
34 | throw e;
35 | }
36 | };
37 | };
38 |
--------------------------------------------------------------------------------
/src/pgdbi/graphile-extensions/dbSchema/resolvers/schema/schemaTables.js:
--------------------------------------------------------------------------------
1 | module.exports = build => {
2 | return async (_schema, args, context, resolveInfo) => {
3 | const { pgSql: sql } = build;
4 | try {
5 | const schemaName = _schema.schemaName;
6 |
7 | const rows = await resolveInfo.graphile.selectGraphQLResultFromTable(
8 | sql.fragment`information_schema.tables`,
9 | (tableAlias, sqlBuilder) => {
10 | sqlBuilder.where(
11 | sql.fragment`${tableAlias}.table_schema = ${sql.value(schemaName)}`,
12 | );
13 | sqlBuilder.where(
14 | sql.fragment`${tableAlias}.table_type = 'BASE TABLE'`,
15 | );
16 | sqlBuilder.orderBy(() => sql.fragment`table_name`, true);
17 | },
18 | );
19 |
20 | return rows;
21 | } catch (e) {
22 | throw e;
23 | }
24 | };
25 | };
26 |
--------------------------------------------------------------------------------
/src/pgdbi/graphile-extensions/dbSchema/resolvers/schema/schemaTreeBySchemaName.js:
--------------------------------------------------------------------------------
1 | module.exports = build => {
2 | return async (_schema, args, context, resolveInfo) => {
3 | const { pgSql: sql } = build;
4 | try {
5 | const schemaName = _schema.schemaName;
6 |
7 | const rows = await resolveInfo.graphile.selectGraphQLResultFromTable(
8 | sql.fragment`information_schema.tables`,
9 | (tableAlias, sqlBuilder) => {
10 | sqlBuilder.where(
11 | sql.fragment`${tableAlias}.table_schema = ${sql.value(schemaName)}`,
12 | );
13 | sqlBuilder.where(
14 | sql.fragment`${tableAlias}.table_type = 'BASE TABLE'`,
15 | );
16 | sqlBuilder.orderBy(() => sql.fragment`table_name`, true);
17 | },
18 | );
19 |
20 | return rows;
21 | } catch (e) {
22 | throw e;
23 | }
24 | };
25 | };
26 |
--------------------------------------------------------------------------------
/src/pgdbi/graphile-extensions/dbSchema/resolvers/table/checkConstraints.js:
--------------------------------------------------------------------------------
1 | const clog = require('fbkt-clog');
2 |
3 | module.exports = build => {
4 | return async (_table, args, context, resolveInfo) => {
5 | const { pgSql: sql } = build;
6 | try {
7 | const constraintSchema = _table.tableSchema;
8 | const tableName = _table.tableName;
9 |
10 | const rows = await resolveInfo.graphile.selectGraphQLResultFromTable(
11 | sql.fragment`information_schema.check_constraints`,
12 | (tableAlias, sqlBuilder) => {
13 | sqlBuilder.where(
14 | sql.fragment`${tableAlias}.constraint_schema = ${sql.value(
15 | constraintSchema,
16 | )}`,
17 | );
18 | sqlBuilder.where(
19 | sql.fragment`${tableAlias}.constraint_name in (
20 | SELECT constraint_name
21 | from information_schema.table_constraints
22 | where table_name = ${sql.value(tableName)}
23 | )`,
24 | );
25 | },
26 | );
27 |
28 | return rows;
29 | } catch (e) {
30 | throw e;
31 | }
32 | };
33 | };
34 |
--------------------------------------------------------------------------------
/src/pgdbi/graphile-extensions/dbSchema/resolvers/table/id.js:
--------------------------------------------------------------------------------
1 | const clog = require('fbkt-clog');
2 |
3 | module.exports = build => {
4 | return async (_table, args, context, resolveInfo) => {
5 | const { pgSql: sql } = build;
6 | try {
7 | const tableSchema = _table.tableSchema;
8 | const tableName = _table.tableName;
9 |
10 | return `table:${tableSchema}.${tableName}`;
11 | } catch (e) {
12 | throw e;
13 | }
14 | };
15 | };
16 |
--------------------------------------------------------------------------------
/src/pgdbi/graphile-extensions/dbSchema/resolvers/table/indices.js:
--------------------------------------------------------------------------------
1 | module.exports = build => {
2 | return async (_table, args, context, resolveInfo) => {
3 | const { pgClient } = context;
4 | try {
5 | const tableSchema = _table.tableSchema;
6 | const tableName = _table.tableName;
7 |
8 | const sql = `
9 | select
10 | ns.nspname || '.' || t.relname id
11 | ,t.relname "tableName"
12 | ,ns.nspname "tableSchema"
13 | ,a.attname "columnName"
14 | ,i.relname "indexName"
15 | from
16 | pg_index ix
17 | join pg_class t on t.oid = ix.indrelid
18 | join pg_class i on i.oid = ix.indexrelid
19 | join pg_namespace ns on t.relnamespace = ns.oid
20 | join pg_attribute a on a.attrelid = t.oid and a.attnum = ANY(ix.indkey)
21 | where
22 | ns.nspname = '${tableSchema}'
23 | and
24 | t.relname = '${tableName}'
25 | group by
26 | ns.nspname,
27 | t.relname,
28 | a.attname,
29 | i.relname
30 | order by
31 | ns.nspname,
32 | t.relname,
33 | a.attname,
34 | i.relname
35 | ;
36 | `;
37 |
38 | const result = await pgClient.query(sql, []);
39 | return result.rows;
40 | } catch (e) {
41 | throw e;
42 | }
43 | };
44 | };
45 |
46 | // select
47 | // jsonb_build_object(
48 | // 'tableIndices', (
49 | // coalesce(
50 | // array_agg(
51 | // jsonb_build_object(
52 | // 'id', 'index:' || ns.nspname || '.' || t.relname
53 | // ,'tableName', t.relname
54 | // ,'tableSchema', ns.nspname
55 | // ,'columnName', a.attname
56 | // ,'indexName', i.relname
57 | // )
58 | // )
59 | // , '{}')
60 | // )
61 | // )
62 |
--------------------------------------------------------------------------------
/src/pgdbi/graphile-extensions/dbSchema/resolvers/table/policies.js:
--------------------------------------------------------------------------------
1 | module.exports = build => {
2 | return async (_table, args, context, resolveInfo) => {
3 | const { pgClient } = context;
4 | try {
5 | const tableSchema = _table.tableSchema;
6 | const tableName = _table.tableName;
7 |
8 | const sql = `
9 | select
10 | jsonb_build_object(
11 | 'tablePolicies', (
12 | coalesce(
13 | array_agg(
14 | jsonb_build_object(
15 | 'schemaName', p.schemaname
16 | ,'tableName', p.tablename
17 | ,'policyName', p.policyname
18 | ,'roles', p.roles
19 | ,'cmd', p.cmd
20 | ,'qual', p.qual
21 | ,'withCheck', p.with_check
22 | )
23 | )
24 | , '{}')
25 | )
26 | )
27 | FROM pg_policies p
28 | where
29 | p.schemaname = '${tableSchema}'
30 | and
31 | p.tablename = '${tableName}'
32 | ;
33 | `;
34 |
35 | const result = await pgClient.query(sql, []);
36 | return result.rows[0].jsonb_build_object.tablePolicies;
37 | } catch (e) {
38 | throw e;
39 | }
40 | };
41 | };
42 |
--------------------------------------------------------------------------------
/src/pgdbi/graphile-extensions/dbSchema/resolvers/table/primaryKeyConstraints.js:
--------------------------------------------------------------------------------
1 | const clog = require('fbkt-clog');
2 |
3 | module.exports = build => {
4 | return async (_table, args, context, resolveInfo) => {
5 | const { pgSql: sql } = build;
6 | try {
7 | const tableSchema = _table.tableSchema;
8 | const tableName = _table.tableName;
9 |
10 | const rows = await resolveInfo.graphile.selectGraphQLResultFromTable(
11 | sql.fragment`information_schema.table_constraints`,
12 | (tableAlias, sqlBuilder) => {
13 | sqlBuilder.where(
14 | sql.fragment`${tableAlias}.table_name = ${sql.value(tableName)}`,
15 | );
16 | sqlBuilder.where(
17 | sql.fragment`${tableAlias}.table_schema = ${sql.value(
18 | tableSchema,
19 | )}`,
20 | );
21 |
22 | sqlBuilder.where(
23 | sql.fragment`${tableAlias}.constraint_type = ${sql.value(
24 | 'PRIMARY KEY',
25 | )}`,
26 | );
27 | },
28 | );
29 |
30 | return rows;
31 | } catch (e) {
32 | throw e;
33 | }
34 | };
35 | };
36 |
--------------------------------------------------------------------------------
/src/pgdbi/graphile-extensions/dbSchema/resolvers/table/psqlDescription.js:
--------------------------------------------------------------------------------
1 | module.exports = build => {
2 | return async (_table, args, context, resolveInfo) => {
3 | const { pgClient } = context;
4 | try {
5 | console.log('_table', _table)
6 | const tableSchema = _table.tableSchema;
7 | const tableName = _table.tableName;
8 |
9 | const sql = `\d+ ${tableSchema}.${tableName};`;
10 | console.log('sql', sql)
11 |
12 | const result = await pgClient.query(sql, []);
13 | return result.rows[0].jsonb_build_object.tablePolicies;
14 | } catch (e) {
15 | throw e;
16 | }
17 | };
18 | };
19 |
--------------------------------------------------------------------------------
/src/pgdbi/graphile-extensions/dbSchema/resolvers/table/referentialConstraints.js:
--------------------------------------------------------------------------------
1 | const clog = require('fbkt-clog');
2 |
3 | module.exports = build => {
4 | return async (_table, args, context, resolveInfo) => {
5 | const { pgSql: sql } = build;
6 | try {
7 | const constraintSchema = _table.tableSchema;
8 | const tableName = _table.tableName;
9 |
10 | const rows = await resolveInfo.graphile.selectGraphQLResultFromTable(
11 | sql.fragment`information_schema.referential_constraints`,
12 | (tableAlias, sqlBuilder) => {
13 | sqlBuilder.where(
14 | sql.fragment`${tableAlias}.constraint_schema = ${sql.value(
15 | constraintSchema,
16 | )}`,
17 | );
18 | sqlBuilder.where(
19 | sql.fragment`${tableAlias}.constraint_name in (
20 | SELECT constraint_name
21 | from information_schema.table_constraints
22 | where table_name = ${sql.value(tableName)}
23 | )`,
24 | );
25 | },
26 | );
27 |
28 | return rows;
29 | } catch (e) {
30 | throw e;
31 | }
32 | };
33 | };
34 |
--------------------------------------------------------------------------------
/src/pgdbi/graphile-extensions/dbSchema/resolvers/table/roleColumnGrants.js:
--------------------------------------------------------------------------------
1 | const clog = require('fbkt-clog');
2 |
3 | module.exports = build => {
4 | return async (_table, args, context, resolveInfo) => {
5 | const { pgSql: sql } = build;
6 | try {
7 | const tableSchema = _table.tableSchema;
8 | const tableName = _table.tableName;
9 |
10 | const rows = await resolveInfo.graphile.selectGraphQLResultFromTable(
11 | sql.fragment`information_schema.role_column_grants`,
12 | (tableAlias, sqlBuilder) => {
13 | sqlBuilder.where(
14 | sql.fragment`${tableAlias}.table_schema = ${sql.value(
15 | tableSchema,
16 | )}`,
17 | );
18 | sqlBuilder.where(
19 | sql.fragment`${tableAlias}.table_name = ${sql.value(tableName)}`,
20 | );
21 | },
22 | );
23 |
24 | return rows;
25 | } catch (e) {
26 | throw e;
27 | }
28 | };
29 | };
30 |
--------------------------------------------------------------------------------
/src/pgdbi/graphile-extensions/dbSchema/resolvers/table/roleTableGrants.js:
--------------------------------------------------------------------------------
1 | const clog = require('fbkt-clog');
2 |
3 | module.exports = build => {
4 | return async (_table, args, context, resolveInfo) => {
5 | const { pgSql: sql } = build;
6 | try {
7 | const tableSchema = _table.tableSchema;
8 | const tableName = _table.tableName;
9 |
10 | const rows = await resolveInfo.graphile.selectGraphQLResultFromTable(
11 | sql.fragment`information_schema.role_table_grants`,
12 | (tableAlias, sqlBuilder) => {
13 | sqlBuilder.where(
14 | sql.fragment`${tableAlias}.table_schema = ${sql.value(
15 | tableSchema,
16 | )}`,
17 | );
18 | sqlBuilder.where(
19 | sql.fragment`${tableAlias}.table_name = ${sql.value(tableName)}`,
20 | );
21 | sqlBuilder.where(sql.fragment`${tableAlias}.grantee != 'postgres'`);
22 | },
23 | );
24 |
25 | return rows;
26 | } catch (e) {
27 | throw e;
28 | }
29 | };
30 | };
31 |
--------------------------------------------------------------------------------
/src/pgdbi/graphile-extensions/dbSchema/resolvers/table/tableById.js:
--------------------------------------------------------------------------------
1 | module.exports = build => {
2 | return async (_schema, args, context, resolveInfo) => {
3 | const { pgSql: sql } = build;
4 | try {
5 | const tableSchema = args.id.split(':')[1].split('.')[0];
6 | const tableName = args.id.split(':')[1].split('.')[1];
7 |
8 | // console.log('args', args)
9 | // console.log('tableSchema', tableSchema)
10 | // console.log('tableName', tableName)
11 |
12 | const rows = await resolveInfo.graphile.selectGraphQLResultFromTable(
13 | sql.fragment`information_schema.tables`,
14 | (tableAlias, sqlBuilder) => {
15 | sqlBuilder.where(
16 | sql.fragment`${tableAlias}.table_schema = ${sql.value(
17 | tableSchema,
18 | )}`,
19 | );
20 | sqlBuilder.where(
21 | sql.fragment`${tableAlias}.table_name = ${sql.value(tableName)}`,
22 | );
23 | },
24 | );
25 |
26 | return rows[0];
27 | } catch (e) {
28 | throw e;
29 | }
30 | };
31 | };
32 |
--------------------------------------------------------------------------------
/src/pgdbi/graphile-extensions/dbSchema/resolvers/table/tableColumns.js:
--------------------------------------------------------------------------------
1 | module.exports = build => {
2 | return async (_table, args, context, resolveInfo) => {
3 | const { pgSql: sql } = build;
4 | try {
5 | const tableSchema = _table.tableSchema;
6 | const tableName = _table.tableName;
7 |
8 | const rows = await resolveInfo.graphile.selectGraphQLResultFromTable(
9 | sql.fragment`information_schema.columns`,
10 | (tableAlias, sqlBuilder) => {
11 | sqlBuilder.where(
12 | sql.fragment`${tableAlias}.table_schema = ${sql.value(
13 | tableSchema,
14 | )}`,
15 | );
16 | sqlBuilder.where(
17 | sql.fragment`${tableAlias}.table_name = ${sql.value(tableName)}`,
18 | );
19 | },
20 | );
21 |
22 | return rows;
23 | } catch (e) {
24 | throw e;
25 | }
26 | };
27 | };
28 |
--------------------------------------------------------------------------------
/src/pgdbi/graphile-extensions/dbSchema/resolvers/table/tableConstraints.js:
--------------------------------------------------------------------------------
1 | module.exports = build => {
2 | return async (_table, args, context, resolveInfo) => {
3 | const { pgSql: sql } = build;
4 | try {
5 | const tableSchema = _table.tableSchema;
6 | const tableName = _table.tableName;
7 |
8 | const rows = await resolveInfo.graphile.selectGraphQLResultFromTable(
9 | sql.fragment`information_schema.constraint_table_usage`,
10 | (tableAlias, sqlBuilder) => {
11 | sqlBuilder.where(
12 | sql.fragment`${tableAlias}.table_schema = ${sql.value(
13 | tableSchema,
14 | )}`,
15 | );
16 | sqlBuilder.where(
17 | sql.fragment`${tableAlias}.table_name = ${sql.value(tableName)}`,
18 | );
19 | },
20 | );
21 |
22 | return rows;
23 | } catch (e) {
24 | throw e;
25 | }
26 | };
27 | };
28 |
--------------------------------------------------------------------------------
/src/pgdbi/graphile-extensions/dbSchema/resolvers/table/triggers.js:
--------------------------------------------------------------------------------
1 | module.exports = build => {
2 | return async (_table, args, context, resolveInfo) => {
3 | const { pgSql: sql } = build;
4 | try {
5 | const tableSchema = _table.tableSchema;
6 | const tableName = _table.tableName;
7 |
8 | const rows = await resolveInfo.graphile.selectGraphQLResultFromTable(
9 | sql.fragment`information_schema.triggers`,
10 | (tableAlias, sqlBuilder) => {
11 | sqlBuilder.where(
12 | sql.fragment`${tableAlias}.event_object_schema = ${sql.value(
13 | tableSchema,
14 | )}`,
15 | );
16 | sqlBuilder.where(
17 | sql.fragment`${tableAlias}.event_object_table = ${sql.value(
18 | tableName,
19 | )}`,
20 | );
21 | },
22 | );
23 |
24 | return rows;
25 | } catch (e) {
26 | throw e;
27 | }
28 | };
29 | };
30 |
--------------------------------------------------------------------------------
/src/pgdbi/graphile-extensions/dbSchema/resolvers/table/uniqueConstraints.js:
--------------------------------------------------------------------------------
1 | const clog = require('fbkt-clog');
2 |
3 | module.exports = build => {
4 | return async (_table, args, context, resolveInfo) => {
5 | const { pgSql: sql } = build;
6 | try {
7 | const tableSchema = _table.tableSchema;
8 | const tableName = _table.tableName;
9 |
10 | const rows = await resolveInfo.graphile.selectGraphQLResultFromTable(
11 | sql.fragment`information_schema.table_constraints`,
12 | (tableAlias, sqlBuilder) => {
13 | sqlBuilder.where(
14 | sql.fragment`${tableAlias}.table_name = ${sql.value(tableName)}`,
15 | );
16 | sqlBuilder.where(
17 | sql.fragment`${tableAlias}.table_schema = ${sql.value(
18 | tableSchema,
19 | )}`,
20 | );
21 |
22 | sqlBuilder.where(
23 | sql.fragment`${tableAlias}.constraint_type = ${sql.value(
24 | 'UNIQUE',
25 | )}`,
26 | );
27 | },
28 | );
29 |
30 | return rows;
31 | } catch (e) {
32 | throw e;
33 | }
34 | };
35 | };
36 |
--------------------------------------------------------------------------------
/src/pgdbi/graphile-extensions/dbSchema/resolvers/tableConstraint/keyColumnUsage.js:
--------------------------------------------------------------------------------
1 | const clog = require('fbkt-clog');
2 |
3 | module.exports = build => {
4 | return async (_tableConstraint, args, context, resolveInfo) => {
5 | const { pgSql: sql } = build;
6 | try {
7 | const constraintSchema = _tableConstraint.constraintSchema;
8 | const constraintName = _tableConstraint.constraintName;
9 |
10 | const rows = await resolveInfo.graphile.selectGraphQLResultFromTable(
11 | sql.fragment`information_schema.key_column_usage`,
12 | (tableAlias, sqlBuilder) => {
13 | sqlBuilder.where(
14 | sql.fragment`${tableAlias}.constraint_schema = ${sql.value(
15 | constraintSchema,
16 | )}`,
17 | );
18 | sqlBuilder.where(
19 | sql.fragment`${tableAlias}.constraint_name = ${sql.value(
20 | constraintName,
21 | )}`,
22 | );
23 | },
24 | );
25 |
26 | return rows;
27 | } catch (e) {
28 | throw e;
29 | }
30 | };
31 | };
32 |
--------------------------------------------------------------------------------
/src/pgdbi/graphile-extensions/dbSchema/resolvers/trigger/id.js:
--------------------------------------------------------------------------------
1 | const clog = require('fbkt-clog');
2 |
3 | module.exports = build => {
4 | return async (_trigger, args, context, resolveInfo) => {
5 | const { pgSql: sql } = build;
6 | try {
7 | const eventManipulation = _trigger.eventManipulation;
8 | const eventObjectSchema = _trigger.eventObjectSchema;
9 | const eventObjectTable = _trigger.eventObjectTable;
10 | const actionTiming = _trigger.actionTiming;
11 |
12 | return `trigger:${actionTiming}.${eventManipulation}.${eventObjectSchema}.${eventObjectTable}`;
13 | } catch (e) {
14 | throw e;
15 | }
16 | };
17 | };
18 |
--------------------------------------------------------------------------------
/src/pgdbi/graphile-extensions/dbSchema/resolvers/trigger/triggerFunction.js:
--------------------------------------------------------------------------------
1 | module.exports = build => {
2 | return async (_trigger, args, context, resolveInfo) => {
3 | const { pgClient } = context;
4 | try {
5 | // assumes action statement of the form: 'EXECUTE PROCEDURE schema_name.function_name()'
6 | const schemaName = _trigger.actionStatement.split(' ')[2].split('.')[0];
7 | const functionName = _trigger.actionStatement
8 | .split(' ')[2]
9 | .split('.')[1]
10 | .split('(')[0];
11 |
12 | const sql = `
13 | select
14 | jsonb_build_object(
15 | 'triggerFunction', (
16 | jsonb_build_object(
17 | 'id', 'function:' || n.nspname || '.' || p.proname
18 | ,'functionName', p.proname
19 | ,'functionSchema', n.nspname
20 | ,'resultDataType', coalesce(pg_catalog.pg_get_function_result(p.oid), 'N/A')
21 | ,'argumentDataTypes', coalesce(pg_catalog.pg_get_function_arguments(p.oid), 'N/A')
22 | ,'definition', coalesce(pg_catalog.pg_get_functiondef(p.oid)::text, 'N/A')
23 | )
24 | )
25 | )
26 | from pg_catalog.pg_proc p
27 | left join pg_catalog.pg_namespace n ON n.oid = p.pronamespace
28 | where n.nspname = '${schemaName}'
29 | and p.proname = '${functionName}'
30 | ;
31 | `;
32 | // console.log('sql',sql)
33 | const result = await pgClient.query(sql, []);
34 | // console.log('result',result)
35 | return result.rows[0].jsonb_build_object.triggerFunction;
36 | } catch (e) {
37 | throw e;
38 | }
39 | };
40 | };
41 |
--------------------------------------------------------------------------------
/src/pgdbi/graphile-extensions/execSql.js:
--------------------------------------------------------------------------------
1 | const { makeExtendSchemaPlugin, gql } = require("graphile-utils");
2 |
3 | const ExecSqlPlugin = makeExtendSchemaPlugin(build => {
4 | const { pgSql: sql } = build;
5 | return {
6 | typeDefs: gql`
7 | input ExecSqlInput {
8 | clientMutationId: String
9 | sql: String!
10 | }
11 |
12 | type ExecSqlPayload {
13 | sql: String!
14 | result: JSON!
15 | }
16 |
17 | extend type Mutation {
18 | ExecSql(input: ExecSqlInput!): ExecSqlPayload
19 | }
20 | `,
21 | resolvers: {
22 | Mutation: {
23 | ExecSql: async (
24 | _mutation,
25 | args,
26 | context,
27 | resolveInfo,
28 | { selectGraphQLResultFromTable }
29 | ) => {
30 | const { pgClient } = context;
31 | // Start a sub-transaction
32 | await pgClient.query("SAVEPOINT graphql_mutation");
33 | try {
34 |
35 | // clog('LET US EXEC SQL', pgClient)
36 | const result = await pgClient.query(args.input.sql, []);
37 |
38 | await pgClient.query("RELEASE SAVEPOINT graphql_mutation");
39 |
40 | return {
41 | sql: args.input.sql,
42 | result: result
43 | };
44 | } catch (e) {
45 | // Oh noes! If at first you don't succeed,
46 | // destroy all evidence you ever tried.
47 | await pgClient.query("ROLLBACK TO SAVEPOINT graphql_mutation");
48 | throw e;
49 | }
50 | },
51 | },
52 | },
53 | };
54 | });
55 |
56 | module.exports = ExecSqlPlugin
57 |
58 |
59 | // the above was built from the below
60 | // https://www.graphile.org/postgraphile/make-extend-schema-plugin/
61 |
--------------------------------------------------------------------------------
/src/pgdbi/graphile-extensions/pgIntrospectionResultsByKind.js:
--------------------------------------------------------------------------------
1 | module.exports = callback => builder => builder.hook('build', (build) =>{callback(build.pgIntrospectionResultsByKind); return build})
2 |
--------------------------------------------------------------------------------
/src/pgdbi/graphile-extensions/pgdbirc.js:
--------------------------------------------------------------------------------
1 | const { makeExtendSchemaPlugin, gql } = require("graphile-utils");
2 | const fs = require('fs')
3 | const defaultPgdbirc = require('./pgdbirc-default')
4 |
5 | const PGDBIRCPlugin = makeExtendSchemaPlugin(build => {
6 | const { pgSql: sql } = build;
7 | const pgdbiDir = `${process.cwd()}/.pgdbi`
8 | const pgdbircPath = `${pgdbiDir}/.pgdbirc.json`
9 |
10 | fs.mkdirSync(pgdbiDir, {recursive: true})
11 |
12 | const exists = fs.existsSync(pgdbircPath)
13 | if (!exists) {
14 | fs.writeFileSync(pgdbircPath, JSON.stringify(defaultPgdbirc,0,2))
15 | }
16 |
17 | return {
18 | typeDefs: gql`
19 | type PGDBIRCPayload {
20 | pgdbirc: JSON!
21 | }
22 |
23 | extend type Query {
24 | PGDBIRC: PGDBIRCPayload
25 | }
26 | `,
27 | resolvers: {
28 | Query: {
29 | PGDBIRC: async (
30 | _query,
31 | args,
32 | context,
33 | resolveInfo,
34 | { selectGraphQLResultFromTable }
35 | ) => {
36 | try {
37 | const pgdbirc = fs.readFileSync(pgdbircPath)
38 |
39 | return {
40 | pgdbirc: JSON.parse(pgdbirc)
41 | };
42 | } catch (e) {
43 | // Oh noes! If at first you don't succeed,
44 | // destroy all evidence you ever tried.
45 | throw e;
46 | }
47 | },
48 | },
49 | },
50 | };
51 | });
52 |
53 | module.exports = PGDBIRCPlugin
54 |
--------------------------------------------------------------------------------
/src/pgdbi/graphile-extensions/pglintrc-default.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | project: null,
3 | token: null
4 | }
5 |
--------------------------------------------------------------------------------
/src/pgdbi/graphile-extensions/project.js:
--------------------------------------------------------------------------------
1 | const { makeExtendSchemaPlugin, gql } = require("graphile-utils");
2 | const fs = require('fs')
3 |
4 | const PGDBIRCPlugin = makeExtendSchemaPlugin(build => {
5 | const { pgSql: sql } = build;
6 | const pgdbiDir = `${process.cwd()}/.pgdbi`
7 | const projectPath = `${pgdbiDir}/project.json`
8 |
9 | return {
10 | typeDefs: gql`
11 | type ProjectPayload {
12 | project: JSON!
13 | }
14 |
15 | extend type Query {
16 | project: ProjectPayload
17 | }
18 | `,
19 | resolvers: {
20 | Query: {
21 | project: async (
22 | _query,
23 | args,
24 | context,
25 | resolveInfo,
26 | { selectGraphQLResultFromTable }
27 | ) => {
28 | try {
29 | const exists = fs.existsSync(projectPath)
30 | if (!exists) {
31 | throw new Error('Project file does not exist')
32 | }
33 |
34 | const project = fs.readFileSync(projectPath)
35 |
36 | return {
37 | project: JSON.parse(project)
38 | };
39 | } catch (e) {
40 | // Oh noes! If at first you don't succeed,
41 | // destroy all evidence you ever tried.
42 | throw e;
43 | }
44 | },
45 | },
46 | },
47 | };
48 | });
49 |
50 | module.exports = PGDBIRCPlugin
51 |
--------------------------------------------------------------------------------
/src/pgdbi/transformBuild.js:
--------------------------------------------------------------------------------
1 | const camelCaseKeys = require('camelcase-keys')
2 | const pg10IntrospectionQuery = require('./pg10IntrospectionQuery')
3 |
4 | const queryBuilderMap = {
5 | "10": require('./pg10IntrospectionQuery'),
6 | "11": require('./pg11IntrospectionQuery'),
7 | "12": require('./pg11IntrospectionQuery')
8 | }
9 |
10 | async function transformBuild(build, pgPool) {
11 | try {
12 | const version = (await pgPool.query('SHOW server_version;')).rows[0].server_version.split('.')[0];
13 | console.log('version', version)
14 | // console.log('build.options', build.options)
15 | const schemas = build.options.pgSchemas.join("','");
16 | console.log('schemas', schemas)
17 | const querySql = await queryBuilderMap[version](schemas)
18 | const schemaTree = camelCaseKeys((await pgPool.query(querySql)).rows[0], {deep:true})
19 | return schemaTree
20 | } catch (e) {
21 | console.log('CAUGHT ERROR', e.toString())
22 | throw e;
23 | }
24 | }
25 |
26 | module.exports = transformBuild
--------------------------------------------------------------------------------
/src/web-vue/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | /dist
4 |
5 | # local env files
6 | .env.local
7 | .env.*.local
8 |
9 | # Log files
10 | npm-debug.log*
11 | yarn-debug.log*
12 | yarn-error.log*
13 |
14 | # Editor directories and files
15 | .idea
16 | .vscode
17 | *.suo
18 | *.ntvs*
19 | *.njsproj
20 | *.sln
21 | *.sw*
22 |
--------------------------------------------------------------------------------
/src/web-vue/README.md:
--------------------------------------------------------------------------------
1 | # web-vue
2 |
3 | ## Project setup
4 |
5 | ```
6 | yarn install
7 | ```
8 |
9 | ### Compiles and hot-reloads for development
10 |
11 | ```
12 | yarn run serve
13 | ```
14 |
15 | ### Compiles and minifies for production
16 |
17 | ```
18 | yarn run build
19 | ```
20 |
21 | ### Run your tests
22 |
23 | ```
24 | yarn run test
25 | ```
26 |
27 | ### Lints and fixes files
28 |
29 | ```
30 | yarn run lint
31 | ```
32 |
33 | ### Customize configuration
34 |
35 | See [Configuration Reference](https://cli.vuejs.org/config/).
36 |
--------------------------------------------------------------------------------
/src/web-vue/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: ['@vue/app'],
3 | };
4 |
--------------------------------------------------------------------------------
/src/web-vue/delete/EnabledRoleListMixin.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
24 |
25 |
28 |
--------------------------------------------------------------------------------
/src/web-vue/delete/RoleFilterFunctionsMixin.vue:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/web-vue/delete/RoleList.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
10 |
11 |
12 |
59 |
60 |
63 |
--------------------------------------------------------------------------------
/src/web-vue/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/graphile-contrib/pgdbi/47d3b0454fde69836e99a388f88b00a8463f4285/src/web-vue/public/favicon.ico
--------------------------------------------------------------------------------
/src/web-vue/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | pg-db-inspector
12 |
13 |
14 |
15 |
16 |
17 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/src/web-vue/public/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/graphile-contrib/pgdbi/47d3b0454fde69836e99a388f88b00a8463f4285/src/web-vue/public/logo.png
--------------------------------------------------------------------------------
/src/web-vue/src/AppBus.js:
--------------------------------------------------------------------------------
1 |
2 | import Vue from 'vue';
3 |
4 | const bus = new Vue();
5 |
6 | export default bus;
--------------------------------------------------------------------------------
/src/web-vue/src/assets/logo.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/web-vue/src/components/Enum/Enum.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | {{ id }}
4 |
5 |
11 |
12 |
13 |
14 |
67 |
68 |
71 |
--------------------------------------------------------------------------------
/src/web-vue/src/components/ForeignKeyIndex/Constraints/CheckConstraints.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 | Check Constraints
8 |
14 |
15 |
16 |
17 |
18 |
19 |
71 |
72 |
73 |
74 |
--------------------------------------------------------------------------------
/src/web-vue/src/components/FunctionSecurity/Assignment/FunctionPolicyAssignment.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
11 | By Schema
12 |
13 |
16 |
17 |
18 |
22 | By Policy
23 |
24 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/src/web-vue/src/components/Help/Help.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | HELP!!!
4 |
5 |
6 |
7 |
16 |
17 |
20 |
--------------------------------------------------------------------------------
/src/web-vue/src/components/PgLint/PgLintResult.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | {{pgLintResult.url}}
4 |
5 |
6 |
7 |
23 |
24 |
--------------------------------------------------------------------------------
/src/web-vue/src/components/Project/ProjectExport.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
Export Project
4 |
5 | Save
6 |
7 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/src/web-vue/src/components/Project/ProjectImport.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
8 |
9 |
10 |
Import Project: {{ projectName }}
11 |
12 | Import
13 |
14 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/src/web-vue/src/components/Project/ProjectNavigator.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
6 |
7 |
8 |
20 |
21 |
24 |
--------------------------------------------------------------------------------
/src/web-vue/src/components/Project/ProjectResetDialog.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
10 | RESET PGDBI
11 |
12 |
13 |
14 | Are you sure you want to reset PGDBI?
15 | This will discard all policy definitions and assignement
16 |
17 |
18 | Cancel
19 | Save Project First
20 | Exterminate!
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
70 |
71 |
--------------------------------------------------------------------------------
/src/web-vue/src/components/Role/CreateRolesRealization.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/src/web-vue/src/components/Schema/SchemaUsageRealization.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/src/web-vue/src/components/Settings/DefaultRlsUsing.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Save
8 | Default RLS Using Clause
9 |
10 |
16 |
17 |
18 |
19 |
20 |
21 |
50 |
51 |
--------------------------------------------------------------------------------
/src/web-vue/src/components/Settings/SecurityPolicySettings.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
28 |
29 |
--------------------------------------------------------------------------------
/src/web-vue/src/components/Settings/Settings.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | Settings
4 | Under Construction
5 |
6 |
10 |
14 | Table Policy Template
15 |
16 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
42 |
43 |
46 |
--------------------------------------------------------------------------------
/src/web-vue/src/components/SmartCommentManager/SmartCommentManager.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
A tool to ensure that all smart comments are properly configured to support postgraphile
4 |
5 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/src/web-vue/src/components/Table/Constraints/TableCheckConstraints.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 | Check Constraints
8 |
14 |
15 |
16 |
17 |
18 |
19 |
71 |
72 |
75 |
--------------------------------------------------------------------------------
/src/web-vue/src/components/Table/Constraints/TableKeyColumnUsage.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
10 | {{ props.item.tableSchema }} |
11 | {{ props.item.tableName }} |
12 | {{ props.item.columnName }} |
13 |
14 |
15 |
16 |
17 |
18 |
50 |
51 |
54 |
--------------------------------------------------------------------------------
/src/web-vue/src/components/Table/Constraints/TableUniqueConstraints.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
10 | {{ props.item.constraintSchema }} |
11 | {{ props.item.constraintName }} |
12 |
13 |
14 |
15 |
16 |
17 |
56 |
57 |
60 |
--------------------------------------------------------------------------------
/src/web-vue/src/components/Table/TableGrants.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
10 |
12 | {{ props.item.grantee }} |
13 |
14 | {{ props.item.privilegeType }} |
15 |
17 |
18 |
19 |
20 |
21 |
22 |
61 |
62 |
65 |
--------------------------------------------------------------------------------
/src/web-vue/src/components/Table/TableIndices copy.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
10 | {{ props.item.tableSchema }} |
11 | {{ props.item.tableName }} |
12 | {{ props.item.columnName }} |
13 | {{ props.item.indexName }} |
14 |
15 |
16 |
17 |
18 |
19 |
68 |
69 |
72 |
--------------------------------------------------------------------------------
/src/web-vue/src/components/Table/TablePolicies.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
10 |
12 | {{ props.item.policyName }} |
13 | {{ props.item.roles }} |
14 | {{ props.item.cmd }} |
15 | {{ props.item.qual }} |
16 | {{ props.item.withCheck }} |
17 |
18 |
19 |
20 |
21 |
22 |
76 |
77 |
80 |
--------------------------------------------------------------------------------
/src/web-vue/src/components/TableSecurity copy/Assignment/TablePolicyAssignment.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
11 | By Schema
12 |
13 |
16 |
17 |
18 |
22 | By Policy
23 |
24 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/src/web-vue/src/components/TableSecurity-next/Assignment/TablePolicyAssignment.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
11 | By Schema
12 |
13 |
16 |
17 |
18 |
22 | By Policy
23 |
24 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/src/web-vue/src/components/TableSecurity/Assignment/TablePolicyAssignment.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
11 | By Schema
12 |
13 |
16 |
17 |
18 |
22 | By Policy
23 |
24 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/src/web-vue/src/components/Udt/Udt.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | {{ id }}
4 |
5 |
11 |
12 |
13 |
14 |
67 |
68 |
71 |
--------------------------------------------------------------------------------
/src/web-vue/src/components/View/ViewColumns.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
12 |
13 |
14 |
15 |
16 |
60 |
61 |
64 |
--------------------------------------------------------------------------------
/src/web-vue/src/components/View/ViewSearch.vue:
--------------------------------------------------------------------------------
1 |
2 |
6 | Enter a search term to find functions of interest
7 |
11 |
12 |
15 |
16 |
17 |
18 |
62 |
63 |
66 |
--------------------------------------------------------------------------------
/src/web-vue/src/gql/mutation/execSql.graphql:
--------------------------------------------------------------------------------
1 | mutation ExecSql(
2 | $sql: String!
3 | ){
4 | ExecSql(input: {
5 | sql: $sql
6 | }) {
7 | result
8 | }
9 | }
--------------------------------------------------------------------------------
/src/web-vue/src/gql/mutation/pgLint.graphql:
--------------------------------------------------------------------------------
1 | mutation PgLint(
2 | $project: String!
3 | $token: String!
4 | ) {
5 | PgLint(input: {
6 | project: $project
7 | token: $token
8 | }) {
9 | result
10 | }
11 | }
--------------------------------------------------------------------------------
/src/web-vue/src/gql/mutation/searchFunctions.graphql:
--------------------------------------------------------------------------------
1 | mutation SearchFunctions(
2 | $searchTerm: String!
3 | ){
4 | searchFunctions(searchTerm: $searchTerm) {
5 | id
6 | functionName
7 | functionSchema
8 | resultDataType
9 | argumentDataTypes
10 | definition
11 | }
12 | }
--------------------------------------------------------------------------------
/src/web-vue/src/gql/mutation/writeArtifacts.graphql:
--------------------------------------------------------------------------------
1 | mutation WriteArtifacts(
2 | $projectState: JSON!
3 | $masterSecurityPolicy: String!
4 | $ownershipPolicy: String!
5 | $schemaUsageSql: String!
6 | $masterTablePolicy: String!
7 | $masterFunctionPolicy: String!
8 | $allSchemaTablePolicies: JSON!
9 | $allSchemaFunctionPolicies: JSON!
10 | ){
11 | WriteArtifacts(input: {
12 | projectState: $projectState
13 | masterSecurityPolicy: $masterSecurityPolicy
14 | ownershipPolicy: $ownershipPolicy
15 | schemaUsageSql: $schemaUsageSql
16 | masterTablePolicy: $masterTablePolicy
17 | masterFunctionPolicy: $masterFunctionPolicy
18 | allSchemaTablePolicies: $allSchemaTablePolicies
19 | allSchemaFunctionPolicies: $allSchemaFunctionPolicies
20 | }) {
21 | result
22 | }
23 | }
--------------------------------------------------------------------------------
/src/web-vue/src/gql/query/allEnabledRoles.graphql:
--------------------------------------------------------------------------------
1 | query {
2 | allEnabledRoles {
3 | nodes {
4 | roleName
5 | applicableRoles {
6 | grantee
7 | roleName
8 | }
9 | }
10 | }
11 | }
--------------------------------------------------------------------------------
/src/web-vue/src/gql/query/dbIntrospection.graphql:
--------------------------------------------------------------------------------
1 | query {
2 | dbIntrospection
3 | pgdbiOptions
4 | }
--------------------------------------------------------------------------------
/src/web-vue/src/gql/query/functionById.graphql:
--------------------------------------------------------------------------------
1 | query FunctionById($id: String!) {
2 | functionById(id: $id) {
3 | id
4 | functionName
5 | functionSchema
6 | resultDataType
7 | argumentDataTypes
8 | definition
9 | }
10 | }
--------------------------------------------------------------------------------
/src/web-vue/src/gql/query/getDbSchemaList.graphql:
--------------------------------------------------------------------------------
1 | query GetDbSchemaList{
2 | allSchemata(
3 | orderBy: SCHEMA_NAME_ASC
4 | )
5 | {
6 | nodes {
7 | id
8 | schemaName
9 | }
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/src/web-vue/src/gql/query/getDbSchemaTree.graphql:
--------------------------------------------------------------------------------
1 | query {
2 | allSchemata
3 | (
4 | filter: {
5 | schemaName: {
6 | notIn: [
7 | "pg_toast",
8 | "pg_temp_1",
9 | "pg_toast_temp_1",
10 | "pg_catalog",
11 | "information_schema",
12 | "public"
13 | ]
14 | }
15 | }
16 | )
17 | {
18 | nodes {
19 | id
20 | schemaName
21 | schemaTables {
22 | id
23 | name: tableName
24 | tableSchema
25 | tableColumns {
26 | tableName
27 | tableSchema
28 | columnName
29 | dataType
30 | }
31 | }
32 | schemaFunctions {
33 | id
34 | name: functionName
35 | functionSchema
36 | }
37 | schemaEnums {
38 | id
39 | name: enumName
40 | enumSchema
41 | enumValues
42 | }
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/src/web-vue/src/gql/query/getDbSchemaTreeBySchemaName.graphql:
--------------------------------------------------------------------------------
1 | query GetDbSchemaTreeBySchemaName($schemaNames: [SqlIdentifier!]){
2 | allSchemata
3 | (
4 | filter: {
5 | schemaName: {
6 | in: $schemaNames
7 | }
8 | }
9 | )
10 | {
11 | nodes {
12 | id
13 | schemaName
14 | schemaTables {
15 | id
16 | name: tableName
17 | tableSchema
18 | tableColumns {
19 | tableName
20 | tableSchema
21 | columnName
22 | dataType
23 | }
24 | indices {
25 | tableName
26 | tableSchema
27 | columnName
28 | indexName
29 | }
30 | referentialConstraints {
31 | constraintName
32 | constraintSchema
33 | uniqueConstraintName
34 | uniqueConstraintSchema
35 | matchOption
36 | updateRule
37 | deleteRule
38 | referencingColumnUsage {
39 | constraintName
40 | tableSchema
41 | tableName
42 | columnName
43 | ordinalPosition
44 | positionInUniqueConstraint
45 | }
46 | referencedColumnUsage {
47 | constraintName
48 | tableSchema
49 | tableName
50 | columnName
51 | ordinalPosition
52 | positionInUniqueConstraint
53 | }
54 | }
55 | roleTableGrants {
56 | grantor
57 | grantee
58 | tableName
59 | tableSchema
60 | privilegeType
61 | isGrantable
62 | withHierarchy
63 | }
64 | }
65 | schemaFunctions {
66 | id
67 | name: functionName
68 | functionSchema
69 | }
70 | schemaEnums {
71 | id
72 | name: enumName
73 | enumSchema
74 | enumValues
75 | }
76 | }
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/src/web-vue/src/gql/query/getDbSecurityTree.graphql:
--------------------------------------------------------------------------------
1 | query {
2 | allSchemata
3 | (
4 | filter: {
5 | schemaName: {
6 | notIn: [
7 | "pg_toast",
8 | "pg_temp_1",
9 | "pg_toast_temp_1",
10 | "pg_catalog",
11 | "information_schema",
12 | "public"
13 | ]
14 | }
15 | }
16 | )
17 | {
18 | nodes {
19 | id
20 | schemaName
21 | schemaTables {
22 | id
23 | tableName
24 | tableSchema
25 | policies {
26 | tableName
27 | schemaName
28 | policyName
29 | roles
30 | cmd
31 | withCheck
32 | qual
33 | }
34 | roleTableGrants {
35 | grantor
36 | grantee
37 | tableName
38 | tableSchema
39 | privilegeType
40 | isGrantable
41 | withHierarchy
42 | }
43 | }
44 | schemaFunctions {
45 | id
46 | name: functionName
47 | functionSchema
48 | }
49 | }
50 | }
51 | }
--------------------------------------------------------------------------------
/src/web-vue/src/gql/query/getDbSecurityTreeFiltered.graphql:
--------------------------------------------------------------------------------
1 | query GetDbSecurityTreeFiltered(
2 | $filter: [SqlIdentifier!]!
3 | ){
4 | allSchemata(filter: {
5 | schemaName: {
6 | in: $filter
7 | }
8 | }) {
9 | nodes {
10 | id
11 | schemaName
12 | schemaTables {
13 | id
14 | tableName
15 | tableSchema
16 | policies {
17 | tableName
18 | schemaName
19 | policyName
20 | roles
21 | cmd
22 | withCheck
23 | qual
24 | }
25 | roleTableGrants {
26 | grantor
27 | grantee
28 | tableName
29 | tableSchema
30 | privilegeType
31 | isGrantable
32 | withHierarchy
33 | }
34 | roleColumnGrants {
35 | grantor
36 | grantee
37 | tableName
38 | tableSchema
39 | privilegeType
40 | isGrantable
41 | columnName
42 | }
43 | }
44 | schemaFunctions {
45 | id
46 | name: functionName
47 | functionSchema
48 | }
49 | }
50 | }
51 | }
--------------------------------------------------------------------------------
/src/web-vue/src/gql/query/pgdbirc.graphql:
--------------------------------------------------------------------------------
1 | query PGDBIRC {
2 | PGDBIRC {
3 | pgdbirc
4 | }
5 | }
--------------------------------------------------------------------------------
/src/web-vue/src/gql/query/pglintrc.graphql:
--------------------------------------------------------------------------------
1 | query pgpintrc {
2 | pglintrc {
3 | pglintrc
4 | }
5 | }
--------------------------------------------------------------------------------
/src/web-vue/src/gql/query/project.graphql:
--------------------------------------------------------------------------------
1 | query Project {
2 | project {
3 | project
4 | }
5 | }
--------------------------------------------------------------------------------
/src/web-vue/src/main.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue';
2 | import vuetify from './plugins/vuetify';
3 | import App from './App.vue';
4 | import router from './router';
5 | import store from './store/store';
6 | import { createProvider } from './vue-apollo';
7 | import VueClipboard from 'vue-clipboard2';
8 | import VueLoading from 'vuejs-loading-plugin'
9 |
10 |
11 | Vue.config.productionTip = false;
12 |
13 | Vue.use(VueClipboard);
14 | Vue.use(VueLoading)
15 |
16 | new Vue({
17 | vuetify,
18 | router,
19 | store,
20 | apolloProvider: createProvider(),
21 | render: h => h(App),
22 | }).$mount('#app');
23 |
--------------------------------------------------------------------------------
/src/web-vue/src/plugins/vuetify.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue';
2 | import Vuetify from 'vuetify/lib';
3 | // import 'material-design-icons-iconfont/dist/material-design-icons.css'
4 | import '@mdi/font/css/materialdesignicons.css' // Ensure you are using css-loader
5 |
6 | Vue.use(Vuetify);
7 |
8 | export default new Vuetify({
9 | icons: {
10 | iconfont: 'mdi',
11 | },
12 | // theme: {
13 | // primary: '#2196f3',
14 | // secondary: '#3f51b5',
15 | // accent: '#03a9f4',
16 | // error: '#f44336',
17 | // warning: '#ffc107',
18 | // info: '#607d8b',
19 | // success: '#4caf50'
20 | // },
21 | // theme: {
22 | // themes: {
23 | // dark: {
24 | // primary: '#2196f3',
25 | // secondary: '#3f51b5',
26 | // accent: '#03a9f4',
27 | // error: '#f44336',
28 | // warning: '#ffc107',
29 | // info: '#607d8b',
30 | // success: '#4caf50'
31 | // }
32 | // }
33 | // }
34 | });
35 |
--------------------------------------------------------------------------------
/src/web-vue/src/scriptCompute/computeAllSchemaFunctionPolicies.js:
--------------------------------------------------------------------------------
1 | import computeSchemaFunctionPolicy from './computeSchemaFunctionPolicy'
2 |
3 | function computeAllSchemaFunctionPolicies (state, policyReadability) {
4 | return state.managedSchemata
5 | .filter(s => !s.parked)
6 | .filter(s => s.schemaFunctions.length > 0)
7 | .reduce(
8 | (all, schema) => {
9 | const schemaFunctions = schema.schemaFunctions
10 | const schemaPolicy = {
11 | name: `${schema.schemaName}`,
12 | policy: computeSchemaFunctionPolicy(state, policyReadability, schemaFunctions)
13 | }
14 | return all.concat([schemaPolicy])
15 | }, []
16 | )
17 | .sort(
18 | (a,b)=>{
19 | return a.name < b.name ? -1 : 1
20 | }
21 | )
22 | }
23 |
24 | export default computeAllSchemaFunctionPolicies
--------------------------------------------------------------------------------
/src/web-vue/src/scriptCompute/computeAllSchemaTablePolicies.js:
--------------------------------------------------------------------------------
1 | // import computeRemoveRls from './computeRemoveRls'
2 | import computeSchemaTablePolicy from './computeSchemaTablePolicy'
3 |
4 | function computeAllSchemaTablePolicies (state, policyReadability) {
5 | return state.managedSchemata
6 | .filter(s => !s.parked)
7 | .filter(s => s.schemaTables.length > 0)
8 | .reduce(
9 | (all, schema) => {
10 | const schemaTables = schema.schemaTables.filter(t => t.tableType === 'BASE TABLE')
11 | // const schemaRemoveRls = computeRemoveRls(schema.schemaName)
12 |
13 | const schemaPolicy = {
14 | name: `${schema.schemaName}`,
15 | policy: computeSchemaTablePolicy(state, policyReadability, schemaTables)
16 | }
17 | return all.concat([schemaPolicy])
18 | }, []
19 | )
20 | .sort(
21 | (a,b)=>{
22 | return a.name < b.name ? -1 : 1
23 | }
24 | )
25 | }
26 |
27 | export default computeAllSchemaTablePolicies
--------------------------------------------------------------------------------
/src/web-vue/src/scriptCompute/computeMasterFunctionPolicy.js:
--------------------------------------------------------------------------------
1 | import computeAllSchemaFunctionPolicies from './computeAllSchemaFunctionPolicies'
2 |
3 | function computeMasterFunctionPolicy (state, policyReadability) {
4 | const masterPolicyName = 'All Schemata - Functions'
5 | const schemaFunctionPolicies = computeAllSchemaFunctionPolicies(state, policyReadability)
6 | const masterPolicy = schemaFunctionPolicies.reduce(
7 | (m, p) => {
8 | return m.concat(p.policy)
9 | }, ''
10 | )
11 |
12 | return {
13 | name: masterPolicyName,
14 | policy: masterPolicy
15 | }
16 | }
17 |
18 | export default computeMasterFunctionPolicy
--------------------------------------------------------------------------------
/src/web-vue/src/scriptCompute/computeMasterSecurityPolicy.js:
--------------------------------------------------------------------------------
1 | import computeRolesSql from "./computeRolesSql"
2 | import computeSchemaUsageSql from "./computeSchemaUsageSql"
3 | import computeMasterTablePolicy from "./computeMasterTablePolicy"
4 | import computeMasterFunctionPolicy from "./computeMasterFunctionPolicy"
5 | import computeOwnershipPolicy from "./computeOwnershipPolicy"
6 |
7 | function computeMasterSecurityPolicy (state, policyReadability) {
8 | return [
9 | '--===== BEGIN COMPLETE SECURITY POLICY -========',
10 | computeRolesSql(state),
11 | '\n\n--***** BEGIN OWNERSHIP -********',
12 | computeOwnershipPolicy(state, policyReadability),
13 | '--***** END OWNERSHIP -**********',
14 | '\n\n--***** BEGIN SCHEMA USAGE -********',
15 | computeSchemaUsageSql(state, policyReadability),
16 | '--***** END SCHEMA USAGE -**********',
17 | '\n\n--***** BEGIN TABLE POLICIES -********',
18 | computeMasterTablePolicy(state, policyReadability).policy,
19 | '--***** END TABLE POLICIES -**********',
20 | '\n\n--***** BEGIN FUNCTION POLICIES -********',
21 | computeMasterFunctionPolicy(state, policyReadability).policy,
22 | '--***** END FUNCTION POLICIES -**********',
23 | '\n\n--===== END COMPLETE SECURITY POLICY -==========',
24 | ].join('\n')
25 |
26 | }
27 |
28 | export default computeMasterSecurityPolicy
--------------------------------------------------------------------------------
/src/web-vue/src/scriptCompute/computeMasterTablePolicy.js:
--------------------------------------------------------------------------------
1 | import computeAllSchemaTablePolicies from './computeAllSchemaTablePolicies'
2 |
3 | function computeMasterTablePolicy (state, policyReadability) {
4 | const masterPolicyName = 'All Schemata - Tables'
5 | const schemaTablePolicies = computeAllSchemaTablePolicies(state, policyReadability)
6 | const masterPolicy = schemaTablePolicies.reduce(
7 | (m, p) => {
8 | return m.concat(p.policy)
9 | }, ''
10 | )
11 |
12 | return {
13 | name: masterPolicyName,
14 | policy: masterPolicy
15 | }
16 |
17 | }
18 |
19 | export default computeMasterTablePolicy
--------------------------------------------------------------------------------
/src/web-vue/src/scriptCompute/computeOwnershipPolicy.js:
--------------------------------------------------------------------------------
1 | import Mustache from 'mustache'
2 |
3 | const ownershipPolicyTemplate = `
4 | ----------
5 | ---------- BEGIN OWNERSHIP SQL
6 | ----------
7 |
8 |
9 | {{#schemata}}
10 | ---------- SCHEMA: {{schemaName}}
11 | ALTER SCHEMA {{schemaName}} OWNER TO {{dbOwnerRole}};
12 | -- tables
13 | {{#schemaTables}}
14 | ALTER TABLE {{schemaName}}.{{tableName}} OWNER TO {{dbOwnerRole}};
15 | {{/schemaTables}}
16 | -- functions
17 | {{#schemaFunctions}}
18 | ALTER FUNCTION {{schemaName}}.{{functionName}}({{argumentDataTypes}}) OWNER TO {{dbOwnerRole}};
19 | {{/schemaFunctions}}
20 | ---------- END SCHEMA: {{schemaName}}
21 | {{/schemata}}
22 | ----------
23 | ---------- END OWNERSHIP SQL
24 | ----------
25 | --==
26 | `
27 |
28 | const computeOwnershipPolicy = (state) => {
29 | const sortedSchemata = state.managedSchemata
30 | .sort((a,b)=>{
31 | if ( a.schemaName < b.schemaName ){
32 | return -1;
33 | }
34 | if ( a.schemaName > b.schemaName ){
35 | return 1;
36 | }
37 | return 0;
38 | })
39 | .map(s=>{
40 | return {
41 | ...s,
42 | schemaFunctions: s.schemaFunctions.map(f=>{
43 | const argumentDataTypes = f.argumentDataTypes
44 | .split(',')
45 | .map(adt => adt.replace('timestamp with time zone', 'timestamptz'))
46 | .map(adt => adt.trim().split(' ')[1])
47 | .join(', ')
48 |
49 | return {
50 | ...f,
51 | argumentDataTypes: argumentDataTypes
52 | }
53 | })
54 | }
55 | })
56 |
57 | return Mustache.render(
58 | ownershipPolicyTemplate,
59 | {
60 | schemata: sortedSchemata,
61 | dbOwnerRole: state.roleSet.dbOwnerRole.roleName
62 | }
63 | ).split("'").join("'")
64 | }
65 |
66 | export default computeOwnershipPolicy
--------------------------------------------------------------------------------
/src/web-vue/src/scriptCompute/computeRemoveRls.js:
--------------------------------------------------------------------------------
1 | import Mustache from 'mustache'
2 |
3 | function computeRemoveRls (schemaName) {
4 | return Mustache.render(
5 | removeAllRlsScriptTemplate,
6 | { schemaName: schemaName }
7 | )
8 | }
9 |
10 | export default computeRemoveRls
11 |
12 | const removeAllRlsScriptTemplate = `
13 | ----------
14 | ---------- remove all rls policies for schema: {{schemaName}}
15 | ----------
16 | DO
17 | $body$
18 | DECLARE
19 | _pol pg_policies;
20 | _drop_sql text;
21 | BEGIN
22 |
23 | for _pol in
24 | select
25 | *
26 | from pg_policies
27 | where schemaname = '{{schemaName}}'
28 | loop
29 | _drop_sql := 'drop policy if exists ' || _pol.policyname || ' on ' || _pol.schemaname || '.' || _pol.tablename || ';';
30 | execute _drop_sql;
31 | end loop
32 | ;
33 | END
34 | $body$;
35 | `
--------------------------------------------------------------------------------
/src/web-vue/src/scriptCompute/computeSchemaFunctionPolicy.js:
--------------------------------------------------------------------------------
1 | import computeFunctionPolicy from './computeFunctionPolicy'
2 |
3 | function computeSchemaFunctionPolicy (state, policyReadability, someFunctions) {
4 | const retval = someFunctions.sort((a,b)=>{return a.functionname < b.functionname ? -1 : 1}).reduce(
5 | (policy, aFunction) => {
6 | const policyTemplate = state.functionPolicies.find(p => p.id === state.functionPolicyAssignments[aFunction.id].policyDefinitionId)
7 | const variables = {
8 | }
9 | const aFunctionPolicy = computeFunctionPolicy(policyTemplate, policyReadability, variables, aFunction)
10 | return policy.concat(aFunctionPolicy)
11 | }, ''
12 | )
13 | return retval
14 | }
15 |
16 | export default computeSchemaFunctionPolicy
--------------------------------------------------------------------------------
/src/web-vue/src/scriptCompute/computeSchemaTablePolicy.js:
--------------------------------------------------------------------------------
1 | import computeTablePolicy from './computeTablePolicy'
2 |
3 | function computeSchemaTablePolicy (state, policyReadability, tables) {
4 | return tables.sort((a,b)=>{return a.tablename < b.tablename ? -1 : 1}).reduce(
5 | (policy, table) => {
6 | const policyTemplate = state.policies.find(p => p.id === state.tablePolicyAssignments[table.id].policyDefinitionId)
7 | const variables = {
8 | schemaName: table.tableSchema,
9 | tableName: table.tablename
10 | }
11 | const tablePolicy = computeTablePolicy(policyTemplate, policyReadability, variables, table)
12 | return policy.concat(tablePolicy)
13 | }, ''
14 | )
15 | }
16 |
17 | export default computeSchemaTablePolicy
--------------------------------------------------------------------------------
/src/web-vue/src/scriptCompute/index.js:
--------------------------------------------------------------------------------
1 | import computeAllSchemaFunctionPolicies from './computeAllSchemaFunctionPolicies'
2 | import computeAllSchemaTablePolicies from './computeAllSchemaTablePolicies'
3 | import computeFunctionPolicy from './computeFunctionPolicy'
4 | import computeMasterFunctionPolicy from './computeMasterFunctionPolicy'
5 | import computeMasterSecurityPolicy from './computeMasterSecurityPolicy'
6 | import computeMasterTablePolicy from './computeMasterTablePolicy'
7 | import computeOwnershipPolicy from './computeOwnershipPolicy'
8 | import computeRemoveRls from './computeRemoveRls'
9 | import computeRolesSql from './computeRolesSql'
10 | import computeSchemaFunctionPolicy from './computeSchemaFunctionPolicy'
11 | import computeSchemaTablePolicy from './computeSchemaTablePolicy'
12 | import computeSchemaUsageSql from './computeSchemaUsageSql'
13 | import computeTablePolicy from './computeTablePolicy'
14 |
15 | export default {
16 | computeAllSchemaFunctionPolicies,
17 | computeAllSchemaTablePolicies,
18 | computeFunctionPolicy,
19 | computeMasterFunctionPolicy,
20 | computeMasterSecurityPolicy,
21 | computeMasterTablePolicy,
22 | computeOwnershipPolicy,
23 | computeRemoveRls,
24 | computeRolesSql,
25 | computeSchemaFunctionPolicy,
26 | computeSchemaTablePolicy,
27 | computeSchemaUsageSql,
28 | computeTablePolicy
29 | }
--------------------------------------------------------------------------------
/src/web-vue/src/store/actions/index.js:
--------------------------------------------------------------------------------
1 | import setProjectRoleSet from './setProjectRoleSet'
2 | import setManagedSchemata from './setManagedSchemata'
3 | import resetDefaultState from './resetDefaultState'
4 | import writeToDisk from './writeToDisk'
5 | import loadFromDisk from './loadFromDisk'
6 |
7 | export default {
8 | setProjectRoleSet,
9 | setManagedSchemata,
10 | resetDefaultState,
11 | writeToDisk,
12 | loadFromDisk
13 | }
--------------------------------------------------------------------------------
/src/web-vue/src/store/actions/loadFromDisk.js:
--------------------------------------------------------------------------------
1 | import {getApolloClient} from '@/vue-apollo'
2 | import project from '@/gql/query/project.graphql'
3 |
4 | async function loadFromDisk({commit}) {
5 | const apolloClient = getApolloClient()
6 |
7 | const queryResult = await apolloClient.query({
8 | query: project,
9 | fetchPolicy: 'network-only'
10 | })
11 |
12 | const theProject = queryResult.data.project.project
13 |
14 | commit('importProject', {
15 | project: theProject
16 | })
17 |
18 | }
19 |
20 | export default loadFromDisk
21 |
--------------------------------------------------------------------------------
/src/web-vue/src/store/actions/pgdbirc.js:
--------------------------------------------------------------------------------
1 | import {getApolloClient} from '@/vue-apollo'
2 | import getPgdbirc from '@/gql/query/pgdbirc.graphql'
3 |
4 | async function pgdbirc() {
5 | const apolloClient = getApolloClient()
6 |
7 | const queryResult = await apolloClient.query({
8 | query: getPgdbirc,
9 | fetchPolicy: 'network-only'
10 | })
11 |
12 | return queryResult.data.PGDBIRC.pgdbirc
13 | }
14 |
15 | export default pgdbirc
16 |
--------------------------------------------------------------------------------
/src/web-vue/src/store/actions/resetDefaultState.js:
--------------------------------------------------------------------------------
1 | import getGetPgdbirc from './pgdbirc'
2 |
3 | async function resetDefaultState(context) {
4 | const pgdbirc = await getGetPgdbirc()
5 | await context.commit('resetDefaultState', pgdbirc)
6 | }
7 |
8 | export default resetDefaultState
9 |
--------------------------------------------------------------------------------
/src/web-vue/src/store/actions/setManagedSchemata.js:
--------------------------------------------------------------------------------
1 | async function setManagedSchemata({commit}, payload) {
2 | await commit('setManagedSchemata', payload.schemaTree)
3 | commit('setPgdbiOptions', payload.pgdbiOptions)
4 | commit('setExistingRlsPolicies', payload.rlsPolicies)
5 | }
6 |
7 | export default setManagedSchemata;
8 |
--------------------------------------------------------------------------------
/src/web-vue/src/store/actions/setProjectRoleSet.js:
--------------------------------------------------------------------------------
1 |
2 | async function setProjectRoleSet({commit, dispatch}, roleSet) {
3 | await dispatch('resetDefaultState')
4 | await commit('setProjectRoleSet', roleSet)
5 | await commit('defaultRlsUsing', roleSet.defaultRlsUsing)
6 | return `role set set - ${roleSet}`
7 | }
8 |
9 | export default setProjectRoleSet;
10 |
--------------------------------------------------------------------------------
/src/web-vue/src/store/mutations/assignFunctionPolicy.js:
--------------------------------------------------------------------------------
1 | function evaluateFunctionPolicy(functionId, policyDefinitionId) {
2 | return {
3 | functionId: functionId
4 | ,policyDefinitionId: policyDefinitionId
5 | ,evaluation: {
6 | status: 'PASS'
7 | ,errors: []
8 | }
9 | }
10 | }
11 |
12 | function assignAll(state, payload) {
13 | state.isDirty = true
14 | const functionIds = payload.functionIds;
15 | const policyDefinitionId = payload.policyDefinitionId;
16 |
17 | functionIds.forEach(
18 | functionId => {
19 | state.functionPolicyAssignments[functionId] = evaluateFunctionPolicy(functionId, policyDefinitionId)
20 | }
21 | )
22 | }
23 |
24 | export default assignAll;
25 |
--------------------------------------------------------------------------------
/src/web-vue/src/store/mutations/assignTablePolicy.js:
--------------------------------------------------------------------------------
1 | function evaluateTablePolicy(tableId, policyDefinitionId) {
2 | return {
3 | tableId: tableId
4 | ,policyDefinitionId: policyDefinitionId
5 | ,evaluation: {
6 | status: 'PASS'
7 | ,errors: []
8 | }
9 | }
10 | }
11 |
12 | function assignAll(state, payload) {
13 | state.isDirty = true
14 | const tableIds = payload.tableIds;
15 | const policyDefinitionId = payload.policyDefinitionId;
16 |
17 | tableIds.forEach(
18 | tableId => {
19 | state.tablePolicyAssignments[tableId] = evaluateTablePolicy(tableId, policyDefinitionId)
20 | }
21 | )
22 | }
23 |
24 | export default assignAll;
25 |
--------------------------------------------------------------------------------
/src/web-vue/src/store/mutations/createRlsPolicy.js:
--------------------------------------------------------------------------------
1 | function createRlsPolicy(state, payload) {
2 | const policy = state.policies.find(p => p.id === payload.policyId);
3 | const otherPolicies = state.policies.filter(p => p.id !== payload.policyId);
4 | const roleName = payload.roleName;
5 | const action = payload.action;
6 |
7 | const id = new Date().getTime() * 10000 + 621355968000000000;
8 | const newRlsPolicy = {
9 | id: id,
10 | name: payload.name || `rls_${id}`,
11 | using: payload.using || state.defaultRlsUsing,
12 | withCheck: payload.withCheck || state.defaultRlsWithCheck,
13 | passStrategy: payload.passStrategy || 'permissive',
14 | };
15 |
16 | const updatedPolicy = {
17 | ...policy,
18 | rlsQualifiers: {
19 | ...policy.rlsQualifiers,
20 | [roleName]: {
21 | ...policy.rlsQualifiers[roleName],
22 | [action]: {
23 | ...policy.rlsQualifiers[roleName][action],
24 | policies: [
25 | ...policy.rlsQualifiers[roleName][action].policies,
26 | ...[newRlsPolicy],
27 | ],
28 | },
29 | },
30 | },
31 | };
32 |
33 | state.policies = [...otherPolicies, ...[updatedPolicy]];
34 | }
35 |
36 | export default createRlsPolicy;
37 |
--------------------------------------------------------------------------------
/src/web-vue/src/store/mutations/customizeTablePolicy.js:
--------------------------------------------------------------------------------
1 | import assignTablePolicy from './assignTablePolicy'
2 |
3 | function customizeTablePolicy(state, payload) {
4 | state.isDirty = true
5 | const sourcePolicyDefinitionId = payload.sourcePolicyDefinitionId;
6 | const newFields = payload.newFields;
7 | const tableIds = payload.tableIds || [];
8 |
9 | const sourcePolicyDefinition = state.policies.find(
10 | p => p.id === sourcePolicyDefinitionId,
11 | );
12 |
13 | const newPolicy = {
14 | ...sourcePolicyDefinition,
15 | id: new Date().getTime() * 10000 + 621355968000000000,
16 | name: newFields.name,
17 | customIdentifier: tableIds.length === 1 ? tableIds[0] : null,
18 | };
19 |
20 | state.policies = [...state.policies, newPolicy]
21 | .sort(function(a, b) {
22 | return a.id < b.id;
23 | });
24 |
25 | assignTablePolicy(state, {
26 | tableIds: tableIds,
27 | policyDefinitionId: newPolicy.id
28 | });
29 | }
30 |
31 | export default customizeTablePolicy;
32 |
--------------------------------------------------------------------------------
/src/web-vue/src/store/mutations/defaultRlsUsing.js:
--------------------------------------------------------------------------------
1 | function defaultRlsUsing(state, payload) {
2 | state.isDirty = true
3 | state.defaultRlsUsing = payload;
4 | }
5 |
6 | export default defaultRlsUsing;
7 |
--------------------------------------------------------------------------------
/src/web-vue/src/store/mutations/defaultRlsWithCheck.js:
--------------------------------------------------------------------------------
1 | function defaultRlsWithCheck(state, payload) {
2 | state.isDirty = true
3 | state.defaultRlsWithCheck = payload.defaultRlsWithCheck;
4 | }
5 |
6 | export default defaultRlsWithCheck;
7 |
--------------------------------------------------------------------------------
/src/web-vue/src/store/mutations/deleteRlsPolicy.js:
--------------------------------------------------------------------------------
1 | function deleteRlsPolicy(state, payload) {
2 | state.isDirty = true
3 | const policy = state.policies.find(p => p.id === payload.policyId);
4 | const otherPolicies = state.policies.filter(p => p.id !== payload.policyId);
5 | const roleName = payload.roleName;
6 | const action = payload.action;
7 | const rlsPolicyId = payload.rlsPolicyId;
8 |
9 | const updatedPolicy = {
10 | ...policy,
11 | rlsQualifiers: {
12 | ...policy.rlsQualifiers,
13 | [roleName]: {
14 | ...policy.rlsQualifiers[roleName],
15 | [action]: {
16 | ...policy.rlsQualifiers[roleName][action],
17 | policies: policy.rlsQualifiers[roleName][action].policies.filter(
18 | rp => rp.id !== rlsPolicyId,
19 | ),
20 | },
21 | },
22 | },
23 | };
24 |
25 | state.policies = [...otherPolicies, ...[updatedPolicy]];
26 | }
27 |
28 | export default deleteRlsPolicy;
29 |
--------------------------------------------------------------------------------
/src/web-vue/src/store/mutations/deleteTablePolicy.js:
--------------------------------------------------------------------------------
1 | function deleteTablePolicy(state, payload) {
2 | state.isDirty = true
3 | const policyDefinitionId = payload.policyDefinitionId;
4 |
5 | const otherPolicies = state.policies.filter(p => p.id !== policyDefinitionId);
6 |
7 | state.policies = [...otherPolicies].sort(function(a, b) {
8 | return a.id < b.id;
9 | });
10 |
11 | Object.keys(state.tablePolicyAssignments).forEach(
12 | tableId => {
13 | if (state.tablePolicyAssignments[tableId] === policyDefinitionId) {
14 | state.tablePolicyAssignments[tableId] = state.defaultPolicy.id
15 | }
16 | }
17 | )
18 | }
19 |
20 | export default deleteTablePolicy;
21 |
--------------------------------------------------------------------------------
/src/web-vue/src/store/mutations/evaluate/evaluateAll.js:
--------------------------------------------------------------------------------
1 | import evaluateFkIndexes from './evaluateFkIndexes'
2 | import evaluateUqIndexes from './evaluateUqIndexes'
3 | import evaluateGenericIndices from './evaluateGenericIndices'
4 | import evaluateEnumScripts from './evaluateEnumScripts'
5 | import evaluateUdtScripts from './evaluateUdtScripts'
6 |
7 |
8 | function evaluateAll(state){
9 | evaluateFkIndexes(state)
10 | evaluateUqIndexes(state)
11 | evaluateGenericIndices(state)
12 | evaluateEnumScripts(state)
13 | evaluateUdtScripts(state)
14 | }
15 |
16 | export default evaluateAll
--------------------------------------------------------------------------------
/src/web-vue/src/store/mutations/evaluate/evaluateEnumScripts.js:
--------------------------------------------------------------------------------
1 | import Mustache from 'mustache'
2 |
3 | const enumTemplate = `
4 | create type {{enumSchema}}.{{enumName}} as (
5 | {{#enumValues}}
6 | '{{value}}'{{comma}}
7 | {{/enumValues}}
8 | );
9 | `
10 |
11 | function evaluateEnumScripts(state){
12 | state.managedSchemata = state.managedSchemata
13 | .map(
14 | schema => {
15 | return {
16 | ...schema
17 | ,schemaEnums: schema.schemaEnums
18 | .map(
19 | e => {
20 | const enumDefinition = Mustache.render(
21 | enumTemplate,
22 | {
23 | ...e
24 | ,enumValues: e.enumValues.map(
25 | (v,i) => {
26 | return {
27 | value: v
28 | ,comma: i === e.enumValues.length -1 ? '' : ','
29 | }
30 | }
31 | )
32 | }
33 | )
34 |
35 | return {
36 | ...e
37 | ,enumDefinition: enumDefinition
38 | }
39 | }
40 | )
41 | }
42 | }
43 | )
44 | }
45 |
46 | export default evaluateEnumScripts
--------------------------------------------------------------------------------
/src/web-vue/src/store/mutations/evaluate/evaluateUdtScripts.js:
--------------------------------------------------------------------------------
1 | import Mustache from 'mustache'
2 |
3 | const udtTemplate = `
4 | create type {{udtSchema}}.{{udtName}} as (
5 | {{#fields}}
6 | {{fieldName}} {{dataType}}{{comma}}
7 | {{/fields}}
8 | );
9 | `
10 |
11 | function evaluateUdtScripts(state){
12 | state.managedSchemata = state.managedSchemata
13 | .map(
14 | schema => {
15 | return {
16 | ...schema
17 | ,schemaUdts: schema.schemaUdts
18 | .map(
19 | e => {
20 | const udtDefinition = Mustache.render(
21 | udtTemplate,
22 | {
23 | ...e
24 | ,fields: e.fields.map(
25 | (f, i) => {
26 | return {
27 | ...f
28 | ,comma: i === e.fields.length -1 ? '' : ','
29 | }
30 | }
31 | )
32 | }
33 | )
34 |
35 | return {
36 | ...e
37 | ,udtDefinition: udtDefinition
38 | }
39 | }
40 | )
41 | }
42 | }
43 | )
44 | }
45 |
46 | export default evaluateUdtScripts
--------------------------------------------------------------------------------
/src/web-vue/src/store/mutations/evaluate/storeEvaluations.js:
--------------------------------------------------------------------------------
1 | function storeEvaluations(state, evaluations){
2 | const indexEvaluations = Object.keys(evaluations)
3 | .reduce(
4 | (all, k) => {
5 | const existing = state.indexEvaluations[k]
6 | const thisEvaluation = existing ? [...existing, ...evaluations[k]] : evaluations[k]
7 | // console.log('evaluations', evaluations)
8 | // console.log('evaluations[k]', k, evaluations[k])
9 | // console.log('existing', existing)
10 | // console.log('thisEvaluation', thisEvaluation)
11 | return thisEvaluation.length === 0 ? all : {
12 | ...all
13 | ,[thisEvaluation[0].idxKey]: thisEvaluation
14 | }
15 | }, {}
16 | )
17 |
18 | state.indexEvaluations = {
19 | ...state.indexEvaluations,
20 | ...indexEvaluations
21 | }
22 | }
23 |
24 | export default storeEvaluations
--------------------------------------------------------------------------------
/src/web-vue/src/store/mutations/filterSchemata.js:
--------------------------------------------------------------------------------
1 | function filterSchemata(state) {
2 | state.isDirty = true
3 | state.schemaFilterOn = true;
4 | }
5 |
6 | export default filterSchemata;
7 |
--------------------------------------------------------------------------------
/src/web-vue/src/store/mutations/importProject.js:
--------------------------------------------------------------------------------
1 | function importProject(state, payload) {
2 | Object.keys(payload.project).forEach(key => {
3 | state[key] = payload.project[key];
4 | });
5 | }
6 |
7 | export default importProject;
8 |
--------------------------------------------------------------------------------
/src/web-vue/src/store/mutations/makeGlobalTablePolicy.js:
--------------------------------------------------------------------------------
1 | function makeGlobalTablePolicy(state, payload) {
2 | state.isDirty = true
3 | const policyDefinitionId = payload.policyDefinitionId;
4 | const newFields = payload.newFields;
5 |
6 | const existing = state.policies.find(p => p.name === newFields.name);
7 | if (existing) {
8 | throw new Error('A policy with this name already exists');
9 | } else {
10 | const policyDefinition = state.policies.find(
11 | p => p.id === policyDefinitionId,
12 | );
13 | const otherPolicies = state.policies.filter(
14 | p => p.id !== policyDefinition.id,
15 | );
16 |
17 | const newGlobalPolicy = {
18 | ...policyDefinition,
19 | name: newFields.name,
20 | customIdentifier: null,
21 | };
22 |
23 | state.policies = [...otherPolicies, ...[newGlobalPolicy]].sort(function(
24 | a,
25 | b,
26 | ) {
27 | return a.id < b.id;
28 | });
29 | }
30 | }
31 |
32 | export default makeGlobalTablePolicy;
33 |
--------------------------------------------------------------------------------
/src/web-vue/src/store/mutations/newFunctionPolicy.js:
--------------------------------------------------------------------------------
1 | function newFunctionPolicy(state, payload) {
2 | state.isDirty = true
3 | const existing = state.policies.find(p => p.name === payload.name);
4 | if (existing) {
5 | throw new Error('A policy with this name already exists');
6 | } else {
7 | const name = payload.name;
8 | const dbUserRoles = state.roleSet.dbUserRoles;
9 |
10 | const newPolicy = {
11 | id: new Date().getTime() * 10000 + 621355968000000000,
12 | name: name,
13 | functionPolicyHeaderTemplate: state.functionPolicyHeaderTemplate,
14 | functionPolicyFooterTemplate: state.functionPolicyFooterTemplate,
15 | roleFunctionGrants: dbUserRoles.reduce((all, projectRole) => {
16 | return {
17 | ...all,
18 | [projectRole.roleName]: state.defaultFunctionRoleGrants,
19 | };
20 | }, {}),
21 | };
22 |
23 | state.functionPolicies = [...state.functionPolicies, ...[newPolicy]].sort(
24 | function(a, b) {
25 | return a.id < b.id;
26 | },
27 | );
28 | }
29 | }
30 |
31 | export default newFunctionPolicy;
32 |
--------------------------------------------------------------------------------
/src/web-vue/src/store/mutations/newPolicy.js:
--------------------------------------------------------------------------------
1 | function newPolicy(state, payload) {
2 | const existing = state.policies.find(p => p.name === payload.name);
3 | if (existing) {
4 | throw new Error('A policy with this name already exists');
5 | } else {
6 | state.isDirty = true
7 | const name = payload.name;
8 | const dbUserRoles = state.roleSet.dbUserRoles;
9 |
10 | const newPolicy = {
11 | id: new Date().getTime() * 10000 + 621355968000000000,
12 | name: name,
13 | policyHeaderTemplate: state.policyHeaderTemplate,
14 | policyFooterTemplate: state.policyFooterTemplate,
15 | enableRls: false,
16 | columnExclusionOverrides: {
17 | insert: [],
18 | update: [],
19 | },
20 | columnExclusions: {
21 | insert: {},
22 | update: {},
23 | },
24 | roleGrants: dbUserRoles.reduce((all, projectRole) => {
25 | return {
26 | ...all,
27 | [projectRole.roleName]: state.defaultRoleGrants,
28 | };
29 | }, {}),
30 | rlsQualifiers: dbUserRoles.reduce((all, projectRole) => {
31 | return {
32 | ...all,
33 | [projectRole.roleName]: state.defaultRlsQualifiers,
34 | };
35 | }, {}),
36 | };
37 |
38 | state.policies = [...state.policies, ...[newPolicy]].sort(function(a, b) {
39 | return a.id < b.id;
40 | });
41 | }
42 | }
43 |
44 | export default newPolicy;
45 |
--------------------------------------------------------------------------------
/src/web-vue/src/store/mutations/projectRoles.js:
--------------------------------------------------------------------------------
1 | function dbUserRoles(state, payload) {
2 | state.isDirty = true
3 | const dbUserRoles = (state.roleSet.dbUserRoles = payload.dbUserRoles.map(role => {
4 | return {
5 | ...role,
6 | applicableRoles: role.applicableRoles || [],
7 | };
8 | }));
9 |
10 | state.policies = state.policies.map(policy => {
11 | return {
12 | ...policy,
13 | roleGrants: dbUserRoles.reduce((all, projectRole) => {
14 | // const existing = policy.roleGrants[projectRole.name]
15 |
16 | return {
17 | ...all,
18 | [projectRole.roleName]:
19 | policy.roleGrants[projectRole.name] || state.defaultRoleGrants,
20 | };
21 | }, {}),
22 | rlsQualifiers: dbUserRoles.reduce((all, projectRole) => {
23 | return {
24 | ...all,
25 | [projectRole.roleName]:
26 | policy.rlsQualifiers[projectRole.name] ||
27 | state.defaultRlsQualifiers,
28 | };
29 | }, {}),
30 | };
31 | });
32 |
33 | state.functionPolicies = state.functionPolicies.map(policy => {
34 | return {
35 | ...policy,
36 | roleFunctionGrants: dbUserRoles.reduce((all, projectRole) => {
37 | return {
38 | ...all,
39 | [projectRole.roleName]:
40 | policy.roleFunctionGrants[projectRole.name] ||
41 | state.defaultFunctionRoleGrants,
42 | };
43 | }, {}),
44 | };
45 | });
46 |
47 | const projectRoleNames = dbUserRoles.map(pr => pr.roleName)
48 |
49 | state.ignoredRoles = state.ignoredRoles.filter(ir => projectRoleNames.indexOf(ir.roleName) === -1)
50 | }
51 |
52 | export default dbUserRoles;
53 |
--------------------------------------------------------------------------------
/src/web-vue/src/store/mutations/renameTablePolicy.js:
--------------------------------------------------------------------------------
1 | function renameTablePolicy(state, payload) {
2 | state.isDirty = true
3 | const policy = state.policies.find(p => p.id === payload.policyDefinitionId)
4 | const others = state.policies.filter(p => p.id !== payload.policyDefinitionId)
5 |
6 | state.policies = [
7 | ...others,
8 | {
9 | ...policy,
10 | name: payload.name
11 | }
12 | ]
13 | }
14 |
15 | export default renameTablePolicy;
16 |
--------------------------------------------------------------------------------
/src/web-vue/src/store/mutations/resetDefaultState.js:
--------------------------------------------------------------------------------
1 | import defaultState from '../defaultState';
2 |
3 | function resetDefaultState(state, pgdbirc) {
4 | Object.keys(defaultState)
5 | .forEach(key => {
6 | state[key] = (pgdbirc[key] || defaultState[key]);
7 | });
8 | state.isDirty = false
9 | }
10 |
11 | export default resetDefaultState;
12 |
--------------------------------------------------------------------------------
/src/web-vue/src/store/mutations/saveFunctionPolicy.js:
--------------------------------------------------------------------------------
1 | function saveFunctionPolicy(state, payload) {
2 | state.isDirty = true
3 | const functionPolicies = state.functionPolicies.filter(
4 | p => p.id !== payload.policy.id,
5 | );
6 | state.functionPolicies = [...functionPolicies, ...[payload.policy]].sort(
7 | (a, b) => {
8 | return a.id - b.id;
9 | },
10 | );
11 | }
12 |
13 | export default saveFunctionPolicy;
14 |
--------------------------------------------------------------------------------
/src/web-vue/src/store/mutations/savePgLintResult.js:
--------------------------------------------------------------------------------
1 | function savePgLintResult(state, payload) {
2 | state.pgLintResults = [...state.pgLintResults, payload]
3 | }
4 |
5 | export default savePgLintResult
--------------------------------------------------------------------------------
/src/web-vue/src/store/mutations/savePolicy.js:
--------------------------------------------------------------------------------
1 | function savePolicy(state, payload) {
2 | state.isDirty = true
3 | const policies = state.policies.filter(p => p.name !== payload.policy.name);
4 | state.policies = [...policies, ...[payload.policy]].sort((a, b) => {
5 | return a.id - b.id;
6 | });
7 | }
8 |
9 | export default savePolicy;
10 |
--------------------------------------------------------------------------------
/src/web-vue/src/store/mutations/selectedRoleFamilies.js:
--------------------------------------------------------------------------------
1 | function selectedRoleFamilies(state, payload) {
2 | state.isDirty = true
3 | state.selectedRoleFamilies = payload.selectedRoleFamilies;
4 | }
5 |
6 | export default selectedRoleFamilies;
7 |
--------------------------------------------------------------------------------
/src/web-vue/src/store/mutations/setAllRoleSets.js:
--------------------------------------------------------------------------------
1 | function setAllRoleSets(state, payload) {
2 | state.isDirty = true
3 | state.allRoleSets = payload
4 | }
5 |
6 | export default setAllRoleSets;
7 |
--------------------------------------------------------------------------------
/src/web-vue/src/store/mutations/setEnabledRoles.js:
--------------------------------------------------------------------------------
1 | function setEnabledRoles(state, payload) {
2 | state.isDirty = true
3 | state.enabledRoles = payload.enabledRoles
4 | }
5 |
6 | export default setEnabledRoles;
7 |
--------------------------------------------------------------------------------
/src/web-vue/src/store/mutations/setExistingRlsPolicies.js:
--------------------------------------------------------------------------------
1 | function setExistingRlsPolicies(state, payload) {
2 | state.existingRlsPolicies = payload
3 | }
4 |
5 | export default setExistingRlsPolicies
--------------------------------------------------------------------------------
/src/web-vue/src/store/mutations/setPgdbiOptions.js:
--------------------------------------------------------------------------------
1 | function setPgdbiOptions(state, payload) {
2 | state.isDirty = true
3 | state.pgdbiOptions = payload.pgdbiOptions
4 | }
5 |
6 | export default setPgdbiOptions;
7 |
--------------------------------------------------------------------------------
/src/web-vue/src/store/mutations/setProjectRoleSet.js:
--------------------------------------------------------------------------------
1 | function setProjectRoleSet(state, payload) {
2 | state.isDirty = true
3 | const roleSet = state.allRoleSets.find(rs => rs.name === payload)
4 | state.roleSet = roleSet
5 | }
6 |
7 | export default setProjectRoleSet;
8 |
--------------------------------------------------------------------------------
/src/web-vue/src/store/mutations/toggleIgnoreRole.js:
--------------------------------------------------------------------------------
1 | function toggleIgnoreRole(state, payload) {
2 | state.isDirty = true
3 | const isIgnored = state.ignoredRoles.find(i => i.roleName === payload.role.roleName)
4 |
5 | state.ignoredRoles = isIgnored ? state.ignoredRoles.filter(i => i.roleName !== payload.role.roleName) : [...state.ignoredRoles, payload.role]
6 | }
7 |
8 | export default toggleIgnoreRole;
9 |
--------------------------------------------------------------------------------
/src/web-vue/src/store/mutations/toggleIndexForDrop.js:
--------------------------------------------------------------------------------
1 | import evaluateAll from './evaluate/evaluateAll'
2 |
3 | function toggleIndexForDrop(state, payload) {
4 | if (payload.value === true && !state.indicesToDrop[payload.item.id]) { // add the index
5 | const indexId = payload.item.id
6 | state.indicesToDrop = {
7 | ...state.indicesToDrop,
8 | [indexId]: payload.item
9 | }
10 | } else if (payload.value === false) {
11 | state.indicesToDrop = Object.keys(state.indicesToDrop)
12 | .filter(k => k !== payload.item.id)
13 | .reduce(
14 | (all, k) => {
15 | return {
16 | ...all,
17 | [k]: state.indicesToDrop[k]
18 | }
19 | }, {}
20 | )
21 | }
22 |
23 | evaluateAll(state)
24 | }
25 |
26 | export default toggleIndexForDrop;
27 |
--------------------------------------------------------------------------------
/src/web-vue/src/store/mutations/updateDefaultRlsUsing.js:
--------------------------------------------------------------------------------
1 | function updateDefaultRlsUsing(state, payload) {
2 | state.isDirty = true
3 | state.defaultRlsUsing = payload.defaultRlsUsing;
4 | }
5 |
6 | module.exports = updateDefaultRlsUsing;
7 |
--------------------------------------------------------------------------------
/src/web-vue/src/store/mutations/updateTablePolicyTemplate.js:
--------------------------------------------------------------------------------
1 | function updateTablePolicyTemplate(state, payload) {
2 | state.isDirty = true
3 | state.tablePolicyTemplate = payload.tablePolicyTemplate;
4 | }
5 |
6 | export default updateTablePolicyTemplate;
7 |
--------------------------------------------------------------------------------
/src/web-vue/src/store/store.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue';
2 | import Vuex from 'vuex';
3 | import createPersistedState from 'vuex-persistedstate';
4 | import mutations from './mutations/mutations';
5 | import actions from './actions';
6 | import defaultState from './defaultState';
7 |
8 | Vue.use(Vuex);
9 |
10 | export default new Vuex.Store({
11 | plugins: [createPersistedState()],
12 | state: defaultState,
13 | mutations: mutations,
14 | actions: actions,
15 | });
16 |
--------------------------------------------------------------------------------
/src/web-vue/src/store/templates/policyFooterTemplate.js:
--------------------------------------------------------------------------------
1 | export default `
2 |
3 | --=================== END: {{schemaName}}.{{tableName}} ===================
4 | `;
5 |
--------------------------------------------------------------------------------
/src/web-vue/src/store/templates/policyHeaderTemplate.js:
--------------------------------------------------------------------------------
1 | module.exports = `
2 | --=================== BEGIN: {{schemaName}}.{{tableName}} ===================
3 |
4 | `;
5 |
--------------------------------------------------------------------------------
/src/web-vue/src/store/templates/roleTableGrantTemplate.js:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/graphile-contrib/pgdbi/47d3b0454fde69836e99a388f88b00a8463f4285/src/web-vue/src/store/templates/roleTableGrantTemplate.js
--------------------------------------------------------------------------------
/src/web-vue/src/views/About.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
This is an about page
4 |
5 |
6 |
--------------------------------------------------------------------------------
/src/web-vue/src/views/ForeignKeyIndexView.vue:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
10 |
27 |
28 |
31 |
--------------------------------------------------------------------------------
/src/web-vue/src/views/Home.vue:
--------------------------------------------------------------------------------
1 |
2 |
7 | PGDBI
8 | postgraphile-db-inspector
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
37 |
38 |
41 |
--------------------------------------------------------------------------------
/src/web-vue/src/views/Initialize.vue:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
13 |
17 | Initialize Project
18 |
19 |
22 |
23 |
24 |
25 |
26 |
30 | Load From Disk
31 |
32 |
35 |
36 | Load From Disk
37 |
38 |
39 |
40 |
41 |
42 |
43 |
84 |
85 |
88 |
--------------------------------------------------------------------------------
/src/web-vue/src/views/RoleManagerView.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 | Role Manager
8 |
12 |
16 | Roles
17 |
18 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
35 | Create Roles Script
36 |
37 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
72 |
73 |
76 |
--------------------------------------------------------------------------------
/src/web-vue/src/views/SearchView.vue:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
10 |
31 |
32 |
35 |
--------------------------------------------------------------------------------
/src/web-vue/src/views/SqitchView.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
Sqitch
4 |
5 |
6 |
--------------------------------------------------------------------------------
/src/web-vue/src/views/TableSecurityProfileDefinitionView.vue:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
11 |
15 | Security Profile Definition
16 |
17 |
20 |
21 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
57 |
58 |
61 |
--------------------------------------------------------------------------------
/src/web-vue/src/views/TableSecurityProfileView.vue:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
11 |
15 | Security Profile
16 |
17 |
20 |
21 | {{ table.id }}
22 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
63 |
64 |
67 |
--------------------------------------------------------------------------------
/src/web-vue/src/views/WorkerView.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
Graphile Worker
4 |
5 |
6 |
--------------------------------------------------------------------------------
/src/web-vue/test/blah.spec.js:
--------------------------------------------------------------------------------
1 | // mutations.spec.js
2 | import { expect } from 'chai';
3 | import { mutations } from './store';
4 |
5 | // destructure assign `mutations`
6 | const { resetDefaultState } = mutations;
7 |
8 | describe('resetDefaultState', () => {
9 | const state = {};
10 |
11 | resetDefaultState(state);
12 |
13 | expect(state).to.be.an('Object');
14 | });
15 |
--------------------------------------------------------------------------------
/src/web-vue/tsconfigs.json:
--------------------------------------------------------------------------------
1 | // tsconfig.json
2 | {
3 | "compilerOptions": {
4 | // this aligns with Vue's browser support
5 | "target": "es5",
6 | // this enables stricter inference for data properties on `this`
7 | "strict": true,
8 | // if using webpack 2+ or rollup, to leverage tree shaking:
9 | "module": "es2015",
10 | "moduleResolution": "node",
11 | "allowJs": true
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/web-vue/vue.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | publicPath: '/pgdbi/',
3 | pluginOptions: {
4 | apollo: {
5 | enableMocks: false,
6 | enableEngine: false,
7 | },
8 | },
9 | devServer: {
10 | proxy: {
11 | '/pgdbi/': {
12 | target: 'http://localhost:5099',
13 | },
14 | },
15 | },
16 | configureWebpack: {
17 | devtool: 'source-map',
18 | },
19 | };
20 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "outDir": "./dist",
4 | // Target latest version of ECMAScript.
5 | "target": "esnext",
6 | // Search under node_modules for non-relative imports.
7 | "moduleResolution": "node",
8 | // Process & infer types from .js files.
9 | "allowJs": true,
10 | // Don't emit; allow Babel to transform files.
11 | "noEmit": true,
12 | // Enable strictest settings like strictNullChecks & noImplicitAny.
13 | "strict": true,
14 | // Disallow features that require cross-file information for emit.
15 | "isolatedModules": true,
16 | // Import non-ES modules as default imports.
17 | "esModuleInterop": true
18 | },
19 | "include": [
20 | "./src/**/*"
21 | ]
22 | }
--------------------------------------------------------------------------------