PgServerObject now contains a list of acl's for the object so all the different objects
can use this implementation.
This commit is contained in:
parent
efb3e71556
commit
93c8b49f61
6 changed files with 284 additions and 36 deletions
|
|
@ -87,7 +87,7 @@ QVariant ProcTableModel::getData(const QModelIndex &index) const
|
||||||
if (lan) return lan->objectName();
|
if (lan) return lan->objectName();
|
||||||
return t.lang;
|
return t.lang;
|
||||||
}
|
}
|
||||||
case AclCol: return t.acl;
|
case AclCol: return t.aclString();
|
||||||
}
|
}
|
||||||
return QVariant();
|
return QVariant();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -410,24 +410,3 @@ QString getConstraintDefinition(const PgDatabaseCatalog &catalog, const PgConstr
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//rolename=xxxx -- privileges granted to a role
|
|
||||||
// =xxxx -- privileges granted to PUBLIC
|
|
||||||
|
|
||||||
// r -- SELECT ("read")
|
|
||||||
// w -- UPDATE ("write")
|
|
||||||
// a -- INSERT ("append")
|
|
||||||
// d -- DELETE
|
|
||||||
// D -- TRUNCATE
|
|
||||||
// x -- REFERENCES
|
|
||||||
// t -- TRIGGER
|
|
||||||
// X -- EXECUTE
|
|
||||||
// U -- USAGE
|
|
||||||
// C -- CREATE
|
|
||||||
// c -- CONNECT
|
|
||||||
// T -- TEMPORARY
|
|
||||||
// arwdDxt -- ALL PRIVILEGES (for tables, varies for other objects)
|
|
||||||
// * -- grant option for preceding privilege
|
|
||||||
|
|
||||||
// /yyyy -- role that granted this privilege
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -56,17 +56,11 @@ class PgProc: public PgNamespaceObject, public PgOwnedObject {
|
||||||
public:
|
public:
|
||||||
using PgNamespaceObject::PgNamespaceObject;
|
using PgNamespaceObject::PgNamespaceObject;
|
||||||
|
|
||||||
// Oid oid = InvalidOid; // oid
|
|
||||||
// QString name; // name
|
|
||||||
// Oid pronamespace = InvalidOid; // oid, namespace
|
|
||||||
// Oid owner = InvalidOid; // oid
|
|
||||||
Oid lang = InvalidOid; // oid
|
Oid lang = InvalidOid; // oid
|
||||||
float cost = 0.f; // float4
|
float cost = 0.f; // float4
|
||||||
float rows = 0.f; // float4
|
float rows = 0.f; // float4
|
||||||
Oid variadic = InvalidOid; // oid
|
Oid variadic = InvalidOid; // oid
|
||||||
QString transform; // regproc
|
QString transform; // regproc
|
||||||
// bool isagg = false; // bool < 11
|
|
||||||
// bool iswindow = false; // bool << 11
|
|
||||||
ProcKind kind = ProcKind::Function; // >= 11
|
ProcKind kind = ProcKind::Function; // >= 11
|
||||||
bool secdef = false; // bool
|
bool secdef = false; // bool
|
||||||
bool leakproof = false; // bool
|
bool leakproof = false; // bool
|
||||||
|
|
@ -81,7 +75,6 @@ public:
|
||||||
QString src; // text
|
QString src; // text
|
||||||
QString bin; // text
|
QString bin; // text
|
||||||
std::vector<QString> config; // text[]
|
std::vector<QString> config; // text[]
|
||||||
QString acl; // aclitem[]
|
|
||||||
|
|
||||||
/// Converts the collection of arrays about the arguments to a single list of arguments
|
/// Converts the collection of arrays about the arguments to a single list of arguments
|
||||||
/// making it much easier to work with them correctly
|
/// making it much easier to work with them correctly
|
||||||
|
|
@ -94,11 +87,6 @@ public:
|
||||||
);
|
);
|
||||||
const std::vector<Arg>& args() const;
|
const std::vector<Arg>& args() const;
|
||||||
|
|
||||||
// bool operator==(Oid _oid) const { return oid == _oid; }
|
|
||||||
// bool operator==(const QString &n) const { return name == n; }
|
|
||||||
// bool operator<(Oid _oid) const { return oid < _oid; }
|
|
||||||
// bool operator<(const PgProc &rhs) const { return oid < rhs.oid; }
|
|
||||||
|
|
||||||
const QString& createSql() const;
|
const QString& createSql() const;
|
||||||
QString argListWithNames(bool multiline = false) const;
|
QString argListWithNames(bool multiline = false) const;
|
||||||
QString argSigList(const bool forScript = false) const;
|
QString argSigList(const bool forScript = false) const;
|
||||||
|
|
|
||||||
|
|
@ -49,8 +49,10 @@ PgProc PgProcContainer::loadElem(const Pgsql::Row &row)
|
||||||
std::optional<QString> argdefaults; // pg_node_tree
|
std::optional<QString> argdefaults; // pg_node_tree
|
||||||
col.getAsVector<Oid>(std::back_inserter(argtypes));
|
col.getAsVector<Oid>(std::back_inserter(argtypes));
|
||||||
col >> allargtypes >> argmodes >> argnames >> argdefaults
|
col >> allargtypes >> argmodes >> argnames >> argdefaults
|
||||||
>> v.src >> v.bin >> v.config >> v.acl;
|
>> v.src >> v.bin >> v.config; // >> v.acl;
|
||||||
|
AclList acl_list;
|
||||||
|
col >> acl_list;
|
||||||
|
v.setAcls(std::move(acl_list));
|
||||||
v.setArgs(argtypes, allargtypes, argmodes, argnames, argdefaults);
|
v.setArgs(argtypes, allargtypes, argmodes, argnames, argdefaults);
|
||||||
|
|
||||||
if (minimumVersion(90500)) {
|
if (minimumVersion(90500)) {
|
||||||
|
|
|
||||||
|
|
@ -1,2 +1,211 @@
|
||||||
#include "PgServerObject.h"
|
#include "PgServerObject.h"
|
||||||
|
#include "ArrayParser.h"
|
||||||
|
#include <QStringBuilder>
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
QString privilegeLetterToKeyword(char c)
|
||||||
|
{
|
||||||
|
switch (c) {
|
||||||
|
case 'r': return "SELECT";
|
||||||
|
case 'w': return "UPDATE";
|
||||||
|
case 'a': return "INSERT";
|
||||||
|
case 'd': return "DELETE";
|
||||||
|
case 'D': return "TRUNCATE";
|
||||||
|
case 'x': return "REFERENCES";
|
||||||
|
case 't': return "TRIGGER";
|
||||||
|
case 'X': return "EXECUTE";
|
||||||
|
case 'U': return "USAGE";
|
||||||
|
case 'C': return "CREATE";
|
||||||
|
case 'c': return "CONNECT";
|
||||||
|
case 'T': return "TEMPORARY";
|
||||||
|
}
|
||||||
|
throw std::runtime_error("Unexpected value for c in privilegeLetterToKeyword");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
char privilegeToChar(Privilege p)
|
||||||
|
{
|
||||||
|
switch (p) {
|
||||||
|
case Privilege::Select: return 'r';
|
||||||
|
case Privilege::Update: return 'w';
|
||||||
|
case Privilege::Insert: return 'a';
|
||||||
|
case Privilege::Delete: return 'd';
|
||||||
|
case Privilege::Truncate: return 'D';
|
||||||
|
case Privilege::References: return 'x';
|
||||||
|
case Privilege::Trigger: return 't';
|
||||||
|
case Privilege::Execute: return 'X';
|
||||||
|
case Privilege::Usage: return 'U';
|
||||||
|
case Privilege::Create: return 'C';
|
||||||
|
case Privilege::Connect: return 'c';
|
||||||
|
case Privilege::Temporary: return 'T';
|
||||||
|
}
|
||||||
|
throw std::runtime_error("Unexpected value for privilege in privilegeToChar");
|
||||||
|
}
|
||||||
|
|
||||||
|
PgAcl::PgAcl(const QString &acl)
|
||||||
|
{
|
||||||
|
setFromString(acl);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PgAcl::setFromString(const QString &acl)
|
||||||
|
{
|
||||||
|
m_grantee = acl.section('=', 0, 0);
|
||||||
|
auto t = acl.section('=', 1);
|
||||||
|
m_privileges = t.section('/', 0, 0);
|
||||||
|
m_grantor = t.section('/', 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
PrivValue PgAcl::privilege(Privilege priv) const
|
||||||
|
{
|
||||||
|
char c = privilegeToChar(priv);
|
||||||
|
return privilege(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
PrivValue PgAcl::privilege(char c) const
|
||||||
|
{
|
||||||
|
int pos = m_privileges.indexOf(c);
|
||||||
|
if (pos >= 0) {
|
||||||
|
if ( (pos+1) < m_privileges.length() && m_privileges[pos+1] == '*')
|
||||||
|
return PrivValue::YesWithGrant;
|
||||||
|
return PrivValue::Yes;
|
||||||
|
}
|
||||||
|
return PrivValue::No;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString PgAcl::singleString() const
|
||||||
|
{
|
||||||
|
return m_grantee % "=" % m_privileges % "/" % m_grantor;
|
||||||
|
}
|
||||||
|
|
||||||
|
//void operator<<(AclList &s, const Pgsql::Value &v)
|
||||||
|
void operator<<(PgAcl &acl, const Pgsql::Value &v)
|
||||||
|
{
|
||||||
|
acl.setFromString(v);
|
||||||
|
// const char *c = v.c_str();
|
||||||
|
// Pgsql::ArrayParser parser(c);
|
||||||
|
|
||||||
|
// while (true) {
|
||||||
|
// auto elem = parser.GetNextElem();
|
||||||
|
// if (!elem.ok)
|
||||||
|
// break;
|
||||||
|
// auto&& v = elem.value.value_or("");
|
||||||
|
// s.emplace_back(QString(v.data()));
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Pgsql {
|
||||||
|
template <>
|
||||||
|
PgAcl StringToArrayElem<PgAcl>(std::string_view sv)
|
||||||
|
{
|
||||||
|
return PgAcl(QString::fromUtf8(sv.data(), static_cast<int>(sv.length())));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PgServerObject::setAcls(AclList acls)
|
||||||
|
{
|
||||||
|
m_acls = std::move(acls);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString PgServerObject::aclString() const
|
||||||
|
{
|
||||||
|
QString result;
|
||||||
|
for (auto&& acl : m_acls) {
|
||||||
|
if (result.isEmpty()) result += "{";
|
||||||
|
else result += ",";
|
||||||
|
result += acl.singleString();
|
||||||
|
}
|
||||||
|
if (!result.isEmpty())
|
||||||
|
result += "}";
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString PgServerObject::grantSql(const QString &all_pattern, const QString &grantee, const QString &column) const
|
||||||
|
{
|
||||||
|
QString grant;
|
||||||
|
// wxString grant, str, user, grantFor, tmpUser;
|
||||||
|
|
||||||
|
// if (_grantFor.IsNull())
|
||||||
|
// {
|
||||||
|
// grantFor = GetTypeName();
|
||||||
|
// grantFor.MakeUpper();
|
||||||
|
// grantFor += wxT(" ") + GetQuotedFullIdentifier();
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// grantFor = _grantFor;
|
||||||
|
|
||||||
|
// if (!acl.IsNull())
|
||||||
|
// {
|
||||||
|
// if (acl == wxT("{}"))
|
||||||
|
// {
|
||||||
|
// grant += GetPrivileges(allPattern, str, grantFor, wxT("public"), qtIdent(_column));
|
||||||
|
// grant += GetPrivileges(allPattern, str, grantFor, qtIdent(owner), qtIdent(_column));
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
// // checks if certain privilege is granted to public
|
||||||
|
// bool grantedToPublic = false;
|
||||||
|
// // checks if certain privilege is granted to owner
|
||||||
|
// bool grantedToOwner = false;
|
||||||
|
|
||||||
|
// queryTokenizer acls(acl.Mid(1, acl.Length() - 2), ',');
|
||||||
|
// while (acls.HasMoreTokens())
|
||||||
|
// {
|
||||||
|
// str = acls.GetNextToken();
|
||||||
|
|
||||||
|
// if (str.Left(1) == '"')
|
||||||
|
// str = str.Mid(1, str.Length() - 2);
|
||||||
|
// user = str.BeforeFirst('=');
|
||||||
|
// str = str.AfterFirst('=').BeforeFirst('/');
|
||||||
|
// if (user == wxT(""))
|
||||||
|
// {
|
||||||
|
// user = wxT("public");
|
||||||
|
// grantedToPublic = true;
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
// if (user.Left(6) == wxT("group "))
|
||||||
|
// {
|
||||||
|
// tmpUser = user.Mid(6);
|
||||||
|
// if (user.Mid(6).StartsWith(wxT("\\\"")) && user.Mid(6).EndsWith(wxT("\\\"")))
|
||||||
|
// user = wxT("GROUP ") + qtIdent(user.Mid(8, user.Length() - 10));
|
||||||
|
// else
|
||||||
|
// user = wxT("GROUP ") + qtIdent(user.Mid(6));
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
// tmpUser = user;
|
||||||
|
// if (user.StartsWith(wxT("\\\"")) && user.EndsWith(wxT("\\\"")))
|
||||||
|
// user = qtIdent(user.Mid(2, user.Length() - 4));
|
||||||
|
// else
|
||||||
|
// user = qtIdent(user);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if (tmpUser.Contains(owner))
|
||||||
|
// grantedToOwner = true;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// grant += GetPrivileges(allPattern, str, grantFor, user, qtIdent(_column));
|
||||||
|
// }
|
||||||
|
|
||||||
|
// str = wxEmptyString;
|
||||||
|
// int metaType = GetMetaType();
|
||||||
|
|
||||||
|
// // We check here that whether the user has revoked prvileges granted to databases, functions
|
||||||
|
// // and languages. If so then this must be part of reverse engineered sql statement
|
||||||
|
// if (!grantedToPublic && (metaType == PGM_LANGUAGE || metaType == PGM_FUNCTION || metaType == PGM_DATABASE))
|
||||||
|
// grant += GetPrivileges(allPattern, str, grantFor, wxT("public"), qtIdent(_column));
|
||||||
|
// // We check here that whether the owner has revoked prvileges on himself to this postgres
|
||||||
|
// // object. If so then this must be part of reverse engineered sql statement
|
||||||
|
// if (!grantedToOwner)
|
||||||
|
// grant += GetPrivileges(allPattern, str, grantFor, qtIdent(owner), qtIdent(_column));
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
return grant;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,13 +3,83 @@
|
||||||
|
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include "PgObject.h"
|
#include "PgObject.h"
|
||||||
|
#include "Pgsql_Value.h"
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
|
||||||
|
enum class Privilege {
|
||||||
|
Select,
|
||||||
|
Update,
|
||||||
|
Insert,
|
||||||
|
Delete,
|
||||||
|
Truncate,
|
||||||
|
References,
|
||||||
|
Trigger,
|
||||||
|
Execute,
|
||||||
|
Usage,
|
||||||
|
Create,
|
||||||
|
Connect,
|
||||||
|
Temporary
|
||||||
|
};
|
||||||
|
|
||||||
|
char privilegeToChar(Privilege p);
|
||||||
|
|
||||||
|
enum class PrivValue {
|
||||||
|
No, Yes, YesWithGrant
|
||||||
|
};
|
||||||
|
|
||||||
|
class PgAcl {
|
||||||
|
public:
|
||||||
|
PgAcl() = default;
|
||||||
|
explicit PgAcl(const QString &acl);
|
||||||
|
void setFromString(const QString &acl);
|
||||||
|
|
||||||
|
PrivValue privilege(Privilege priv) const;
|
||||||
|
PrivValue privilege(char c) const;
|
||||||
|
const QString& grantee() const { return m_grantee; }
|
||||||
|
const QString& grantor() const { return m_grantor; }
|
||||||
|
QString singleString() const;
|
||||||
|
private:
|
||||||
|
QString m_grantee;
|
||||||
|
QString m_grantor;
|
||||||
|
QString m_privileges;
|
||||||
|
};
|
||||||
|
|
||||||
|
using AclList = std::vector<PgAcl>;
|
||||||
|
|
||||||
|
void operator<<(PgAcl &acl, const Pgsql::Value &v);
|
||||||
|
|
||||||
|
namespace Pgsql {
|
||||||
|
template <>
|
||||||
|
PgAcl StringToArrayElem<PgAcl>(std::string_view sv);
|
||||||
|
}
|
||||||
|
|
||||||
/// Base object for objects that belong to a server
|
/// Base object for objects that belong to a server
|
||||||
class PgServerObject: public PgObject {
|
class PgServerObject: public PgObject {
|
||||||
public:
|
public:
|
||||||
using PgObject::PgObject;
|
using PgObject::PgObject;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief setAcls Takes the acl array as stored by postgres as a single string
|
||||||
|
* and decodes it directly into an AclList.
|
||||||
|
* @param acls
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void setAcls(AclList acls);
|
||||||
|
QString aclString() const;
|
||||||
|
/**
|
||||||
|
* @brief grantSql
|
||||||
|
* @param all_pattern Used to recognize when a GRANT ALL can be generated but also to not consider irrelevant letters.
|
||||||
|
* @param grantee
|
||||||
|
* @param column
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
QString grantSql(const QString &all_pattern, const QString &grantee, const QString &column) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
AclList m_acls;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // PGSERVEROBJECT_H
|
#endif // PGSERVEROBJECT_H
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue