pgadmin3/ctl/ctlDefaultSecurityPanel.cpp
lsv 38f4510342 Add view MAINTAIN privilege
Добавлена поддержка отображения новой привелегии MAINTAIN.
2025-01-21 10:16:11 +05:00

625 lines
18 KiB
C++

//////////////////////////////////////////////////////////////////////////
//
// pgAdmin III - PostgreSQL Tools
//
// Copyright (C) 2002 - 2016, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
// ctlDefaultSecurityPanel.cpp - Panel with default security information
//
//////////////////////////////////////////////////////////////////////////
// wxWindows headers
#include <wx/wx.h>
#include <wx/settings.h>
#include <wx/imaglist.h>
// App headers
#include "pgAdmin3.h"
#include "ctl/ctlDefaultSecurityPanel.h"
#include "db/pgConn.h"
#include "dlg/dlgProperty.h"
#include "schema/pgGroup.h"
#include "schema/pgUser.h"
#include "utils/sysLogger.h"
#include <wx/arrimpl.cpp>
defaultPrivilegesOn g_defPrivTables17('r', wxT("Tables"), wxT("arwdDxtm")), g_defPrivTables('r', wxT("Tables"), wxT("arwdDxt")),
g_defPrivSequences('S', wxT("Sequences"), wxT("rwU")),
g_defPrivFunctions('f', wxT("Functions"), wxT("X")),
g_defPrivTypes('T', wxT("Types"), wxT("U"));
defaultPrivilegesOn::defaultPrivilegesOn(const wxChar privType, const wxString &privOn, const wxString &privileges)
: m_privilegeType(privType), m_privilegesOn(privOn), m_privileges(privileges) {}
ctlDefaultSecurityPanel::ctlDefaultSecurityPanel(pgConn *conn, wxNotebook *nb, wxImageList *imgList)
: wxPanel(nb, -1, wxDefaultPosition, wxDefaultSize), nbNotebook(NULL)
{
nb->AddPage(this, _("Default Privileges"));
wxFlexGridSizer *mainSizer = new wxFlexGridSizer(1, 1, 1, 1);
mainSizer->AddGrowableCol(0);
mainSizer->AddGrowableRow(0);
nbNotebook = new wxNotebook(this, -1, wxDefaultPosition, wxDefaultSize, 0, _("Default ACLs"));
if (conn->BackendMinimumVersion(17, 0))
m_defPrivOnTablesPanel = new ctlDefaultPrivilegesPanel(this, nbNotebook, g_defPrivTables17, imgList);
else
m_defPrivOnTablesPanel = new ctlDefaultPrivilegesPanel(this, nbNotebook, g_defPrivTables, imgList);
m_defPrivOnSeqsPanel = new ctlDefaultPrivilegesPanel(this, nbNotebook, g_defPrivSequences, imgList);
m_defPrivOnFuncsPanel = new ctlDefaultPrivilegesPanel(this, nbNotebook, g_defPrivFunctions, imgList);
if (conn->BackendMinimumVersion(9, 2))
m_defPrivOnTypesPanel = new ctlDefaultPrivilegesPanel(this, nbNotebook, g_defPrivTypes, imgList);
else
m_defPrivOnTypesPanel = NULL;
mainSizer->Add(nbNotebook, 0, wxEXPAND | wxALL, 2);
this->SetSizer(mainSizer);
mainSizer->Fit(this);
}
void ctlDefaultSecurityPanel::UpdatePrivilegePages(bool createDefPrivs, const wxString &defPrivsOnTables,
const wxString &defPrivsOnSeqs, const wxString &defPrivsOnFuncs, const wxString &defPrivsOnTypes)
{
if (!createDefPrivs)
{
nbNotebook->Enable(false);
return;
}
m_defPrivOnTablesPanel->Update(defPrivsOnTables);
m_defPrivOnSeqsPanel->Update(defPrivsOnSeqs);
m_defPrivOnFuncsPanel->Update(defPrivsOnFuncs);
if (m_defPrivOnTypesPanel)
m_defPrivOnTypesPanel->Update(defPrivsOnTypes);
}
wxString ctlDefaultSecurityPanel::GetDefaultPrivileges(const wxString &schemaName)
{
wxString strDefPrivs;
int nPageCount = nbNotebook->GetPageCount();
for (int index = 0; index < nPageCount; index++)
{
strDefPrivs += (dynamic_cast<ctlDefaultPrivilegesPanel *>(nbNotebook->GetPage(index)))->GetDefaultPrivileges(schemaName);
}
return strDefPrivs;
}
///////////////////////////////////////////////////////////////////////////////
// ctlDefaultPrivilegesPanel
///////////////////////////////////////////////////////////////////////////////
BEGIN_EVENT_TABLE(ctlDefaultPrivilegesPanel, wxPanel)
EVT_LIST_ITEM_SELECTED(CTL_DEFLBPRIV, ctlDefaultPrivilegesPanel::OnPrivSelChange)
EVT_BUTTON(CTL_DEFADDPRIV, ctlDefaultPrivilegesPanel::OnAddPriv)
EVT_BUTTON(CTL_DEFDELPRIV, ctlDefaultPrivilegesPanel::OnDelPriv)
EVT_TEXT(CTL_DEFCBGROUP, ctlDefaultPrivilegesPanel::OnGroupChange)
EVT_COMBOBOX(CTL_DEFCBGROUP, ctlDefaultPrivilegesPanel::OnGroupChange)
EVT_CHECKBOX(CTL_DEFALLPRIV, ctlDefaultPrivilegesPanel::OnPrivCheckAll)
EVT_CHECKBOX(CTL_DEFALLPRIVGRANT, ctlDefaultPrivilegesPanel::OnPrivCheckAllGrant)
EVT_CHECKBOX(CTL_DEFPRIVCB, ctlDefaultPrivilegesPanel::OnPrivCheck)
EVT_CHECKBOX(CTL_DEFPRIVCB + 2, ctlDefaultPrivilegesPanel::OnPrivCheck)
EVT_CHECKBOX(CTL_DEFPRIVCB + 4, ctlDefaultPrivilegesPanel::OnPrivCheck)
EVT_CHECKBOX(CTL_DEFPRIVCB + 6, ctlDefaultPrivilegesPanel::OnPrivCheck)
EVT_CHECKBOX(CTL_DEFPRIVCB + 8, ctlDefaultPrivilegesPanel::OnPrivCheck)
EVT_CHECKBOX(CTL_DEFPRIVCB + 10, ctlDefaultPrivilegesPanel::OnPrivCheck)
EVT_CHECKBOX(CTL_DEFPRIVCB + 12, ctlDefaultPrivilegesPanel::OnPrivCheck)
EVT_CHECKBOX(CTL_DEFPRIVCB + 14, ctlDefaultPrivilegesPanel::OnPrivCheck)
EVT_CHECKBOX(CTL_DEFPRIVCB + 16, ctlDefaultPrivilegesPanel::OnPrivCheck)
END_EVENT_TABLE();
DEFINE_LOCAL_EVENT_TYPE(EVT_DEFAULTSECURITYPANEL_CHANGE)
ctlDefaultPrivilegesPanel::ctlDefaultPrivilegesPanel(ctlDefaultSecurityPanel *defSecurityPanel, wxNotebook *nb,
defaultPrivilegesOn &privOn, wxImageList *imgList)
: wxPanel(nb, -1, wxDefaultPosition, wxDefaultSize), m_defPrivChanged(false),
m_privilegeType(privOn), m_defSecurityPanel(defSecurityPanel)
{
nb->AddPage(this, m_privilegeType.m_privilegesOn);
allPrivileges = 0;
privCheckboxes = 0;
m_currentSelectedPriv = NULL;
privilegeCount = m_privilegeType.m_privileges.Length();
wxFlexGridSizer *item0 = new wxFlexGridSizer(3, 1, 5, 5);
item0->AddGrowableCol(0);
item0->AddGrowableRow(0);
privCheckboxes = new wxCheckBox*[privilegeCount * 2];
wxFlexGridSizer *itemSizer1 = new wxFlexGridSizer(1, 1, 5, 5);
itemSizer1->AddGrowableCol(0);
itemSizer1->AddGrowableRow(0);
wxString strGroupLabel = settings->GetShowUsersForPrivileges() ? _("Role/Group") : _("Role");
lbPrivileges = new ctlListView(this, CTL_DEFLBPRIV, wxDefaultPosition, wxDefaultSize, wxSUNKEN_BORDER | wxLC_REPORT);
lbPrivileges->SetImageList(imgList, wxIMAGE_LIST_SMALL);
lbPrivileges->AddColumn(_("Role/Group"), 60, wxLIST_FORMAT_LEFT);
lbPrivileges->AddColumn(_("Privileges"), 60, wxLIST_FORMAT_LEFT);
itemSizer1->Add(lbPrivileges, 0, wxEXPAND | wxTOP | wxLEFT | wxRIGHT, 4);
item0->Add(itemSizer1, 0, wxEXPAND | wxALL, 5);
wxBoxSizer *itemSizer2 = new wxBoxSizer(wxHORIZONTAL);
btnAddPriv = new wxButton(this, CTL_DEFADDPRIV, _("Add/Change"));
itemSizer2->Add(btnAddPriv, 0, wxEXPAND | wxTOP | wxLEFT | wxRIGHT, 4);
btnDelPriv = new wxButton(this, CTL_DEFDELPRIV, _("Remove"));
itemSizer2->Add(btnDelPriv, 0, wxEXPAND | wxTOP | wxLEFT | wxRIGHT, 4);
item0->Add(itemSizer2, 0, wxEXPAND | wxALL, 0);
wxStaticBox *sb = new wxStaticBox(this, -1, _("Privileges"));
wxBoxSizer *itemSizer3 = new wxStaticBoxSizer( sb, wxVERTICAL );
item0->Add(itemSizer3, 0, wxEXPAND | wxALL, 5);
wxBoxSizer *itemSizer4a = new wxBoxSizer(wxHORIZONTAL);
stGroup = new wxStaticText(this, CTL_DEFSTATICGROUP, strGroupLabel);
itemSizer4a->Add(stGroup, 0, wxEXPAND | wxTOP | wxLEFT | wxRIGHT, 4);
cbGroups = new ctlComboBox(this, CTL_DEFCBGROUP, wxDefaultPosition, wxDefaultSize);
cbGroups->Append(wxT("public"));
cbGroups->SetSelection(0);
itemSizer4a->Add(cbGroups, wxEXPAND | wxTOP | wxLEFT | wxRIGHT);
itemSizer3->Add(itemSizer4a, 0, wxEXPAND | wxALL, 0);
/* border size depends on the plateform */
#ifdef __WXMSW__
int bordersize = 4;
#endif
#ifdef __WXMAC__
int bordersize = 3;
#endif
#ifdef __WXGTK__
int bordersize = 0;
#endif
wxBoxSizer *itemSizer5 = new wxBoxSizer(wxHORIZONTAL);
allPrivileges = new wxCheckBox(this, CTL_DEFALLPRIV, wxT("ALL"));
itemSizer5->Add(allPrivileges, wxEXPAND | wxTOP | wxLEFT | wxRIGHT);
allPrivilegesGrant = new wxCheckBox(this, CTL_DEFALLPRIVGRANT, wxT("WITH GRANT OPTION"));
itemSizer5->Add(allPrivilegesGrant, wxEXPAND | wxTOP | wxLEFT | wxRIGHT);
allPrivilegesGrant->Disable();
itemSizer3->Add(itemSizer5, 0, wxALL, bordersize);
for (int index = 0; index < privilegeCount; index++)
{
int i = index * 2;
wxChar privilege = m_privilegeType.m_privileges.GetChar(index);
wxString priv = pgObject::GetPrivilegeName(privilege);
wxCheckBox *cb;
wxBoxSizer *itemSizer6 = new wxBoxSizer(wxHORIZONTAL);
cb = new wxCheckBox(this, CTL_DEFPRIVCB + i, priv);
itemSizer6->Add(cb, wxEXPAND | wxTOP | wxLEFT | wxRIGHT);
privCheckboxes[i++] = cb;
cb = new wxCheckBox(this, CTL_DEFPRIVCB + i, wxT("WITH GRANT OPTION"));
itemSizer6->Add(cb, wxEXPAND | wxTOP | wxLEFT | wxRIGHT);
cb->Disable();
privCheckboxes[i] = cb;
itemSizer3->Add(itemSizer6, 0, wxALL, bordersize);
}
this->SetSizer(item0);
item0->Fit(this);
}
ctlDefaultPrivilegesPanel::~ctlDefaultPrivilegesPanel()
{
cbGroups->Clear();
if (privCheckboxes)
delete[] privCheckboxes;
}
// Find the privileges for the selected user from the map
// and select the check-boxes accordingly
bool ctlDefaultPrivilegesPanel::PrivCheckBoxUpdate(wxString &strRole)
{
int index = 0;
wxString strKey = strRole;
defPrivHash::iterator priv = m_privileges.find(strKey);
bool canGrant = CanGrant();
if (priv == m_privileges.end())
{
m_currentSelectedPriv = NULL;
allPrivileges->SetValue(true);
allPrivilegesGrant->Enable(canGrant);
for (; index < privilegeCount; index++)
{
privCheckboxes[index * 2]->Enable();
privCheckboxes[index * 2]->SetValue(true);
privCheckboxes[index * 2 + 1]->Enable(canGrant);
}
return false;
}
else
{
allPrivileges->SetValue(false);
allPrivilegesGrant->SetValue(false);
allPrivilegesGrant->Enable(false);
}
wxString currentPrivileges = priv->second.m_modified ? priv->second.m_newPriv : priv->second.m_origPriv;
m_currentSelectedPriv = &priv->second;
for (index = 0; index < privilegeCount; index++)
{
int privAt = currentPrivileges.Find(m_privilegeType.m_privileges.GetChar(index));
if (privAt != wxNOT_FOUND)
{
privCheckboxes[index * 2]->SetValue(true);
privCheckboxes[index * 2 + 1]->Enable(canGrant);
if (canGrant && (unsigned int)privAt < currentPrivileges.Length() - 1 && currentPrivileges.GetChar(privAt + 1) == wxT('*'))
privCheckboxes[index * 2 + 1]->SetValue(true);
else
privCheckboxes[index * 2 + 1]->SetValue(false);
}
else
{
privCheckboxes[index * 2]->SetValue(false);
privCheckboxes[index * 2 + 1]->SetValue(false);
privCheckboxes[index * 2 + 1]->Disable();
}
}
return false;
}
bool ctlDefaultPrivilegesPanel::CanGrant()
{
if (cbGroups->GetValue() == wxT("public"))
return false;
return true;
}
void ctlDefaultPrivilegesPanel::OnGroupChange(wxCommandEvent &ev)
{
cbGroups->GuessSelection(ev);
wxString strRole = cbGroups->GetValue();
if (strRole.IsEmpty())
return;
btnAddPriv->Enable(!PrivCheckBoxUpdate(strRole));
}
void ctlDefaultPrivilegesPanel::OnPrivCheckAll(wxCommandEvent &ev)
{
bool all = allPrivileges->GetValue();
allPrivilegesGrant->Enable(all && CanGrant());
for (int i = 0; i < privilegeCount; i++)
{
privCheckboxes[i * 2]->SetValue(all);
CheckGrantOpt(i);
}
}
void ctlDefaultPrivilegesPanel::OnPrivCheckAllGrant(wxCommandEvent &ev)
{
bool grant = allPrivilegesGrant->GetValue();
for (int i = 0 ; i < privilegeCount ; i++)
privCheckboxes[i * 2 + 1]->SetValue(grant);
}
void ctlDefaultPrivilegesPanel::OnPrivCheck(wxCommandEvent &ev)
{
int id = (ev.GetId() - CTL_DEFPRIVCB) / 2;
CheckGrantOpt(id);
btnAddPriv->Enable();
if (!privCheckboxes[id * 2]->GetValue())
allPrivileges->SetValue(false);
}
void ctlDefaultPrivilegesPanel::CheckGrantOpt(int id)
{
bool canGrant = (privCheckboxes[id * 2]->GetValue() && CanGrant());
if (canGrant)
privCheckboxes[id * 2 + 1]->Enable(true);
else
{
privCheckboxes[id * 2 + 1]->SetValue(false);
privCheckboxes[id * 2 + 1]->Disable();
}
btnAddPriv->Enable();
}
void ctlDefaultPrivilegesPanel::OnDelPriv(wxCommandEvent &ev)
{
int pos;
wxString strRole;
if ((pos = lbPrivileges->GetFirstSelected()) == -1)
return;
wxListItem info;
info.m_itemId = pos;
info.m_col = 0;
info.m_mask = wxLIST_MASK_TEXT;
if (lbPrivileges->GetItem(info))
strRole = info.m_text;
wxString strKey = strRole;
defPrivHash::iterator priv = m_privileges.find(strKey);
if (priv != m_privileges.end())
{
priv->second.m_modified = true;
priv->second.m_newPriv = wxT("");
if (m_currentSelectedPriv == &priv->second)
PrivCheckBoxUpdate(strRole);
}
lbPrivileges->DeleteCurrentItem();
m_defPrivChanged = true;
ev.Skip();
}
void ctlDefaultPrivilegesPanel::OnAddPriv(wxCommandEvent &ev)
{
wxString strRole, strPriv;
bool isPresent = (m_currentSelectedPriv != NULL &&
((m_currentSelectedPriv->m_modified &&
!m_currentSelectedPriv->m_newPriv.IsEmpty()) ||
(!m_currentSelectedPriv->m_modified)))
|| lbPrivileges->FindItem(-1, cbGroups->GetGuessedStringSelection()) >= 0;
if (allPrivileges && allPrivileges->GetValue())
{
if (allPrivilegesGrant->GetValue())
{
for (int index = 0; index < privilegeCount; index++)
{
strPriv += m_privilegeType.m_privileges.GetChar(index);
strPriv += wxT('*');
}
}
else
strPriv = m_privilegeType.m_privileges;
}
else
{
for (int index = 0; index < privilegeCount; index++)
{
if (privCheckboxes[index * 2]->GetValue())
{
strPriv += m_privilegeType.m_privileges.GetChar(index);
if(privCheckboxes[index * 2 + 1]->IsEnabled() && privCheckboxes[index * 2 + 1]->GetValue())
strPriv += wxT('*');
}
}
}
if (!m_currentSelectedPriv)
{
strRole = cbGroups->GetGuessedStringSelection();
if (strRole.IsEmpty())
return;
defPrivilege priv;
priv.m_username = strRole;
priv.m_origPriv = wxT("");
priv.m_modified = true;
priv.m_newPriv = strPriv;
wxString strKey = strRole;
m_privileges[strKey] = priv;
defPrivHash::iterator itr = m_privileges.find(strKey);
m_currentSelectedPriv = &itr->second;
}
else
{
if (m_currentSelectedPriv->m_modified ?
m_currentSelectedPriv->m_newPriv == strPriv :
m_currentSelectedPriv->m_origPriv == strPriv)
{
ev.Skip();
return;
}
strRole = m_currentSelectedPriv->m_username;
m_currentSelectedPriv->m_modified = true;
m_currentSelectedPriv->m_newPriv = strPriv;
}
if (!isPresent)
{
int icon;
if (strRole.IsSameAs(wxT("public"), true))
icon = PGICON_PUBLIC;
else if (strRole.StartsWith(wxT("group ")))
icon = groupFactory.GetIconId();
else
icon = userFactory.GetIconId();
long pos = lbPrivileges->GetItemCount();
lbPrivileges->InsertItem(pos, strRole, icon);
lbPrivileges->SetItem(pos, 1, strPriv);
}
else
{
long nCount = lbPrivileges->GetItemCount();
wxListItem info;
for (int index = 0; index < nCount; index++)
{
wxString strTempRole;
info.m_itemId = index;
info.m_col = 0;
info.m_mask = wxLIST_MASK_TEXT;
if (lbPrivileges->GetItem(info))
strTempRole = info.m_text;
if (strTempRole == strRole)
{
lbPrivileges->SetItem(index, 1, strPriv);
break;
}
}
}
m_defPrivChanged = true;
ev.Skip();
}
void ctlDefaultPrivilegesPanel::OnPrivSelChange(wxListEvent &ev)
{
if (!cbGroups)
return;
if (allPrivileges)
{
allPrivileges->SetValue(false);
allPrivilegesGrant->SetValue(false);
allPrivilegesGrant->Disable();
}
long pos = lbPrivileges->GetSelection();
if (pos >= 0)
{
wxString name = lbPrivileges->GetText(pos);
wxString value = lbPrivileges->GetText(pos, 1);
pos = cbGroups->FindString(name);
if (pos < 0)
{
cbGroups->Append(name);
pos = cbGroups->GetCount() - 1;
}
cbGroups->SetSelection(pos);
int i;
for (i = 0 ; i < privilegeCount ; i++)
{
if (privCheckboxes[i * 2]->GetName() != wxT("DISABLE"))
{
privCheckboxes[i * 2]->Enable();
int index = value.Find(m_privilegeType.m_privileges.GetChar(i));
if (index >= 0)
{
privCheckboxes[i * 2]->SetValue(true);
privCheckboxes[i * 2 + 1]->SetValue(value.Mid(index + 1, 1) == wxT("*"));
}
else
privCheckboxes[i * 2]->SetValue(false);
}
CheckGrantOpt(i);
}
PrivCheckBoxUpdate(name);
}
btnAddPriv->Enable();
}
void ctlDefaultPrivilegesPanel::Update(wxString strDefPrivs)
{
unsigned int index = 0;
lbPrivileges->DeleteAllItems();
m_privileges.clear();
cbGroups->Clear();
cbGroups->Append(wxT("public"));
for (; index < m_defSecurityPanel->m_groups.GetCount(); index++)
{
cbGroups->Append(m_defSecurityPanel->m_groups[index]);
}
if (!strDefPrivs.IsEmpty())
{
wxString strRole, strPriv;
strDefPrivs.Replace(wxT("\\\""), wxT("\""), true);
strDefPrivs.Replace(wxT("\\\\"), wxT("\\"), true);
// Removing starting brace '{' and ending brace '}'
strDefPrivs = strDefPrivs.SubString(1, strDefPrivs.Length() - 1);
long pos = 0;
while (pgObject::findUserPrivs(strDefPrivs, strRole, strPriv))
{
int icon;
if (strRole.IsSameAs(wxT("public"), true))
icon = PGICON_PUBLIC;
else if (cbGroups->FindString(strRole) != wxNOT_FOUND)
icon = userFactory.GetIconId();
else if (cbGroups->FindString(wxT("group ") + strRole) != wxNOT_FOUND)
{
icon = groupFactory.GetIconId();
strRole = wxT("group ") + strRole;
}
else
continue;
defPrivilege priv;
priv.m_username = strRole;
priv.m_origPriv = strPriv;
priv.m_modified = false;
priv.m_newPriv = wxT("");
wxString strKey = strRole;
m_privileges[strKey] = priv;
pos = lbPrivileges->GetItemCount();
lbPrivileges->InsertItem(pos, strRole, icon);
lbPrivileges->SetItem(pos, 1, strPriv);
strRole = wxT("");
strPriv = wxT("");
pos++;
}
}
}
wxString ctlDefaultPrivilegesPanel::GetDefaultPrivileges(const wxString &schemaName)
{
if(!m_defPrivChanged)
return wxT("");
wxString strDefPrivs;
defPrivHash::iterator itr = m_privileges.begin();
for (; itr != m_privileges.end(); itr++)
{
if(itr->second.m_modified)
{
wxString strRole = itr->second.m_username;
if (strRole.StartsWith(wxT("group ")))
{
strRole = strRole.Mid(6);
strRole = qtIdent(strRole);
}
else if (strRole != wxT("public"))
strRole = qtIdent(strRole);
wxString strOrigDefPrivs = itr->second.m_origPriv;
wxString strNewDefPrivs = itr->second.m_newPriv;
strDefPrivs += pgObject::GetDefaultPrivileges(m_privilegeType.m_privilegesOn.Upper(), m_privilegeType.m_privileges, schemaName, strOrigDefPrivs, strNewDefPrivs, strRole);
}
}
return strDefPrivs;
}