mirror of
https://github.com/pgadmin-org/pgadmin4.git
synced 2025-02-25 18:55:31 -06:00
Grant wizard.
This commit is contained in:
committed by
Dave Page
parent
6e237d16ca
commit
40c592a988
143
web/pgadmin/browser/static/css/wizard.css
Normal file
143
web/pgadmin/browser/static/css/wizard.css
Normal file
@@ -0,0 +1,143 @@
|
|||||||
|
/** CSS for Wizard **/
|
||||||
|
.pgadmin_grant_wizard_body .ajs-content {
|
||||||
|
padding-top: 0px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wizard-header {
|
||||||
|
background: #428bca;
|
||||||
|
padding-left: 15px;
|
||||||
|
padding-bottom: 7px;
|
||||||
|
color: #fff;
|
||||||
|
font-size: 18px;
|
||||||
|
height: 76px;
|
||||||
|
line-height: 76px;
|
||||||
|
border-radius: 6px 6px 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wizard-header h3 {
|
||||||
|
font-size: 18px;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wizard_dlg {
|
||||||
|
float: left;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grant_wizard_container {
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grant_wizard_container .pgadmin-wizard {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grant_wizard_container .wizard-content {
|
||||||
|
position: relative;
|
||||||
|
padding: 0;
|
||||||
|
height: 78%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grant_wizard_container .wizard-right-panel {
|
||||||
|
overflow-y: auto;
|
||||||
|
height: 100%;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grant_wizard_container .wizard-left-panel {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
display: flex;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grant_wizard_container .wizard-left-panel img {
|
||||||
|
width: 140px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grant_wizard_container .wizard-right-panel_content {
|
||||||
|
height: 60%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grant_wizard_container {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Wizard Footer CSS */
|
||||||
|
.grant_wizard_container .footer {
|
||||||
|
position: absolute;
|
||||||
|
background: #fff;
|
||||||
|
border-top: 1px solid #ccc;
|
||||||
|
bottom: 0px;
|
||||||
|
height: 62px;
|
||||||
|
right: 0px;
|
||||||
|
padding-top: 22px;
|
||||||
|
border-radius: 0 0 6px 6px;
|
||||||
|
z-index: 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Wizard Button CSS */
|
||||||
|
.grant_wizard_container .wizard-buttons {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grant_wizard_container .wizard-buttons button {
|
||||||
|
float: left;
|
||||||
|
padding: 7px 15.2px;
|
||||||
|
font-size: 14px;
|
||||||
|
margin: 0px 5px 0 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grant_wizard_container .wizard-buttons button.wizard-next i.fa {
|
||||||
|
padding-left: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grant_wizard_container .wizard-buttons button.wizard-back i.fa,
|
||||||
|
.grant_wizard_container .wizard-buttons button.wizard-cancel i.fa {
|
||||||
|
padding-right: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grant_wizard_container .wizard-buttons .wizard-finish {
|
||||||
|
margin-right: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Wizard Status bar CSS */
|
||||||
|
.grant_wizard_container .wizard-description {
|
||||||
|
padding: 1.7em 0.1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Error message css */
|
||||||
|
.grant_wizard_container .error_msg_div {
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
bottom: 55px;
|
||||||
|
background: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grant_wizard_container .error_msg_div p {
|
||||||
|
background: #fff;
|
||||||
|
color: #b92c28;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* In wizard select2 dropdown doesn't
|
||||||
|
* popup because z-index of alertify
|
||||||
|
* wizard is greater than the z-index
|
||||||
|
* of select2 dropdown. To make select2
|
||||||
|
* visible, set z-index of select2
|
||||||
|
* higher value than wizard's
|
||||||
|
*/
|
||||||
|
.select2-container--open {
|
||||||
|
z-index: 10000;
|
||||||
|
}
|
@@ -280,7 +280,8 @@ function($, _, pgAdmin, Backbone, Backform, Alertify, Node) {
|
|||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
while(p) {
|
// check if p is not empty
|
||||||
|
while(p && p.length > 0) {
|
||||||
top = p.get(0).offsetTop + p.height();
|
top = p.get(0).offsetTop + p.height();
|
||||||
p = p.parent();
|
p = p.parent();
|
||||||
if (hasScrollbar(p)) {
|
if (hasScrollbar(p)) {
|
||||||
|
233
web/pgadmin/browser/static/js/wizard.js
Normal file
233
web/pgadmin/browser/static/js/wizard.js
Normal file
@@ -0,0 +1,233 @@
|
|||||||
|
define(
|
||||||
|
['underscore', 'backbone', 'pgadmin', 'pgadmin.browser'],
|
||||||
|
function(_, Backbone, pgAdmin, pgBrowser) {
|
||||||
|
|
||||||
|
pgBrowser = pgBrowser || pgAdmin.Browser || {};
|
||||||
|
|
||||||
|
/* Wizard individual Page Model */
|
||||||
|
var WizardPage = pgBrowser.WizardPage = Backbone.Model.extend({
|
||||||
|
defaults: {
|
||||||
|
id: undefined, /* Id */
|
||||||
|
page_title: undefined, /* Page Title */
|
||||||
|
view: undefined, /* A Backbone View */
|
||||||
|
html: undefined, /* HTML tags to be rendered */
|
||||||
|
image: undefined, /* Left hand side image */
|
||||||
|
disable_prev: false, /* Previous Button Flag */
|
||||||
|
disable_next: false, /* Next Button Flag */
|
||||||
|
disable_cancel: false, /* Cancel Button Flag */
|
||||||
|
show_progress_bar: '',
|
||||||
|
/* Callback for OnLoad */
|
||||||
|
onLoad: function() {
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
/* Callback for before Next */
|
||||||
|
beforeNext: function() {
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
onNext: function(){},
|
||||||
|
onBefore: function() {},
|
||||||
|
/* Callback for before Previous */
|
||||||
|
beforePrev: function() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var Wizard = pgBrowser.Wizard = Backbone.View.extend({
|
||||||
|
options: {
|
||||||
|
title: 'Wizard', /* Main Wizard Title */
|
||||||
|
image: 'left_panel.png', /* TODO:: We can use default image here */
|
||||||
|
curr_page: 0, /* Current Page to Load */
|
||||||
|
disable_next: false,
|
||||||
|
disable_prev: false,
|
||||||
|
disable_finish: false,
|
||||||
|
disable_cancel: false,
|
||||||
|
height: 400,
|
||||||
|
width: 650,
|
||||||
|
show_left_panel: true
|
||||||
|
},
|
||||||
|
tmpl: _.template(
|
||||||
|
" <div class='pgadmin-wizard' style='height: <%= this.options.height %>px;"
|
||||||
|
+ " width: <%= this.options.width %>px'>"
|
||||||
|
+ " <div class='wizard-header wizard-badge'>"
|
||||||
|
+ " <div class='row'>"
|
||||||
|
+ " <div class='col-sm-9'>"
|
||||||
|
+ " <h3><span id='main-title'><%= this.options.title %></span> -"
|
||||||
|
+ " <span id='step-title'><%= page_title %></span></h3>"
|
||||||
|
+ " </div>"
|
||||||
|
+ " </div>"
|
||||||
|
+ " </div>"
|
||||||
|
+ " <div class='wizard-content col-sm-12'>"
|
||||||
|
+ " <% if(this.options.show_left_panel) { %>"
|
||||||
|
+ " <div class='col-sm-3 wizard-left-panel'>"
|
||||||
|
+ " <img src='<%= this.options.image %>'></div>"
|
||||||
|
+ " <% } %>"
|
||||||
|
+ " <div class='col-sm-<% if(this.options.show_left_panel){ %>9<% }"
|
||||||
|
+ " else { %>12<% } %> wizard-right-panel'>"
|
||||||
|
+ " <% if( typeof show_description != 'undefined'){ %>"
|
||||||
|
+ " <div class='wizard-description'>"
|
||||||
|
+ " <%= show_description %>"
|
||||||
|
+ " </div>"
|
||||||
|
+ " <% } %>"
|
||||||
|
+ " <div class='wizard-right-panel_content'>"
|
||||||
|
+ " </div>"
|
||||||
|
+ " </div>"
|
||||||
|
+ " </div>"
|
||||||
|
+ " <div class='col-sm-12 error_msg_div'>"
|
||||||
|
+ " <p></p>"
|
||||||
|
+ " </div>"
|
||||||
|
+ " <div class='footer col-sm-12'>"
|
||||||
|
+ " <div class='row'>"
|
||||||
|
+ " <div class='col-sm-4 wizard-progress-bar'>"
|
||||||
|
+ " <p><% if(show_progress_bar){ %><%= show_progress_bar %><% } %></p>"
|
||||||
|
+ " </div>"
|
||||||
|
+ " <div class='col-sm-8'>"
|
||||||
|
+ " <div class='wizard-buttons'>"
|
||||||
|
+ " <button class='btn btn-primary wizard-back' <%=this.options.disable_prev ? 'disabled' : ''%>>"
|
||||||
|
+ " <i class='fa fa-backward'></i>Back</button>"
|
||||||
|
+ " <button class='btn btn-primary wizard-next' <%=this.options.disable_next ? 'disabled' : ''%>>Next"
|
||||||
|
+ " <i class='fa fa-forward'></i></button>"
|
||||||
|
+ " <button class='btn btn-danger wizard-cancel' <%=this.options.disable_cancel ? 'disabled' : ''%>>"
|
||||||
|
+ " <i class='fa fa-lg fa-close'></i>Cancel</button>"
|
||||||
|
+ " <button class='btn btn-primary wizard-finish' <%=this.options.disable_finish ? 'disabled' : ''%>>"
|
||||||
|
+ " Finish</button>"
|
||||||
|
+ " </div>"
|
||||||
|
+ " </div>"
|
||||||
|
+ " </div>"
|
||||||
|
+ " </div>"
|
||||||
|
+ " </div>"),
|
||||||
|
events: {
|
||||||
|
"click button.wizard-next" : "nextPage",
|
||||||
|
"click button.wizard-back" : "prevPage",
|
||||||
|
"click button.wizard-cancel" : "onCancel",
|
||||||
|
"click button.wizard-finish" : "finishWizard",
|
||||||
|
},
|
||||||
|
initialize: function(options) {
|
||||||
|
this.options = _.extend({}, this.options, options.options);
|
||||||
|
this.currPage = this.collection.at(this.options.curr_page).toJSON();
|
||||||
|
},
|
||||||
|
render: function() {
|
||||||
|
var data = this.currPage;
|
||||||
|
|
||||||
|
/* Check Status of the buttons */
|
||||||
|
this.options.disable_next = (this.options.disable_next ? true : this.evalASFunc(this.currPage.disable_next));
|
||||||
|
this.options.disable_prev = (this.options.disable_prev ? true : this.evalASFunc(this.currPage.disable_prev));
|
||||||
|
this.options.disable_cancel = (this.currPage.canCancel ? true : this.evalASFunc(this.currPage.disable_cancel));
|
||||||
|
|
||||||
|
that = this;
|
||||||
|
|
||||||
|
/* HTML Content */
|
||||||
|
if (data.html) { data.content = data.html; }
|
||||||
|
/* Backbone View */
|
||||||
|
else if (data.view) { data.content = data.view.render().el;}
|
||||||
|
|
||||||
|
$(this.el).html(this.tmpl(data));
|
||||||
|
$(this.el).find(".wizard-right-panel_content").html(data.content);
|
||||||
|
|
||||||
|
/* OnLoad Callback */
|
||||||
|
this.onLoad();
|
||||||
|
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
nextPage: function() {
|
||||||
|
this.options.curr_page.el = this.$el;
|
||||||
|
if (!this.beforeNext()) { return false; }
|
||||||
|
|
||||||
|
page_id = this.onNext();
|
||||||
|
|
||||||
|
if (page_id ) {
|
||||||
|
this.currPage = this.collection.get(page_id).toJSON();
|
||||||
|
this.options.curr_page = this.collection.indexOf(this.collection.get(page_id));
|
||||||
|
}
|
||||||
|
else if (this.options.curr_page < (this.collection.length-1)) {
|
||||||
|
this.options.curr_page = this.options.curr_page + 1;
|
||||||
|
this.currPage = this.collection.at(this.options.curr_page).toJSON();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.enableDisableNext();
|
||||||
|
this.enableDisablePrev();
|
||||||
|
|
||||||
|
return this.render();
|
||||||
|
},
|
||||||
|
prevPage: function() {
|
||||||
|
if (!this.beforePrev()) { return false; }
|
||||||
|
|
||||||
|
page_id = this.onPrev();
|
||||||
|
|
||||||
|
if (page_id){
|
||||||
|
this.currPage = this.collection.get(page_id).toJSON();
|
||||||
|
this.options.curr_page = this.collection.indexOf(this.collection.get(page_id));
|
||||||
|
}
|
||||||
|
else if (this.options.curr_page > 0) {
|
||||||
|
this.options.curr_page = this.options.curr_page - 1;
|
||||||
|
this.currPage = this.collection.at(this.options.curr_page).toJSON();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.enableDisableNext();
|
||||||
|
this.enableDisablePrev();
|
||||||
|
|
||||||
|
return this.render();
|
||||||
|
},
|
||||||
|
finishWizard: function() {
|
||||||
|
this.onFinish();
|
||||||
|
this.remove(); // Remove view from DOM
|
||||||
|
this.unbind(); // Unbind all local event bindings
|
||||||
|
delete this.$el; // Delete the jQuery wrapped object variable
|
||||||
|
delete this.el; // Delete the variable reference to this node
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
enableDisableNext: function(disable) {
|
||||||
|
if (typeof(disable) != 'undefined') {
|
||||||
|
this.options.disable_next = disable;
|
||||||
|
}
|
||||||
|
else if (this.options.curr_page >= (this.collection.length-1)) {
|
||||||
|
this.options.disable_next = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.options.disable_next = false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
enableDisablePrev: function(disable) {
|
||||||
|
if (typeof(disable) != 'undefined') {
|
||||||
|
this.options.disable_prev = disable;
|
||||||
|
}
|
||||||
|
else if (this.options.curr_page <= 0) {
|
||||||
|
this.options.disable_prev = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.options.disable_prev = false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
beforeNext: function(){
|
||||||
|
return this.evalASFunc(this.currPage.beforeNext);
|
||||||
|
},
|
||||||
|
beforePrev: function(){
|
||||||
|
return this.evalASFunc(this.currPage.beforePrev);
|
||||||
|
},
|
||||||
|
onPrev: function(){
|
||||||
|
return this.evalASFunc(this.currPage.onPrev);
|
||||||
|
},
|
||||||
|
onNext: function(){
|
||||||
|
return this.evalASFunc(this.currPage.onNext);
|
||||||
|
},
|
||||||
|
onLoad: function() {
|
||||||
|
return this.evalASFunc(this.currPage.onLoad);
|
||||||
|
},
|
||||||
|
onFinish: function() {
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
onCancel: function() {
|
||||||
|
this.$el.remove();
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
evalASFunc: function(func, ctx) {
|
||||||
|
var self = this;
|
||||||
|
ctx = ctx || self.currPage;
|
||||||
|
|
||||||
|
return (_.isFunction(func) ? func.apply(ctx, [self]) : func);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return pgBrowser;
|
||||||
|
|
||||||
|
});
|
@@ -45,6 +45,10 @@ body {
|
|||||||
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAACXBIWXMAAArrAAAK6wGCiw1aAAAAVElEQVQY05WQuQ0AMQgEB8lN0H9vdhnj4B7ZJwfcJkjsImBCpaIGMMYQIDNjNbe+Su9d1bsee5yM0+AbXMPfkHrdWNKv1ZVn2oJiw5OZ8eABiCrwCW8QwRIof5qAAAAAAElFTkSuQmCC) !important;
|
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAACXBIWXMAAArrAAAK6wGCiw1aAAAAVElEQVQY05WQuQ0AMQgEB8lN0H9vdhnj4B7ZJwfcJkjsImBCpaIGMMYQIDNjNbe+Su9d1bsee5yM0+AbXMPfkHrdWNKv1ZVn2oJiw5OZ8eABiCrwCW8QwRIof5qAAAAAAElFTkSuQmCC) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.alertify .ajs-modal {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
/* iFrames should have no border */
|
/* iFrames should have no border */
|
||||||
iframe {
|
iframe {
|
||||||
border-width: 0;
|
border-width: 0;
|
||||||
|
461
web/pgadmin/tools/grant_wizard/__init__.py
Normal file
461
web/pgadmin/tools/grant_wizard/__init__.py
Normal file
@@ -0,0 +1,461 @@
|
|||||||
|
##########################################################################
|
||||||
|
#
|
||||||
|
# pgAdmin 4 - PostgreSQL Tools
|
||||||
|
#
|
||||||
|
# Copyright (C) 2013 - 2016, The pgAdmin Development Team
|
||||||
|
# This software is released under the PostgreSQL Licence
|
||||||
|
#
|
||||||
|
##########################################################################
|
||||||
|
|
||||||
|
"""Implements Grant Wizard"""
|
||||||
|
|
||||||
|
import simplejson as json
|
||||||
|
from flask import render_template, request, current_app
|
||||||
|
from flask.ext.babel import gettext
|
||||||
|
from pgadmin.utils.ajax import make_response as ajax_response, \
|
||||||
|
make_json_response, internal_server_error
|
||||||
|
from pgadmin.utils.driver import get_driver
|
||||||
|
from config import PG_DEFAULT_DRIVER
|
||||||
|
from pgadmin.browser.server_groups.servers.utils import parse_priv_to_db
|
||||||
|
from pgadmin.utils import PgAdminModule
|
||||||
|
from flask import Response, url_for
|
||||||
|
from flask.ext.security import login_required
|
||||||
|
from urllib import unquote
|
||||||
|
from pgadmin.utils.ajax import precondition_required
|
||||||
|
from functools import wraps
|
||||||
|
from pgadmin.utils.preferences import Preferences
|
||||||
|
|
||||||
|
# set template path for sql scripts
|
||||||
|
MODULE_NAME = 'grant_wizard'
|
||||||
|
server_info = {}
|
||||||
|
|
||||||
|
|
||||||
|
class GrantWizardModule(PgAdminModule):
|
||||||
|
"""
|
||||||
|
class GrantWizardModule(Object):
|
||||||
|
|
||||||
|
It is a wizard which inherits PgAdminModule
|
||||||
|
class and define methods to load its own
|
||||||
|
javascript file.
|
||||||
|
|
||||||
|
LABEL = gettext('Browser')
|
||||||
|
"""
|
||||||
|
def get_own_stylesheets(self):
|
||||||
|
"""
|
||||||
|
Returns:
|
||||||
|
list: the stylesheets used by this module.
|
||||||
|
"""
|
||||||
|
stylesheets = [
|
||||||
|
url_for('browser.static', filename='css/wizard.css'),
|
||||||
|
url_for('grant_wizard.static', filename='css/grant_wizard.css')
|
||||||
|
]
|
||||||
|
return stylesheets
|
||||||
|
|
||||||
|
def get_own_javascripts(self):
|
||||||
|
""""
|
||||||
|
Returns:
|
||||||
|
list: js files used by this module
|
||||||
|
"""
|
||||||
|
scripts = []
|
||||||
|
scripts.append({
|
||||||
|
'name': 'pgadmin.tools.grant_wizard',
|
||||||
|
'path': url_for('grant_wizard.index') + 'grant_wizard',
|
||||||
|
'when': None
|
||||||
|
})
|
||||||
|
scripts.append({
|
||||||
|
'name': 'pgadmin.browser.wizard',
|
||||||
|
'path': url_for('browser.static', filename='js/wizard'),
|
||||||
|
'when': None
|
||||||
|
})
|
||||||
|
return scripts
|
||||||
|
|
||||||
|
def show_system_objects(self):
|
||||||
|
"""
|
||||||
|
return system preference objects
|
||||||
|
"""
|
||||||
|
return self.pref_show_system_objects
|
||||||
|
|
||||||
|
def register_preferences(self):
|
||||||
|
"""
|
||||||
|
Get show_system_objects preference
|
||||||
|
"""
|
||||||
|
self.browser_preference = Preferences.module('browser')
|
||||||
|
self.pref_show_system_objects = self.browser_preference.preference(
|
||||||
|
'show_system_objects'
|
||||||
|
)
|
||||||
|
|
||||||
|
# Create blueprint for GrantWizardModule class
|
||||||
|
blueprint = GrantWizardModule(
|
||||||
|
MODULE_NAME, __name__, static_url_path='')
|
||||||
|
|
||||||
|
|
||||||
|
def check_precondition(f):
|
||||||
|
"""
|
||||||
|
This function will behave as a decorator which will checks
|
||||||
|
database connection before running view, it will also attaches
|
||||||
|
manager,conn & template_path properties to instance of the method.
|
||||||
|
|
||||||
|
Assumptions:
|
||||||
|
This function will always be used as decorator of a class method.
|
||||||
|
"""
|
||||||
|
@wraps(f)
|
||||||
|
def wrap(*args, **kwargs):
|
||||||
|
# Here args[0] will hold self & kwargs will hold gid,sid,did
|
||||||
|
|
||||||
|
server_info.clear()
|
||||||
|
server_info['manager'] = get_driver(
|
||||||
|
PG_DEFAULT_DRIVER).connection_manager(
|
||||||
|
kwargs['sid']
|
||||||
|
)
|
||||||
|
server_info['conn'] = server_info['manager'].connection(
|
||||||
|
did=kwargs['did']
|
||||||
|
)
|
||||||
|
# If DB not connected then return error to browser
|
||||||
|
if not server_info['conn'].connected():
|
||||||
|
return precondition_required(
|
||||||
|
gettext("Connection to the server has been lost!")
|
||||||
|
)
|
||||||
|
|
||||||
|
# Set template path for sql scripts
|
||||||
|
server_info['server_type'] = server_info['manager'].server_type
|
||||||
|
server_info['version'] = server_info['manager'].version
|
||||||
|
if server_info['server_type'] == 'pg':
|
||||||
|
server_info['template_path'] = 'grant_wizard/pg/9.1_plus'
|
||||||
|
elif server_info['server_type'] == 'ppas':
|
||||||
|
server_info['template_path'] = 'grant_wizard/ppas/9.1_plus'
|
||||||
|
|
||||||
|
return f(*args, **kwargs)
|
||||||
|
|
||||||
|
return wrap
|
||||||
|
|
||||||
|
|
||||||
|
@blueprint.route("/")
|
||||||
|
@login_required
|
||||||
|
def index():
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@blueprint.route("/grant_wizard.js")
|
||||||
|
@login_required
|
||||||
|
def script():
|
||||||
|
"""render own javascript"""
|
||||||
|
return Response(response=render_template(
|
||||||
|
"grant_wizard/js/grant_wizard.js", _=gettext),
|
||||||
|
status=200,
|
||||||
|
mimetype="application/javascript")
|
||||||
|
|
||||||
|
|
||||||
|
@blueprint.route(
|
||||||
|
'/acl/<int:gid>/<int:sid>/<int:did>/', methods=('GET', 'POST'))
|
||||||
|
@login_required
|
||||||
|
@check_precondition
|
||||||
|
def acl_list(gid, sid, did):
|
||||||
|
"""render list of acls"""
|
||||||
|
server_prop = server_info
|
||||||
|
return Response(response=render_template(
|
||||||
|
server_prop['template_path']+"/acl.json", _=gettext),
|
||||||
|
status=200,
|
||||||
|
mimetype="application/json")
|
||||||
|
|
||||||
|
|
||||||
|
@blueprint.route(
|
||||||
|
'/properties/<int:gid>/<int:sid>/<int:did>'
|
||||||
|
'/<int:node_id>/<node_type>/',
|
||||||
|
methods=('GET', 'POST'))
|
||||||
|
@login_required
|
||||||
|
@check_precondition
|
||||||
|
def properties(gid, sid, did, node_id, node_type):
|
||||||
|
"""It fetches the properties of object types
|
||||||
|
and render into selection page of wizard
|
||||||
|
"""
|
||||||
|
|
||||||
|
# unquote encoded url parameter
|
||||||
|
node_type = unquote(node_type)
|
||||||
|
|
||||||
|
server_prop = server_info
|
||||||
|
|
||||||
|
res_data = []
|
||||||
|
manager = get_driver(PG_DEFAULT_DRIVER).connection_manager(sid)
|
||||||
|
conn = manager.connection(did=did)
|
||||||
|
|
||||||
|
node_types = []
|
||||||
|
nspname = ''
|
||||||
|
show_sysobj = blueprint.show_system_objects().get()
|
||||||
|
if node_type == 'database':
|
||||||
|
|
||||||
|
# Fetch list of schemas
|
||||||
|
# Get sys_obj_values and get list of schemas
|
||||||
|
ntype = 'schema'
|
||||||
|
SQL = render_template("/".join(
|
||||||
|
[server_prop['template_path'], '/sql/get_schemas.sql']),
|
||||||
|
show_sysobj=show_sysobj)
|
||||||
|
status, res = conn.execute_dict(SQL)
|
||||||
|
|
||||||
|
if not status:
|
||||||
|
return internal_server_error(errormsg=res)
|
||||||
|
node_types = res['rows']
|
||||||
|
else:
|
||||||
|
SQL = render_template("/".join(
|
||||||
|
[server_prop['template_path'], '/sql/get_schemas.sql']),
|
||||||
|
nspid=node_id, show_sysobj=False)
|
||||||
|
status, res = conn.execute_dict(SQL)
|
||||||
|
|
||||||
|
if not status:
|
||||||
|
return internal_server_error(errormsg=res)
|
||||||
|
node_types = res['rows']
|
||||||
|
ntype = node_type
|
||||||
|
nspname = node_types[0]['name']
|
||||||
|
|
||||||
|
for row in node_types:
|
||||||
|
if 'oid' in row:
|
||||||
|
node_id = row['oid']
|
||||||
|
nspname = row['name']
|
||||||
|
|
||||||
|
# Fetch functions against schema
|
||||||
|
if ntype in ['schema', 'function']:
|
||||||
|
SQL = render_template("/".join(
|
||||||
|
[server_prop['template_path'], '/sql/function.sql']),
|
||||||
|
node_id=node_id, nspname=nspname, type='function')
|
||||||
|
|
||||||
|
status, res = conn.execute_dict(SQL)
|
||||||
|
|
||||||
|
if not status:
|
||||||
|
return internal_server_error(errormsg=res)
|
||||||
|
|
||||||
|
res_data.extend(res['rows'])
|
||||||
|
|
||||||
|
# Fetch trigger functions
|
||||||
|
if ntype in ['schema', 'trigger_function']:
|
||||||
|
SQL = render_template("/".join(
|
||||||
|
[server_prop['template_path'], '/sql/function.sql']),
|
||||||
|
node_id=node_id, nspname=nspname, type='trigger_function')
|
||||||
|
status, res = conn.execute_dict(SQL)
|
||||||
|
|
||||||
|
if not status:
|
||||||
|
return internal_server_error(errormsg=res)
|
||||||
|
|
||||||
|
res_data.extend(res['rows'])
|
||||||
|
|
||||||
|
# Fetch Sequences against schema
|
||||||
|
if ntype in ['schema', 'sequence']:
|
||||||
|
SQL = render_template("/".join(
|
||||||
|
[server_prop['template_path'], '/sql/sequence.sql']),
|
||||||
|
node_id=node_id, nspname=nspname)
|
||||||
|
|
||||||
|
status, res = conn.execute_dict(SQL)
|
||||||
|
if not status:
|
||||||
|
return internal_server_error(errormsg=res)
|
||||||
|
res_data.extend(res['rows'])
|
||||||
|
|
||||||
|
# Fetch Tables against schema
|
||||||
|
if ntype in ['schema', 'table']:
|
||||||
|
SQL = render_template("/".join(
|
||||||
|
[server_prop['template_path'], '/sql/table.sql']),
|
||||||
|
node_id=node_id, nspname=nspname)
|
||||||
|
|
||||||
|
status, res = conn.execute_dict(SQL)
|
||||||
|
if not status:
|
||||||
|
return internal_server_error(errormsg=res)
|
||||||
|
|
||||||
|
res_data.extend(res['rows'])
|
||||||
|
|
||||||
|
# Fetch Views against schema
|
||||||
|
if ntype in ['schema', 'view']:
|
||||||
|
SQL = render_template("/".join(
|
||||||
|
[server_prop['template_path'], '/sql/view.sql']),
|
||||||
|
node_id=node_id, nspname=nspname)
|
||||||
|
|
||||||
|
status, res = conn.execute_dict(SQL)
|
||||||
|
if not status:
|
||||||
|
return internal_server_error(errormsg=res)
|
||||||
|
|
||||||
|
res_data.extend(res['rows'])
|
||||||
|
|
||||||
|
return ajax_response(
|
||||||
|
response=res_data,
|
||||||
|
status=200
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@blueprint.route(
|
||||||
|
'/msql/<int:gid>/<int:sid>/<int:did>/',
|
||||||
|
methods=('GET', 'POST'))
|
||||||
|
@login_required
|
||||||
|
@check_precondition
|
||||||
|
def msql(gid, sid, did):
|
||||||
|
"""
|
||||||
|
This function will return modified SQL
|
||||||
|
"""
|
||||||
|
|
||||||
|
server_prop = server_info
|
||||||
|
data = {}
|
||||||
|
for k, v in request.args.items():
|
||||||
|
try:
|
||||||
|
data[k] = json.loads(v)
|
||||||
|
except ValueError:
|
||||||
|
data[k] = v
|
||||||
|
|
||||||
|
# Form db connection
|
||||||
|
manager = get_driver(PG_DEFAULT_DRIVER).connection_manager(sid)
|
||||||
|
conn = manager.connection(did=did)
|
||||||
|
|
||||||
|
acls = []
|
||||||
|
try:
|
||||||
|
acls = render_template(
|
||||||
|
"/".join([server_prop['template_path'], '/acl.json'])
|
||||||
|
)
|
||||||
|
acls = json.loads(acls)
|
||||||
|
except Exception as e:
|
||||||
|
current_app.logger.exception(e)
|
||||||
|
|
||||||
|
try:
|
||||||
|
|
||||||
|
# Parse privileges
|
||||||
|
data['priv'] = {}
|
||||||
|
if 'acl' in data:
|
||||||
|
# Get function acls
|
||||||
|
data['priv']['function'] = parse_priv_to_db(
|
||||||
|
data['acl'],
|
||||||
|
acls['function']['acl'])
|
||||||
|
|
||||||
|
data['priv']['sequence'] = parse_priv_to_db(
|
||||||
|
data['acl'],
|
||||||
|
acls['sequence']['acl'])
|
||||||
|
|
||||||
|
data['priv']['table'] = parse_priv_to_db(
|
||||||
|
data['acl'],
|
||||||
|
acls['table']['acl'])
|
||||||
|
|
||||||
|
# Pass database objects and get SQL for privileges
|
||||||
|
SQL_data = ''
|
||||||
|
data_func = {}
|
||||||
|
data_func['objects'] = data['objects']
|
||||||
|
data_func['priv'] = data['priv']['function']
|
||||||
|
SQL = render_template(
|
||||||
|
"/".join([server_prop['template_path'],
|
||||||
|
'/sql/grant_function.sql']),
|
||||||
|
data=data_func, conn=conn)
|
||||||
|
if SQL and SQL.strip('\n') != '':
|
||||||
|
SQL_data += SQL
|
||||||
|
|
||||||
|
data_seq = {}
|
||||||
|
data_seq['objects'] = data['objects']
|
||||||
|
data_seq['priv'] = data['priv']['sequence']
|
||||||
|
SQL = render_template(
|
||||||
|
"/".join([server_prop['template_path'],
|
||||||
|
'/sql/grant_sequence.sql']),
|
||||||
|
data=data_seq, conn=conn)
|
||||||
|
if SQL and SQL.strip('\n') != '':
|
||||||
|
SQL_data += SQL
|
||||||
|
|
||||||
|
data_table = {}
|
||||||
|
data_table['objects'] = data['objects']
|
||||||
|
data_table['priv'] = data['priv']['table']
|
||||||
|
SQL = render_template(
|
||||||
|
"/".join([server_prop['template_path'], '/sql/grant_table.sql']),
|
||||||
|
data=data_table, conn=conn)
|
||||||
|
if SQL and SQL.strip('\n') != '':
|
||||||
|
SQL_data += SQL
|
||||||
|
|
||||||
|
res = {'data': SQL_data}
|
||||||
|
|
||||||
|
return ajax_response(
|
||||||
|
response=res,
|
||||||
|
status=200
|
||||||
|
)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
return make_json_response(
|
||||||
|
status=410,
|
||||||
|
success=0,
|
||||||
|
errormsg=e.message
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@blueprint.route(
|
||||||
|
'/save/<int:gid>/<int:sid>/<int:did>/',
|
||||||
|
methods=('GET', 'POST'))
|
||||||
|
@login_required
|
||||||
|
@check_precondition
|
||||||
|
def save(gid, sid, did):
|
||||||
|
"""
|
||||||
|
This function will apply the privileges to the selected
|
||||||
|
Database Objects
|
||||||
|
"""
|
||||||
|
server_prop = server_info
|
||||||
|
data = request.form if request.form else json.loads(request.data.decode())
|
||||||
|
|
||||||
|
# Form db connection and we use conn to execute sql
|
||||||
|
manager = get_driver(PG_DEFAULT_DRIVER).connection_manager(sid)
|
||||||
|
conn = manager.connection(did=did)
|
||||||
|
|
||||||
|
acls = []
|
||||||
|
try:
|
||||||
|
acls = render_template(
|
||||||
|
"/".join([server_prop['template_path'], 'acl.json']),
|
||||||
|
)
|
||||||
|
acls = json.loads(acls)
|
||||||
|
except Exception as e:
|
||||||
|
current_app.logger.exception(e)
|
||||||
|
|
||||||
|
try:
|
||||||
|
|
||||||
|
# Parse privileges
|
||||||
|
data['priv'] = {}
|
||||||
|
if 'acl' in data:
|
||||||
|
# Get function acls
|
||||||
|
data['priv']['function'] = parse_priv_to_db(
|
||||||
|
data['acl'],
|
||||||
|
acls['function']['acl'])
|
||||||
|
|
||||||
|
data['priv']['sequence'] = parse_priv_to_db(
|
||||||
|
data['acl'],
|
||||||
|
acls['sequence']['acl'])
|
||||||
|
|
||||||
|
data['priv']['table'] = parse_priv_to_db(
|
||||||
|
data['acl'],
|
||||||
|
acls['table']['acl'])
|
||||||
|
|
||||||
|
# Pass database objects and get SQL for privileges
|
||||||
|
# Pass database objects and get SQL for privileges
|
||||||
|
SQL_data = ''
|
||||||
|
data_func = {}
|
||||||
|
data_func['objects'] = data['objects']
|
||||||
|
data_func['priv'] = data['priv']['function']
|
||||||
|
SQL = render_template(
|
||||||
|
"/".join([server_prop['template_path'],
|
||||||
|
'/sql/grant_function.sql']),
|
||||||
|
data=data_func, conn=conn)
|
||||||
|
if SQL and SQL.strip('\n') != '':
|
||||||
|
SQL_data += SQL
|
||||||
|
|
||||||
|
data_seq = {}
|
||||||
|
data_seq['objects'] = data['objects']
|
||||||
|
data_seq['priv'] = data['priv']['sequence']
|
||||||
|
SQL = render_template(
|
||||||
|
"/".join([server_prop['template_path'],
|
||||||
|
'/sql/grant_sequence.sql']),
|
||||||
|
data=data_seq, conn=conn)
|
||||||
|
if SQL and SQL.strip('\n') != '':
|
||||||
|
SQL_data += SQL
|
||||||
|
|
||||||
|
data_table = {}
|
||||||
|
data_table['objects'] = data['objects']
|
||||||
|
data_table['priv'] = data['priv']['table']
|
||||||
|
SQL = render_template(
|
||||||
|
"/".join([server_prop['template_path'], '/sql/grant_table.sql']),
|
||||||
|
data=data_table, conn=conn)
|
||||||
|
if SQL and SQL.strip('\n') != '':
|
||||||
|
SQL_data += SQL
|
||||||
|
|
||||||
|
status, res = conn.execute_dict(SQL_data)
|
||||||
|
if not status:
|
||||||
|
return internal_server_error(errormsg=res)
|
||||||
|
|
||||||
|
return make_json_response(
|
||||||
|
success=1,
|
||||||
|
info="Privileges applied"
|
||||||
|
)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
return internal_server_error(errormsg=e.message)
|
109
web/pgadmin/tools/grant_wizard/static/css/grant_wizard.css
Normal file
109
web/pgadmin/tools/grant_wizard/static/css/grant_wizard.css
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
/** Grant Wizard CSS **/
|
||||||
|
|
||||||
|
/**
|
||||||
|
CSS to make db object type table
|
||||||
|
fixed so that tbody content may
|
||||||
|
scroll
|
||||||
|
*/
|
||||||
|
|
||||||
|
.db_objects_container {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.object_type_table {
|
||||||
|
display: inline-block;
|
||||||
|
height: 100%;
|
||||||
|
border: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.object_type_table thead tr {
|
||||||
|
position: relative;
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.object_type_table tbody {
|
||||||
|
display: block;
|
||||||
|
overflow: scroll;
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
width: 100%;
|
||||||
|
min-height: 100%;
|
||||||
|
max-height: 66%;
|
||||||
|
height: 66%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.object_type_table tbody tr {
|
||||||
|
display: table;
|
||||||
|
max-width: 100%;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.object_type_table tbody tr td {
|
||||||
|
background-position: 4px 4px;
|
||||||
|
border-radius: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.object_type_table tbody tr td:nth-child(1),
|
||||||
|
.object_type_table thead tr th:nth-child(1) {
|
||||||
|
width: 28px;
|
||||||
|
min-width: 28px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.object_type_table tbody tr td:nth-child(2) {
|
||||||
|
width: 161px;
|
||||||
|
min-width: 161px;
|
||||||
|
max-width: 161px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.object_type_table thead tr th:nth-child(2) {
|
||||||
|
width: 161px;
|
||||||
|
min-width: 161px;
|
||||||
|
max-width: 161px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.object_type_table tbody tr td:nth-child(3) {
|
||||||
|
width: 109px;
|
||||||
|
min-width: 109px;
|
||||||
|
max-width: 109px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.object_type_table thead tr th:nth-child(3) {
|
||||||
|
width: 109px;
|
||||||
|
min-width: 109px;
|
||||||
|
max-width: 109px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.object_type_table thead tr th:nth-child(4) {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.object_type_table tbody tr td:nth-child(4) {
|
||||||
|
width: 100%;
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Override Backgrid filter CSS **/
|
||||||
|
.db_objects_container .backgrid-filter.form-search {
|
||||||
|
float: left;
|
||||||
|
margin: 0px 5px 5px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Custom styling for Codemirror field **/
|
||||||
|
.wizard-right-panel_content {
|
||||||
|
border: 1px solide #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wizard-right-panel_content .CodeMirror {
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
height: 285px !important;
|
||||||
|
min-height: 285px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wizard-right-panel_content .CodeMirror-linenumber {
|
||||||
|
background: #F7F7F7;
|
||||||
|
border-right: 1px solid #DDDDDD;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wizard-right-panel_content .CodeMirror-gutters {
|
||||||
|
min-height: 285px !important;
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,30 @@
|
|||||||
|
{# List of allowed privileges of Schema, table sequence, function and view #}
|
||||||
|
{#
|
||||||
|
Format for allowed privileges are:
|
||||||
|
"node_name": {
|
||||||
|
"type": "name",
|
||||||
|
"acl": [...]
|
||||||
|
}
|
||||||
|
#}
|
||||||
|
{
|
||||||
|
"schema": {
|
||||||
|
"type": "SCHEMA",
|
||||||
|
"acl": ["a", "r", "w", "d", "D", "x", "t", "U", "X"]
|
||||||
|
},
|
||||||
|
"table": {
|
||||||
|
"type": "TABLE",
|
||||||
|
"acl": ["a", "w", "d", "D", "x", "t"]
|
||||||
|
},
|
||||||
|
"view": {
|
||||||
|
"type": "VIEW",
|
||||||
|
"acl": ["a", "w", "d", "D", "x", "t"]
|
||||||
|
},
|
||||||
|
"sequence": {
|
||||||
|
"type": "SEQUENCE",
|
||||||
|
"acl": ["w", "U"]
|
||||||
|
},
|
||||||
|
"function": {
|
||||||
|
"type": "FUNCTION",
|
||||||
|
"acl": ["X"]
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,23 @@
|
|||||||
|
{# ===== Fetch list of Database object types(Functions) ====== #}
|
||||||
|
{% if type and node_id and nspname %}
|
||||||
|
{% set func_type = 'Trigger Function' if type == 'trigger_function' else 'Function' %}
|
||||||
|
SELECT
|
||||||
|
pr.oid,
|
||||||
|
pg_get_function_identity_arguments(pr.oid) AS proargs,
|
||||||
|
{# pr.proname || '(' || pg_get_function_identity_arguments(pr.oid) || ')' AS name,#}
|
||||||
|
pr.proname AS name,
|
||||||
|
'{{ nspname }}' AS nspname,
|
||||||
|
'{{ func_type }}' AS object_type,
|
||||||
|
'{{ "icon-function" if type != "trigger_function" else "icon-trigger_function" }}' AS icon
|
||||||
|
FROM
|
||||||
|
pg_proc pr
|
||||||
|
JOIN pg_type typ ON typ.oid=prorettype
|
||||||
|
JOIN pg_namespace typns ON typns.oid=typ.typnamespace
|
||||||
|
JOIN pg_language lng ON lng.oid=prolang
|
||||||
|
LEFT OUTER JOIN pg_description des ON (des.objoid=pr.oid AND des.classoid='pg_proc'::regclass)
|
||||||
|
WHERE
|
||||||
|
proisagg = FALSE AND pronamespace = {{ node_id }}::oid
|
||||||
|
AND typname {{ 'NOT' if type != 'trigger_function' else '' }} IN ('trigger', 'event_trigger')
|
||||||
|
ORDER BY
|
||||||
|
proname
|
||||||
|
{% endif %}
|
@@ -0,0 +1,19 @@
|
|||||||
|
{# ===== Fetch list of all schemas ===== #}
|
||||||
|
{% import 'catalog/pg/macros/catalogs.sql' as CATALOGS %}
|
||||||
|
SELECT
|
||||||
|
nsp.oid,
|
||||||
|
nsp.nspname as name
|
||||||
|
FROM
|
||||||
|
pg_namespace nsp
|
||||||
|
WHERE
|
||||||
|
{% if nspid %}
|
||||||
|
nsp.oid={{nspid}}::int AND
|
||||||
|
{% else %}
|
||||||
|
{% if not show_sysobj %}
|
||||||
|
nspname NOT LIKE E'pg\_%' AND
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
|
NOT (
|
||||||
|
{{ CATALOGS.LIST('nsp') }}
|
||||||
|
)
|
||||||
|
ORDER BY nspname;
|
@@ -0,0 +1,10 @@
|
|||||||
|
{# ===== Grant Permissions on Database Objects Selected ==== #}
|
||||||
|
{% import 'macros/functions/privilege.macros' as PRIVILEGE_FUNCTION %}
|
||||||
|
{% for obj in data.objects -%}
|
||||||
|
{% for priv in data.priv -%}
|
||||||
|
{# ===== if object_type is Function then apply function marcros ===== #}
|
||||||
|
{% if (obj.object_type == 'Function' or obj.object_type == 'Trigger Function') %}
|
||||||
|
{{ PRIVILEGE_FUNCTION.SET(conn, 'FUNCTION', priv['grantee'], obj.name, priv['without_grant'], priv['with_grant'], obj.nspname, obj.proargs)}}
|
||||||
|
{% endif -%}
|
||||||
|
{% endfor -%}
|
||||||
|
{% endfor -%}
|
@@ -0,0 +1,9 @@
|
|||||||
|
{# ===== Grant Permissions on Database Objects Selected ==== #}
|
||||||
|
{% import 'macros/schemas/privilege.macros' as PRIVILEGE %}
|
||||||
|
{% for obj in data.objects -%}
|
||||||
|
{% for priv in data.priv -%}
|
||||||
|
{% if obj.object_type == 'Sequence' %}
|
||||||
|
{{ PRIVILEGE.SET(conn, 'SEQUENCE', priv['grantee'], obj.name, priv['without_grant'], priv['with_grant'], obj.nspname ) }}
|
||||||
|
{% endif %}
|
||||||
|
{% endfor -%}
|
||||||
|
{% endfor -%}
|
@@ -0,0 +1,9 @@
|
|||||||
|
{# ===== Grant Permissions on Database Objects Selected ==== #}
|
||||||
|
{% import 'macros/schemas/privilege.macros' as PRIVILEGE %}
|
||||||
|
{% for obj in data.objects -%}
|
||||||
|
{% for priv in data.priv -%}
|
||||||
|
{% if obj.object_type == 'Table' or obj.object_type == 'View' %}
|
||||||
|
{{ PRIVILEGE.SET(conn, 'TABLE', priv['grantee'], obj.name, priv['without_grant'], priv['with_grant'], obj.nspname ) }}
|
||||||
|
{% endif %}
|
||||||
|
{% endfor -%}
|
||||||
|
{% endfor -%}
|
@@ -0,0 +1,15 @@
|
|||||||
|
{# ===== Fetch list of Database object types(Sequence) ===== #}
|
||||||
|
{% if node_id, nspname %}
|
||||||
|
SELECT
|
||||||
|
cl.relname AS name,
|
||||||
|
'Sequence' AS object_type,
|
||||||
|
'icon-sequence' AS icon,
|
||||||
|
'{{ nspname }}' AS nspname
|
||||||
|
FROM
|
||||||
|
pg_class cl
|
||||||
|
LEFT OUTER JOIN pg_description des ON (des.objoid=cl.oid AND des.classoid='pg_class'::regclass)
|
||||||
|
WHERE
|
||||||
|
relkind = 'S' AND relnamespace = {{ node_id }}::oid
|
||||||
|
ORDER BY
|
||||||
|
cl.relname
|
||||||
|
{% endif %}
|
@@ -0,0 +1,19 @@
|
|||||||
|
{# ===== Fetch list of Database object types(Tables) ===== #}
|
||||||
|
{% if node_id and nspname %}
|
||||||
|
SELECT
|
||||||
|
rel.relname AS name,
|
||||||
|
'Table' AS object_type,
|
||||||
|
'icon-table' AS icon,
|
||||||
|
'{{ nspname }}' AS nspname
|
||||||
|
FROM
|
||||||
|
pg_class rel
|
||||||
|
LEFT OUTER JOIN pg_tablespace spc ON spc.oid=rel.reltablespace
|
||||||
|
LEFT OUTER JOIN pg_description des ON (des.objoid=rel.oid AND des.objsubid=0 AND des.classoid='pg_class'::regclass)
|
||||||
|
LEFT OUTER JOIN pg_constraint con ON con.conrelid=rel.oid AND con.contype='p'
|
||||||
|
LEFT OUTER JOIN pg_class tst ON tst.oid = rel.reltoastrelid
|
||||||
|
LEFT JOIN pg_type typ ON rel.reloftype=typ.oid
|
||||||
|
WHERE
|
||||||
|
rel.relkind IN ('r','s','t') AND rel.relnamespace = {{ node_id }}::oid
|
||||||
|
ORDER BY
|
||||||
|
rel.relname
|
||||||
|
{% endif %}
|
@@ -0,0 +1,28 @@
|
|||||||
|
{# ===== Fetch list of Database object types(View) ===== #}
|
||||||
|
{% if node_id %}
|
||||||
|
SELECT
|
||||||
|
c.relname AS name,
|
||||||
|
'View' AS object_type,
|
||||||
|
'icon-view' AS icon,
|
||||||
|
'{{ nspname }}' AS nspname
|
||||||
|
FROM
|
||||||
|
pg_class c
|
||||||
|
LEFT OUTER JOIN pg_tablespace spc ON spc.oid=c.reltablespace
|
||||||
|
LEFT OUTER JOIN pg_description des ON (des.objoid=c.oid and des.objsubid=0 AND des.classoid='pg_class'::regclass)
|
||||||
|
LEFT OUTER JOIN pg_class tst ON tst.oid = c.reltoastrelid
|
||||||
|
WHERE
|
||||||
|
((c.relhasrules AND (EXISTS (
|
||||||
|
SELECT
|
||||||
|
r.rulename
|
||||||
|
FROM
|
||||||
|
pg_rewrite r
|
||||||
|
WHERE
|
||||||
|
((r.ev_class = c.oid)
|
||||||
|
AND (bpchar(r.ev_type) = '1'::bpchar))
|
||||||
|
))
|
||||||
|
) OR (c.relkind = 'v'::char)
|
||||||
|
)
|
||||||
|
AND c.relnamespace = {{ node_id }}::oid
|
||||||
|
ORDER BY
|
||||||
|
c.relname
|
||||||
|
{% endif %}
|
@@ -0,0 +1,30 @@
|
|||||||
|
{# List of allowed privileges of Schema, table sequence, function and view #}
|
||||||
|
{#
|
||||||
|
Format for allowed privileges are:
|
||||||
|
"node_name": {
|
||||||
|
"type": "name",
|
||||||
|
"acl": [...]
|
||||||
|
}
|
||||||
|
#}
|
||||||
|
{
|
||||||
|
"schema": {
|
||||||
|
"type": "SCHEMA",
|
||||||
|
"acl": ["a", "r", "w", "d", "D", "x", "t", "U", "X"]
|
||||||
|
},
|
||||||
|
"table": {
|
||||||
|
"type": "TABLE",
|
||||||
|
"acl": ["a", "w", "d", "D", "x", "t"]
|
||||||
|
},
|
||||||
|
"view": {
|
||||||
|
"type": "VIEW",
|
||||||
|
"acl": ["a", "w", "d", "D", "x", "t"]
|
||||||
|
},
|
||||||
|
"sequence": {
|
||||||
|
"type": "SEQUENCE",
|
||||||
|
"acl": ["w", "U"]
|
||||||
|
},
|
||||||
|
"function": {
|
||||||
|
"type": "FUNCTION",
|
||||||
|
"acl": ["X"]
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,23 @@
|
|||||||
|
{# ===== Fetch list of Database object types(Functions) ====== #}
|
||||||
|
{% if type and node_id and nspname %}
|
||||||
|
{% set func_type = 'Trigger Function' if type == 'trigger_function' else 'Function' %}
|
||||||
|
SELECT
|
||||||
|
pr.oid,
|
||||||
|
pg_get_function_identity_arguments(pr.oid) AS proargs,
|
||||||
|
{# pr.proname || '(' || pg_get_function_identity_arguments(pr.oid) || ')' AS name,#}
|
||||||
|
pr.proname AS name,
|
||||||
|
'{{ nspname }}' AS nspname,
|
||||||
|
'{{ func_type }}' AS object_type,
|
||||||
|
'{{ "icon-function" if type != "trigger_function" else "icon-trigger_function" }}' AS icon
|
||||||
|
FROM
|
||||||
|
pg_proc pr
|
||||||
|
JOIN pg_type typ ON typ.oid=prorettype
|
||||||
|
JOIN pg_namespace typns ON typns.oid=typ.typnamespace
|
||||||
|
JOIN pg_language lng ON lng.oid=prolang
|
||||||
|
LEFT OUTER JOIN pg_description des ON (des.objoid=pr.oid AND des.classoid='pg_proc'::regclass)
|
||||||
|
WHERE
|
||||||
|
proisagg = FALSE AND pronamespace = {{ node_id }}::oid
|
||||||
|
AND typname {{ 'NOT' if type != 'trigger_function' else '' }} IN ('trigger', 'event_trigger')
|
||||||
|
ORDER BY
|
||||||
|
proname
|
||||||
|
{% endif %}
|
@@ -0,0 +1,19 @@
|
|||||||
|
{# ===== Fetch list of all schemas ===== #}
|
||||||
|
{% import 'catalog/pg/macros/catalogs.sql' as CATALOGS %}
|
||||||
|
SELECT
|
||||||
|
nsp.oid,
|
||||||
|
nsp.nspname as name
|
||||||
|
FROM
|
||||||
|
pg_namespace nsp
|
||||||
|
WHERE
|
||||||
|
{% if nspid %}
|
||||||
|
nsp.oid={{nspid}}::int AND
|
||||||
|
{% else %}
|
||||||
|
{% if not show_sysobj %}
|
||||||
|
nspname NOT LIKE E'pg\_%' AND
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
|
NOT (
|
||||||
|
{{ CATALOGS.LIST('nsp') }}
|
||||||
|
)
|
||||||
|
ORDER BY nspname;
|
@@ -0,0 +1,10 @@
|
|||||||
|
{# ===== Grant Permissions on Database Objects Selected ==== #}
|
||||||
|
{% import 'macros/functions/privilege.macros' as PRIVILEGE_FUNCTION %}
|
||||||
|
{% for obj in data.objects -%}
|
||||||
|
{% for priv in data.priv -%}
|
||||||
|
{# ===== if object_type is Function then apply function marcros ===== #}
|
||||||
|
{% if (obj.object_type == 'Function' or obj.object_type == 'Trigger Function') %}
|
||||||
|
{{ PRIVILEGE_FUNCTION.SET(conn, 'FUNCTION', priv['grantee'], obj.name, priv['without_grant'], priv['with_grant'], obj.nspname, obj.proargs)}}
|
||||||
|
{% endif -%}
|
||||||
|
{% endfor -%}
|
||||||
|
{% endfor -%}
|
@@ -0,0 +1,9 @@
|
|||||||
|
{# ===== Grant Permissions on Database Objects Selected ==== #}
|
||||||
|
{% import 'macros/schemas/privilege.macros' as PRIVILEGE %}
|
||||||
|
{% for obj in data.objects -%}
|
||||||
|
{% for priv in data.priv -%}
|
||||||
|
{% if obj.object_type == 'Sequence' %}
|
||||||
|
{{ PRIVILEGE.SET(conn, 'SEQUENCE', priv['grantee'], obj.name, priv['without_grant'], priv['with_grant'], obj.nspname ) }}
|
||||||
|
{% endif %}
|
||||||
|
{% endfor -%}
|
||||||
|
{% endfor -%}
|
@@ -0,0 +1,9 @@
|
|||||||
|
{# ===== Grant Permissions on Database Objects Selected ==== #}
|
||||||
|
{% import 'macros/schemas/privilege.macros' as PRIVILEGE %}
|
||||||
|
{% for obj in data.objects -%}
|
||||||
|
{% for priv in data.priv -%}
|
||||||
|
{% if obj.object_type == 'Table' or obj.object_type == 'View' %}
|
||||||
|
{{ PRIVILEGE.SET(conn, 'TABLE', priv['grantee'], obj.name, priv['without_grant'], priv['with_grant'], obj.nspname ) }}
|
||||||
|
{% endif %}
|
||||||
|
{% endfor -%}
|
||||||
|
{% endfor -%}
|
@@ -0,0 +1,15 @@
|
|||||||
|
{# ===== Fetch list of Database object types(Sequence) ===== #}
|
||||||
|
{% if node_id, nspname %}
|
||||||
|
SELECT
|
||||||
|
cl.relname AS name,
|
||||||
|
'Sequence' AS object_type,
|
||||||
|
'icon-sequence' AS icon,
|
||||||
|
'{{ nspname }}' AS nspname
|
||||||
|
FROM
|
||||||
|
pg_class cl
|
||||||
|
LEFT OUTER JOIN pg_description des ON (des.objoid=cl.oid AND des.classoid='pg_class'::regclass)
|
||||||
|
WHERE
|
||||||
|
relkind = 'S' AND relnamespace = {{ node_id }}::oid
|
||||||
|
ORDER BY
|
||||||
|
cl.relname
|
||||||
|
{% endif %}
|
@@ -0,0 +1,19 @@
|
|||||||
|
{# ===== Fetch list of Database object types(Tables) ===== #}
|
||||||
|
{% if node_id and nspname %}
|
||||||
|
SELECT
|
||||||
|
rel.relname AS name,
|
||||||
|
'Table' AS object_type,
|
||||||
|
'icon-table' AS icon,
|
||||||
|
'{{ nspname }}' AS nspname
|
||||||
|
FROM
|
||||||
|
pg_class rel
|
||||||
|
LEFT OUTER JOIN pg_tablespace spc ON spc.oid=rel.reltablespace
|
||||||
|
LEFT OUTER JOIN pg_description des ON (des.objoid=rel.oid AND des.objsubid=0 AND des.classoid='pg_class'::regclass)
|
||||||
|
LEFT OUTER JOIN pg_constraint con ON con.conrelid=rel.oid AND con.contype='p'
|
||||||
|
LEFT OUTER JOIN pg_class tst ON tst.oid = rel.reltoastrelid
|
||||||
|
LEFT JOIN pg_type typ ON rel.reloftype=typ.oid
|
||||||
|
WHERE
|
||||||
|
rel.relkind IN ('r','s','t') AND rel.relnamespace = {{ node_id }}::oid
|
||||||
|
ORDER BY
|
||||||
|
rel.relname
|
||||||
|
{% endif %}
|
@@ -0,0 +1,28 @@
|
|||||||
|
{# ===== Fetch list of Database object types(View) ===== #}
|
||||||
|
{% if node_id %}
|
||||||
|
SELECT
|
||||||
|
c.relname AS name,
|
||||||
|
'View' AS object_type,
|
||||||
|
'icon-view' AS icon,
|
||||||
|
'{{ nspname }}' AS nspname
|
||||||
|
FROM
|
||||||
|
pg_class c
|
||||||
|
LEFT OUTER JOIN pg_tablespace spc ON spc.oid=c.reltablespace
|
||||||
|
LEFT OUTER JOIN pg_description des ON (des.objoid=c.oid and des.objsubid=0 AND des.classoid='pg_class'::regclass)
|
||||||
|
LEFT OUTER JOIN pg_class tst ON tst.oid = c.reltoastrelid
|
||||||
|
WHERE
|
||||||
|
((c.relhasrules AND (EXISTS (
|
||||||
|
SELECT
|
||||||
|
r.rulename
|
||||||
|
FROM
|
||||||
|
pg_rewrite r
|
||||||
|
WHERE
|
||||||
|
((r.ev_class = c.oid)
|
||||||
|
AND (bpchar(r.ev_type) = '1'::bpchar))
|
||||||
|
))
|
||||||
|
) OR (c.relkind = 'v'::char)
|
||||||
|
)
|
||||||
|
AND c.relnamespace = {{ node_id }}::oid
|
||||||
|
ORDER BY
|
||||||
|
c.relname
|
||||||
|
{% endif %}
|
Reference in New Issue
Block a user