pgadmin3/dlg/dlgUser.cpp
levinsv 4af765213c support PG11
Поддержка PostgreSQL 11 только для Windows
2018-10-10 22:59:25 +05:00

571 lines
14 KiB
C++

//////////////////////////////////////////////////////////////////////////
//
// pgAdmin III - PostgreSQL Tools
//
// Copyright (C) 2002 - 2016, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
// dlgUser.cpp - PostgreSQL User Property
//
//////////////////////////////////////////////////////////////////////////
#include "pgAdmin3.h"
// wxWindows headers
#include <wx/wx.h>
// App headers
#include "utils/misc.h"
#include "dlg/dlgUser.h"
#include "schema/pgUser.h"
// pointer to controls
#define txtID CTRL_TEXT("txtID")
#define txtPasswd CTRL_TEXT("txtPasswd")
#define txtRePasswd CTRL_TEXT("txtRePasswd")
#define datValidUntil CTRL_CALENDAR("datValidUntil")
#define timValidUntil CTRL_TIME("timValidUntil")
#define chkCreateDB CTRL_CHECKBOX("chkCreateDB")
#define chkCreateUser CTRL_CHECKBOX("chkCreateUser")
#define lbGroupsNotIn CTRL_LISTBOX("lbGroupsNotIn")
#define lbGroupsIn CTRL_LISTBOX("lbGroupsIn")
#define btnAddGroup CTRL_BUTTON("btnAddGroup")
#define btnDelGroup CTRL_BUTTON("btnDelGroup")
#define lstVariables CTRL_LISTVIEW("lstVariables")
#define btnAdd CTRL_BUTTON("wxID_ADD")
#define btnRemove CTRL_BUTTON("wxID_REMOVE")
#define cbVarname CTRL_COMBOBOX2("cbVarname")
#define txtValue CTRL_TEXT("txtValue")
#define chkValue CTRL_CHECKBOX("chkValue")
dlgProperty *pgUserFactory::CreateDialog(frmMain *frame, pgObject *node, pgObject *parent)
{
return new dlgUser(this, frame, (pgUser *)node);
}
BEGIN_EVENT_TABLE(dlgUser, dlgProperty)
EVT_CALENDAR_SEL_CHANGED(XRCID("datValidUntil"), dlgUser::OnChangeCal)
EVT_DATE_CHANGED(XRCID("datValidUntil"), dlgUser::OnChangeDate)
EVT_SPIN(XRCID("timValidUntil"), dlgUser::OnChangeSpin)
EVT_LISTBOX_DCLICK(XRCID("lbGroupsNotIn"), dlgUser::OnGroupAdd)
EVT_LISTBOX_DCLICK(XRCID("lbGroupsIn"), dlgUser::OnGroupRemove)
EVT_TEXT(XRCID("txtPasswd"), dlgUser::OnChangePasswd)
EVT_TEXT(XRCID("txtRePasswd"), dlgUser::OnChangePasswd)
EVT_CHECKBOX(XRCID("chkCreateDB"), dlgUser::OnChange)
EVT_CHECKBOX(XRCID("chkCreateUser"), dlgUser::OnChangeSuperuser)
EVT_BUTTON(XRCID("btnAddGroup"), dlgUser::OnGroupAdd)
EVT_BUTTON(XRCID("btnDelGroup"), dlgUser::OnGroupRemove)
EVT_LIST_ITEM_SELECTED(XRCID("lstVariables"), dlgUser::OnVarSelChange)
EVT_BUTTON(wxID_ADD, dlgUser::OnVarAdd)
EVT_BUTTON(wxID_REMOVE, dlgUser::OnVarRemove)
EVT_TEXT(XRCID("cbVarname"), dlgUser::OnVarnameSelChange)
EVT_COMBOBOX(XRCID("cbVarname"), dlgUser::OnVarnameSelChange)
END_EVENT_TABLE();
dlgUser::dlgUser(pgaFactory *f, frmMain *frame, pgUser *node)
: dlgProperty(f, frame, wxT("dlgUser"))
{
user = node;
lstVariables->CreateColumns(0, _("Variable"), _("Value"), -1);
btnOK->Disable();
chkValue->Hide();
}
pgObject *dlgUser::GetObject()
{
return user;
}
int dlgUser::Go(bool modal)
{
pgSet *set = connection->ExecuteSet(wxT("SELECT groname FROM pg_group"));
if (set)
{
while (!set->Eof())
{
wxString groupName = set->GetVal(wxT("groname"));
if (user && user->GetGroupsIn().Index(groupName) >= 0)
lbGroupsIn->Append(groupName);
else
lbGroupsNotIn->Append(groupName);
set->MoveNext();
}
delete set;
}
if (connection->BackendMinimumVersion(7, 4))
set = connection->ExecuteSet(wxT("SELECT name, vartype, min_val, max_val\n")
wxT(" FROM pg_settings WHERE context in ('user', 'superuser')"));
else
set = connection->ExecuteSet(wxT("SELECT name, 'string' as vartype, '' as min_val, '' as max_val FROM pg_settings"));
if (set)
{
while (!set->Eof())
{
cbVarname->Append(set->GetVal(0));
varInfo.Add(set->GetVal(wxT("vartype")) + wxT(" ") +
set->GetVal(wxT("min_val")) + wxT(" ") +
set->GetVal(wxT("max_val")));
set->MoveNext();
}
delete set;
cbVarname->SetSelection(0);
SetupVarEditor(0);
}
if (user)
{
// Edit Mode
readOnly = !user->GetServer()->GetSuperUser();
txtID->SetValue(NumToStr(user->GetUserId()));
chkCreateDB->SetValue(user->GetCreateDatabase());
chkCreateUser->SetValue(user->GetSuperuser());
if (user->GetAccountExpires().IsValid())
{
datValidUntil->SetValue(user->GetAccountExpires().GetDateOnly());
timValidUntil->SetTime(user->GetAccountExpires());
}
if (!connection->BackendMinimumVersion(7, 4))
txtName->Disable();
txtID->Disable();
size_t index;
for (index = 0 ; index < user->GetConfigList().GetCount() ; index++)
{
wxString item = user->GetConfigList().Item(index);
lstVariables->AppendItem(0, item.BeforeFirst('='), item.AfterFirst('='));
}
timValidUntil->Enable(!readOnly && user->GetAccountExpires().IsValid());
if (readOnly)
{
chkCreateDB->Disable();
chkCreateUser->Disable();
datValidUntil->Disable();
timValidUntil->Disable();
btnAddGroup->Disable();
btnDelGroup->Disable();
cbVarname->Disable();
txtValue->Disable();
btnRemove->Disable();
if (connection->GetUser() != user->GetName())
{
txtPasswd->Disable();
txtRePasswd->Disable();
btnAdd->Disable();
}
else
{
txtPasswd->Enable();
txtRePasswd->Enable();
btnAdd->Enable();
}
}
}
else
{
wxDateTime empty;
datValidUntil->SetValue(empty);
txtID->SetValidator(numericValidator);
timValidUntil->Disable();
}
return dlgProperty::Go(modal);
}
wxString dlgUser::GetHelpPage() const
{
if (nbNotebook->GetSelection() == 2)
return wxT("pg/runtime-config");
return dlgProperty::GetHelpPage();
}
void dlgUser::OnChangeCal(wxCalendarEvent &ev)
{
bool timEn = ev.GetDate().IsValid();
timValidUntil->Enable(timEn);
if (!timEn)
timValidUntil->SetTime(wxDefaultDateTime);
else
timValidUntil->SetTime(wxDateTime::Today());
CheckChange();
}
void dlgUser::OnChangeDate(wxDateEvent &ev)
{
bool timEn = ev.GetDate().IsValid();
timValidUntil->Enable(timEn);
if (!timEn)
timValidUntil->SetTime(wxDefaultDateTime);
else
timValidUntil->SetTime(wxDateTime::Today());
CheckChange();
}
void dlgUser::OnChangeSpin(wxSpinEvent &ev)
{
CheckChange();
}
void dlgUser::OnChangeSuperuser(wxCommandEvent &ev)
{
if (user && user->GetSuperuser() && !chkCreateUser->GetValue())
{
wxMessageDialog dlg(this,
_("Deleting a superuser might result in unwanted behaviour (e.g. when restoring the database).\nAre you sure?"),
_("Confirm superuser deletion"),
wxICON_EXCLAMATION | wxYES_NO | wxNO_DEFAULT);
if (dlg.ShowModal() != wxID_YES)
{
chkCreateUser->SetValue(true);
return;
}
}
CheckChange();
}
void dlgUser::OnChangePasswd(wxCommandEvent &ev)
{
CheckChange();
}
void dlgUser::CheckChange()
{
bool timEn = datValidUntil->GetValue().IsValid();
timValidUntil->Enable(timEn);
if (!timEn)
timValidUntil->SetTime(wxDefaultDateTime);
// Check the passwords match
if (txtPasswd->GetValue() != txtRePasswd->GetValue())
{
bool enable = true;
CheckValid(enable, false, _("The passwords entered do not match!"));
EnableOK(enable);
return;
}
if (!user)
{
wxString name = GetName();
bool enable = true;
CheckValid(enable, !name.IsEmpty(), _("Please specify name."));
EnableOK(enable);
}
else
{
EnableOK(!GetSql().IsEmpty());
}
}
void dlgUser::OnGroupAdd(wxCommandEvent &ev)
{
if (!readOnly)
{
int pos = lbGroupsNotIn->GetSelection();
if (pos >= 0)
{
lbGroupsIn->Append(lbGroupsNotIn->GetString(pos));
lbGroupsNotIn->Delete(pos);
}
CheckChange();
}
}
void dlgUser::OnGroupRemove(wxCommandEvent &ev)
{
if (!readOnly)
{
int pos = lbGroupsIn->GetSelection();
if (pos >= 0)
{
lbGroupsNotIn->Append(lbGroupsIn->GetString(pos));
lbGroupsIn->Delete(pos);
}
CheckChange();
}
}
void dlgUser::OnVarnameSelChange(wxCommandEvent &ev)
{
int sel = cbVarname->GuessSelection(ev);
SetupVarEditor(sel);
}
void dlgUser::SetupVarEditor(int var)
{
if (var >= 0 && varInfo.Count() > 0)
{
wxStringTokenizer vals(varInfo.Item(var));
wxString typ = vals.GetNextToken();
if (typ == wxT("bool"))
{
txtValue->Hide();
chkValue->Show();
}
else
{
chkValue->Hide();
txtValue->Show();
if (typ == wxT("string") || typ == wxT("enum"))
txtValue->SetValidator(wxTextValidator());
else
txtValue->SetValidator(numericValidator);
}
}
}
void dlgUser::OnVarSelChange(wxListEvent &ev)
{
long pos = lstVariables->GetSelection();
if (pos >= 0)
{
wxString value = lstVariables->GetText(pos, 1);
cbVarname->SetValue(lstVariables->GetText(pos));
// We used to raise an OnVarnameSelChange() event here, but
// at this point the combo box hasn't necessarily updated.
int sel = cbVarname->FindString(lstVariables->GetText(pos));
SetupVarEditor(sel);
txtValue->SetValue(value);
chkValue->SetValue(value == wxT("on"));
}
}
void dlgUser::OnVarAdd(wxCommandEvent &ev)
{
wxString name = cbVarname->GetValue();
wxString value;
if (chkValue->IsShown())
value = chkValue->GetValue() ? wxT("on") : wxT("off");
else
value = txtValue->GetValue().Strip(wxString::both);
if (value.IsEmpty())
value = wxT("DEFAULT");
if (!name.IsEmpty())
{
long pos = lstVariables->FindItem(-1, name);
if (pos < 0)
{
pos = lstVariables->GetItemCount();
lstVariables->InsertItem(pos, name, 0);
}
lstVariables->SetItem(pos, 1, value);
}
CheckChange();
}
void dlgUser::OnVarRemove(wxCommandEvent &ev)
{
if (lstVariables->GetSelection() == wxNOT_FOUND)
return;
lstVariables->DeleteCurrentItem();
CheckChange();
}
pgObject *dlgUser::CreateObject(pgCollection *collection)
{
wxString name = GetName();
pgObject *obj = userFactory.CreateObjects(collection, 0, wxT("\n WHERE usename=") + qtDbString(name));
return obj;
}
wxString dlgUser::GetSql()
{
int pos;
wxString sql;
wxString name = GetName();
wxString passwd = txtPasswd->GetValue();
bool createDB = chkCreateDB->GetValue(),
createUser = chkCreateUser->GetValue();
if (user)
{
// Edit Mode
AppendNameChange(sql);
wxString options;
if (!passwd.IsEmpty())
options += wxT(" ENCRYPTED PASSWORD ") + qtDbString(connection->EncryptPassword(name, passwd));
if (createDB != user->GetCreateDatabase() || createUser != user->GetSuperuser())
options += wxT("\n ");
if (createDB != user->GetCreateDatabase())
{
if (createDB)
options += wxT(" CREATEDB");
else
options += wxT(" NOCREATEDB");
}
if (createUser != user->GetSuperuser())
{
if (createUser)
options += wxT(" CREATEUSER");
else
options += wxT(" NOCREATEUSER");
}
if (!datValidUntil->GetValue().IsValid() || DateToStr(datValidUntil->GetValue()) != DateToStr(user->GetAccountExpires()))
{
if (datValidUntil->GetValue().IsValid())
options += wxT("\n VALID UNTIL ") + qtDbString(DateToAnsiStr(datValidUntil->GetValue() + timValidUntil->GetValue()));
else
options += wxT("\n VALID UNTIL 'infinity'");
}
if (!options.IsNull())
sql += wxT("ALTER USER ") + qtIdent(name) + options + wxT(";\n");
int cnt = lbGroupsIn->GetCount();
wxArrayString tmpGroups = user->GetGroupsIn();
// check for added groups
for (pos = 0 ; pos < cnt ; pos++)
{
wxString groupName = lbGroupsIn->GetString(pos);
int index = tmpGroups.Index(groupName);
if (index >= 0)
tmpGroups.RemoveAt(index);
else
sql += wxT("ALTER GROUP ") + qtIdent(groupName)
+ wxT("\n ADD USER ") + qtIdent(name) + wxT(";\n");
}
// check for removed groups
for (pos = 0 ; pos < (int)tmpGroups.GetCount() ; pos++)
{
sql += wxT("ALTER GROUP ") + qtIdent(tmpGroups.Item(pos))
+ wxT("\n DROP USER ") + qtIdent(name) + wxT(";\n");
}
}
else
{
// Create Mode
long id = StrToLong(txtID->GetValue());
sql = wxT(
"CREATE USER ") + qtIdent(name);
if (id)
sql += wxT("\n WITH SYSID ") + NumToStr(id);
if (!passwd.IsEmpty())
sql += wxT(" ENCRYPTED PASSWORD ") + qtDbString(connection->EncryptPassword(name, passwd));
if (createDB || createUser)
sql += wxT("\n ");
if (createDB)
sql += wxT(" CREATEDB");
if (createUser)
sql += wxT(" CREATEUSER");
if (datValidUntil->GetValue().IsValid())
sql += wxT("\n VALID UNTIL ") + qtDbString(DateToAnsiStr(datValidUntil->GetValue() + timValidUntil->GetValue()));
else
sql += wxT("\n VALID UNTIL 'infinity'");
sql += wxT(";\n");
int cnt = lbGroupsIn->GetCount();
for (pos = 0 ; pos < cnt ; pos++)
sql += wxT("ALTER GROUP ") + qtIdent(lbGroupsIn->GetString(pos))
+ wxT("\n ADD USER ") + qtIdent(name) + wxT(";\n");
}
wxArrayString vars;
size_t index;
if (user)
{
for (index = 0 ; index < user->GetConfigList().GetCount() ; index++)
vars.Add(user->GetConfigList().Item(index));
}
int cnt = lstVariables->GetItemCount();
// check for changed or added vars
for (pos = 0 ; pos < cnt ; pos++)
{
wxString newVar = lstVariables->GetText(pos);
wxString newVal = lstVariables->GetText(pos, 1);
wxString oldVal;
for (index = 0 ; index < vars.GetCount() ; index++)
{
wxString var = vars.Item(index);
if (var.BeforeFirst('=').IsSameAs(newVar, false))
{
oldVal = var.Mid(newVar.Length() + 1);
vars.RemoveAt(index);
break;
}
}
if (oldVal != newVal)
{
if (newVar != wxT("search_path") && newVar != wxT("temp_tablespaces"))
sql += wxT("ALTER USER ") + qtIdent(name)
+ wxT("\n SET ") + newVar
+ wxT("='") + newVal
+ wxT("';\n");
else
sql += wxT("ALTER USER ") + qtIdent(name)
+ wxT("\n SET ") + newVar
+ wxT("=") + newVal
+ wxT(";\n");
}
}
// check for removed vars
for (pos = 0 ; pos < (int)vars.GetCount() ; pos++)
{
sql += wxT("ALTER USER ") + qtIdent(name)
+ wxT("\n RESET ") + vars.Item(pos).BeforeFirst('=')
+ wxT(";\n");
}
return sql;
}