1 //////////////////////////////////////////////////////////////////////////
2 //
3 // pgAdmin III - PostgreSQL Tools
4 //
5 // Copyright (C) 2002 - 2016, The pgAdmin Development Team
6 // This software is released under the PostgreSQL Licence
7 //
8 // frmGrantWizard.cpp - Grant Wizard dialogue
9 //
10 //////////////////////////////////////////////////////////////////////////
11 
12 // wxWindows headers
13 #include <wx/wx.h>
14 #include <wx/settings.h>
15 #include <wx/xrc/xmlres.h>
16 
17 
18 // App headers
19 #include "pgAdmin3.h"
20 #include "frm/frmGrantWizard.h"
21 #include "frm/frmMain.h"
22 #include "utils/sysLogger.h"
23 #include "ctl/ctlSecurityPanel.h"
24 #include "schema/pgFunction.h"
25 #include "schema/pgSequence.h"
26 #include "schema/pgTable.h"
27 #include "schema/pgView.h"
28 #include "schema/gpExtTable.h"
29 
30 // Icons
31 #include "images/index.pngc"
32 
33 
34 #define chkList     CTRL_CHECKLISTBOX("chkList")
35 
36 
37 
BEGIN_EVENT_TABLE(frmGrantWizard,ExecutionDialog)38 BEGIN_EVENT_TABLE(frmGrantWizard, ExecutionDialog)
39 	EVT_NOTEBOOK_PAGE_CHANGED(XRCID("nbNotebook"),  frmGrantWizard::OnPageSelect)
40 	EVT_BUTTON(XRCID("btnChkAll"),                  frmGrantWizard::OnCheckAll)
41 	EVT_BUTTON(XRCID("btnUnchkAll"),                frmGrantWizard::OnUncheckAll)
42 	EVT_CHECKLISTBOX(XRCID("chkList"),              frmGrantWizard::OnChange)
43 END_EVENT_TABLE()
44 
45 
46 frmGrantWizard::frmGrantWizard(frmMain *form, pgObject *obj) : ExecutionDialog(form, obj)
47 {
48 	nbNotebook = 0;
49 
50 	SetFont(settings->GetSystemFont());
51 	LoadResource(form, wxT("frmGrantWizard"));
52 	RestorePosition();
53 
54 	SetTitle(object->GetTranslatedMessage(GRANTWIZARDTITLE));
55 
56 	// Icon
57 	SetIcon(*index_png_ico);
58 	nbNotebook = CTRL_NOTEBOOK("nbNotebook");
59 	sqlPane = 0;
60 
61 	Restore();
62 	EnableOK(false);
63 }
64 
65 
~frmGrantWizard()66 frmGrantWizard::~frmGrantWizard()
67 {
68 	SavePosition();
69 	Abort();
70 }
71 
72 
GetHelpPage() const73 wxString frmGrantWizard::GetHelpPage() const
74 {
75 	wxString page = wxT("pg/sql-grant");
76 
77 	return page;
78 }
79 
OnChange(wxCommandEvent & event)80 void frmGrantWizard::OnChange(wxCommandEvent &event)
81 {
82 	sqlPane->SetReadOnly(false);
83 	sqlPane->SetText(GetSql());
84 	sqlPane->SetReadOnly(true);
85 
86 	if (sqlPane->GetText().IsEmpty())
87 		EnableOK(false);
88 	else
89 		EnableOK(true);
90 }
91 
92 
OnUncheckAll(wxCommandEvent & event)93 void frmGrantWizard::OnUncheckAll(wxCommandEvent &event)
94 {
95 	unsigned int i;
96 	for (i = 0 ; i < chkList->GetCount() ; i++)
97 		chkList->Check(i, false);
98 
99 	OnChange(event);
100 }
101 
102 
103 
OnCheckAll(wxCommandEvent & event)104 void frmGrantWizard::OnCheckAll(wxCommandEvent &event)
105 {
106 	unsigned int i;
107 	for (i = 0 ; i < chkList->GetCount() ; i++)
108 		chkList->Check(i, true);
109 
110 	OnChange(event);
111 }
112 
OnPageSelect(wxNotebookEvent & event)113 void frmGrantWizard::OnPageSelect(wxNotebookEvent &event)
114 {
115 	if (nbNotebook && sqlPane && event.GetSelection() == (int)nbNotebook->GetPageCount() - 2)
116 	{
117 		sqlPane->SetReadOnly(false);
118 		sqlPane->SetText(GetSql());
119 		sqlPane->SetReadOnly(true);
120 	}
121 }
122 
123 
AddObjects(pgCollection * collection)124 void frmGrantWizard::AddObjects(pgCollection *collection)
125 {
126 	bool traverseKids = (!collection->IsCollection() || collection->GetMetaType() == PGM_SCHEMA);
127 
128 	if (!traverseKids)
129 	{
130 		pgaFactory *factory = collection->GetFactory();
131 		if (!factory->IsCollectionFor(tableFactory) &&
132 		        !factory->IsCollectionFor(functionFactory) &&
133 		        !factory->IsCollectionFor(triggerFunctionFactory) &&
134 		        !factory->IsCollectionFor(procedureFactory) &&
135 		        !factory->IsCollectionFor(viewFactory) &&
136 		        !factory->IsCollectionFor(extTableFactory) &&
137 		        !factory->IsCollectionFor(sequenceFactory))
138 			return;
139 	}
140 
141 	wxCookieType cookie;
142 	wxTreeItemId item = mainForm->GetBrowser()->GetFirstChild(collection->GetId(), cookie);
143 
144 	while (item)
145 	{
146 		pgObject *obj = mainForm->GetBrowser()->GetObject(item);
147 		if (obj)
148 		{
149 			if (traverseKids)
150 				AddObjects((pgCollection *)obj);
151 			else
152 			{
153 				if (obj->CanEdit())
154 				{
155 					objectArray.Add(obj);
156 					chkList->Append((wxString)wxGetTranslation(obj->GetTypeName()) + wxT(" ") + obj->GetFullIdentifier());
157 				}
158 			}
159 		}
160 		item = mainForm->GetBrowser()->GetNextChild(collection->GetId(), cookie);
161 	}
162 }
163 
Go()164 void frmGrantWizard::Go()
165 {
166 	chkList->SetFocus();
167 
168 	wxString privList = wxT("INSERT,SELECT,UPDATE,DELETE,TRUNCATE,REFERENCES,TRIGGER");
169 	const char *privChar = "arwdDxt";
170 
171 	switch (object->GetMetaType())
172 	{
173 		case PGM_DATABASE:
174 		case PGM_SCHEMA:
175 			privList.Append(wxT(",EXECUTE,USAGE"));
176 			privChar = "arwdDxtXU";
177 			break;
178 		case PGM_FUNCTION:
179 			privList = wxT("EXECUTE");
180 			privChar = "X";
181 			break;
182 		case PGM_SEQUENCE:
183 			privList = wxT("SELECT,UPDATE,USAGE");
184 			privChar = "rwU";
185 			break;
186 		case GP_EXTTABLE:
187 			privList = wxT("SELECT");
188 			privChar = "r";
189 		default:
190 			break;
191 	}
192 
193 	securityPage = new ctlSecurityPanel(nbNotebook, privList, privChar, mainForm->GetImageList());
194 	securityPage->SetConnection(object->GetConnection());
195 	this->Connect(EVT_SECURITYPANEL_CHANGE, wxCommandEventHandler(frmGrantWizard::OnChange));
196 
197 	sqlPane = new ctlSQLBox(nbNotebook, CTL_PROPSQL, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE | wxSUNKEN_BORDER | wxTE_READONLY | wxTE_RICH2);
198 	nbNotebook->AddPage(sqlPane, wxT("SQL"));
199 
200 	txtMessages = new wxTextCtrl(nbNotebook, CTL_MSG, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE | wxTE_READONLY | wxHSCROLL);
201 	nbNotebook->AddPage(txtMessages, _("Messages"));
202 
203 	AddObjects((pgCollection *)object);
204 
205 
206 	if (securityPage->cbGroups)
207 	{
208 		pgSet *set = object->GetConnection()->ExecuteSet(wxT("SELECT groname FROM pg_group ORDER BY groname"));
209 
210 		if (set)
211 		{
212 			while (!set->Eof())
213 			{
214 				securityPage->cbGroups->Append(wxT("group ") + set->GetVal(0));
215 				set->MoveNext();
216 			}
217 			delete set;
218 		}
219 
220 		if (settings->GetShowUsersForPrivileges())
221 		{
222 			set = object->GetConnection()->ExecuteSet(wxT("SELECT usename FROM pg_user ORDER BY usename"));
223 
224 			if (set)
225 			{
226 				securityPage->stGroup->SetLabel(_("Group/User"));
227 
228 				while (!set->Eof())
229 				{
230 					securityPage->cbGroups->Append(set->GetVal(0));
231 					set->MoveNext();
232 				}
233 				delete set;
234 				Layout();
235 			}
236 		}
237 	}
238 
239 	Layout();
240 	Show(true);
241 
242 	// Work around a weird display bug in wx2.7
243 	this->Refresh();
244 }
245 
246 
GetSql()247 wxString frmGrantWizard::GetSql()
248 {
249 	wxString sql;
250 
251 	unsigned int i;
252 	for (i = 0 ; i < chkList->GetCount() ; i++)
253 	{
254 		if (chkList->IsChecked(i))
255 		{
256 			wxString tmp;
257 
258 			pgObject *obj = (pgObject *)objectArray.Item(i);
259 
260 			switch (obj->GetMetaType())
261 			{
262 				case PGM_FUNCTION:
263 				{
264 					if (((pgFunction *)obj)->GetIsProcedure())
265 					{
266 						tmp = securityPage->GetGrant(wxT("X"), wxT("PROCEDURE ")
267 						                             + obj->GetQuotedFullIdentifier() + wxT("(")
268 						                             + ((pgProcedure *)obj)->GetArgSigList() + wxT(")"));
269 					}
270 					else
271 					{
272 						tmp = securityPage->GetGrant(wxT("X"), wxT("FUNCTION ")
273 						                             + obj->GetQuotedFullIdentifier() + wxT("(")
274 						                             + ((pgFunction *)obj)->GetArgSigList() + wxT(")"));
275 					}
276 					break;
277 				}
278 				case PGM_VIEW:
279 					tmp = securityPage->GetGrant(wxT("arwdxt"), wxT("TABLE ") + obj->GetQuotedFullIdentifier());
280 					break;
281 				case PGM_SEQUENCE:
282 					tmp = securityPage->GetGrant(wxT("rwU"), wxT("SEQUENCE ") + obj->GetQuotedFullIdentifier());
283 					break;
284 				case GP_EXTTABLE:
285 					tmp = securityPage->GetGrant(wxT("r"), wxT("TABLE ") + obj->GetQuotedFullIdentifier());
286 				default:
287 					if (obj->GetTypeName().Upper() == wxT("EXTERNAL TABLE")) // somewhat of a hack
288 					{
289 						tmp = securityPage->GetGrant(wxT("r"), wxT("TABLE ") + obj->GetQuotedFullIdentifier());
290 					}
291 					else
292 						tmp = securityPage->GetGrant(wxT("arwdDxt"), obj->GetTypeName().Upper() + wxT(" ") + obj->GetQuotedFullIdentifier());
293 					break;
294 			}
295 
296 			if (!tmp.IsEmpty())
297 				sql.Append(tmp);
298 		}
299 	}
300 	return sql;
301 }
302 
303 
grantWizardFactory(menuFactoryList * list,wxMenu * mnu,ctlMenuToolbar * toolbar)304 grantWizardFactory::grantWizardFactory(menuFactoryList *list, wxMenu *mnu, ctlMenuToolbar *toolbar) : contextActionFactory(list)
305 {
306 	mnu->Append(id, _("&Grant Wizard..."), _("Grants rights to multiple objects"));
307 }
308 
309 
StartDialog(frmMain * form,pgObject * obj)310 wxWindow *grantWizardFactory::StartDialog(frmMain *form, pgObject *obj)
311 {
312 	frmGrantWizard *frm = new frmGrantWizard(form, obj);
313 	frm->Go();
314 	return 0;
315 }
316 
317 
CheckEnable(pgObject * obj)318 bool grantWizardFactory::CheckEnable(pgObject *obj)
319 {
320 	if (obj)
321 	{
322 		switch (obj->GetMetaType())
323 		{
324 			case PGM_TABLE:
325 			case PGM_FUNCTION:
326 			case PGM_SEQUENCE:
327 			case PGM_VIEW:
328 			case GP_EXTTABLE:
329 				if (obj->IsCollection() && obj->GetSchema()->GetMetaType() != PGM_CATALOG)
330 					return obj->GetSchema()->CanEdit();
331 				break;
332 
333 			case PGM_SCHEMA:
334 				return obj->CanEdit();
335 			default:
336 				break;
337 		}
338 	}
339 	return false;
340 }
341