Generic GRANT/REVOKE generation from ACL's complete.
Moved the owned concept to PgServerObject as it is needed for the generic acl functionality that is also in PgServerObject.
This commit is contained in:
parent
cc0b28e8e0
commit
c2c01cf431
23 changed files with 358 additions and 312 deletions
190
pglablib/catalog/PgAcl.cpp
Normal file
190
pglablib/catalog/PgAcl.cpp
Normal file
|
|
@ -0,0 +1,190 @@
|
|||
#include "PgAcl.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())));
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
void appendColumn(QString &rights, const QString &column)
|
||||
{
|
||||
if (!column.isEmpty()) {
|
||||
rights += "(" % column % ")";
|
||||
}
|
||||
}
|
||||
|
||||
QString privilegeGrant(const QString &all_pattern, const QString &acl, const QString &grantOnObject, QString user, const QString &column)
|
||||
{
|
||||
QString rights;
|
||||
|
||||
if (user.isEmpty())
|
||||
user = "PUBLIC";
|
||||
|
||||
if (all_pattern.length() > 1 && acl == all_pattern) {
|
||||
rights = "ALL";
|
||||
appendColumn(rights, column);
|
||||
}
|
||||
else {
|
||||
for (auto c : acl) {
|
||||
if (!rights.isEmpty())
|
||||
rights += ", ";
|
||||
rights += privilegeLetterToKeyword(c.toLatin1());
|
||||
appendColumn(rights, column);
|
||||
}
|
||||
}
|
||||
QString grant;
|
||||
if (rights.isEmpty()) {
|
||||
grant += "REVOKE ALL";
|
||||
appendColumn(grant, column);
|
||||
}
|
||||
else
|
||||
grant += "GRANT " + rights;
|
||||
|
||||
grant += " ON " + grantOnObject;
|
||||
|
||||
if (rights.isEmpty())
|
||||
grant += " FROM ";
|
||||
else
|
||||
grant += " TO ";
|
||||
|
||||
grant += user;
|
||||
|
||||
return grant;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
QString PgAcl::sql(const QString &all_pattern, const QString &grant_on_object, const QString &column) const
|
||||
{
|
||||
QString acl, acl_with_grant;
|
||||
// Doorloop acl en scheid de rechten met GRANT optie van die zonder
|
||||
for (auto c : all_pattern) {
|
||||
switch(privilege(c.toLatin1())) {
|
||||
case PrivValue::No:
|
||||
break;
|
||||
case PrivValue::Yes:
|
||||
acl += c;
|
||||
break;
|
||||
case PrivValue::YesWithGrant:
|
||||
acl_with_grant += c;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
QString sql;
|
||||
// Call when acl is not empty or both are empty
|
||||
// needs to be calledwhen both are empty to generate REVOKE
|
||||
if (!acl.isEmpty() || acl_with_grant.isEmpty()) {
|
||||
sql += privilegeGrant(all_pattern, acl, grant_on_object, m_grantee, column)
|
||||
+ ";\n";
|
||||
}
|
||||
if (!acl_with_grant.isEmpty()) {
|
||||
sql += privilegeGrant(all_pattern, acl_with_grant, grant_on_object, m_grantee, column)
|
||||
+ " WITH GRANT OPTION;\n";
|
||||
}
|
||||
return sql;
|
||||
}
|
||||
|
||||
bool PgAcl::empty() const
|
||||
{
|
||||
return m_privileges.isEmpty();
|
||||
}
|
||||
61
pglablib/catalog/PgAcl.h
Normal file
61
pglablib/catalog/PgAcl.h
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
#ifndef PGACL_H
|
||||
#define PGACL_H
|
||||
|
||||
#include "Pgsql_Value.h"
|
||||
#include <QString>
|
||||
#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;
|
||||
|
||||
QString sql(const QString &all_pattern, const QString &grant_on_object, const QString &column) const;
|
||||
// Returns true when the list of privileges is empty
|
||||
bool empty() 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);
|
||||
}
|
||||
|
||||
|
||||
#endif // PGACL_H
|
||||
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
#include "Pgsql_Value.h"
|
||||
#include "PgNamespaceObject.h"
|
||||
#include "PgOwnedObject.h"
|
||||
#include <QString>
|
||||
#include <libpq-fe.h>
|
||||
|
||||
|
|
@ -29,7 +28,7 @@ enum class RelKind {
|
|||
void operator<<(RelKind &s, const Pgsql::Value &v);
|
||||
|
||||
|
||||
class PgClass: public PgNamespaceObject, public PgOwnedObject {
|
||||
class PgClass: public PgNamespaceObject {
|
||||
public:
|
||||
|
||||
// Oid oid = InvalidOid;
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ PgClass PgClassContainer::loadElem(const Pgsql::Row &row)
|
|||
>> v.tuples_est >> v.toastrelid >> v.isshared >> v.persistence
|
||||
>> v.kind >> v.hasoids >> v.ispopulated >> v.frozenxid >> v.minmxid
|
||||
>> v.acl >> v.options;
|
||||
v.setOwnerOid(m_catalog, owner);
|
||||
v.setOwnerOid(owner);
|
||||
// auto&& ns = m_catalog.namespaces()->getByKey(v.relnamespace);
|
||||
// if (ns) {
|
||||
// v.relnamespace_name = ns->objectName();
|
||||
|
|
|
|||
|
|
@ -2,13 +2,12 @@
|
|||
#define PGCOLLATION_H
|
||||
|
||||
#include "PgNamespaceObject.h"
|
||||
#include "PgOwnedObject.h"
|
||||
#include <QString>
|
||||
#include <libpq-fe.h>
|
||||
#include "Pgsql_Value.h"
|
||||
//#include <vector>
|
||||
|
||||
class PgCollation: public PgNamespaceObject, public PgOwnedObject {
|
||||
class PgCollation: public PgNamespaceObject {
|
||||
public:
|
||||
using PgNamespaceObject::PgNamespaceObject;
|
||||
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ PgCollation PgCollationContainer::loadElem(const Pgsql::Row &row)
|
|||
Oid owner ;
|
||||
|
||||
col >> owner >> v.collencoding >> v.collcollate >> v.collctype;
|
||||
v.setOwnerOid(m_catalog, owner);
|
||||
v.setOwnerOid(owner);
|
||||
|
||||
return v;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -123,7 +123,7 @@ public:
|
|||
using t_Elem = std::shared_ptr<T>;
|
||||
using t_Container = std::vector<t_Elem>; ///< Do not assume it will stay a vector only expect bidirectional access
|
||||
|
||||
explicit PgSPtrContainer(std::weak_ptr<PgDatabaseCatalog> cat)
|
||||
explicit PgSPtrContainer(PgDatabaseCatalog& cat)
|
||||
: IPgContainer(cat)
|
||||
{}
|
||||
|
||||
|
|
@ -145,7 +145,7 @@ public:
|
|||
|
||||
int count() const
|
||||
{
|
||||
return (int)m_container.size();
|
||||
return static_cast<int>(m_container.size());
|
||||
}
|
||||
|
||||
const t_Elem getByKey(const K &key) const
|
||||
|
|
|
|||
|
|
@ -2,12 +2,11 @@
|
|||
#define PGLANGUAGE_H
|
||||
|
||||
#include "PgDatabaseObject.h"
|
||||
#include "PgOwnedObject.h"
|
||||
#include <QString>
|
||||
#include <libpq-fe.h>
|
||||
//#include "Pgsql_Value.h"
|
||||
|
||||
class PgLanguage: public PgDatabaseObject, public PgOwnedObject {
|
||||
class PgLanguage: public PgDatabaseObject {
|
||||
public:
|
||||
|
||||
// Oid oid;
|
||||
|
|
|
|||
|
|
@ -17,6 +17,6 @@ PgLanguage PgLanguageContainer::loadElem(const Pgsql::Row &row)
|
|||
Oid owner = col.nextValue();
|
||||
PgLanguage v(m_catalog, lan_oid, name);
|
||||
col >> v.ispl >> v.pltrusted >> v.plcallfoid >> v.inline_ >> v.validator >> v.acl;
|
||||
v.setOwnerOid(m_catalog, owner);
|
||||
v.setOwnerOid(owner);
|
||||
return v;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ public:
|
|||
QString nsName() const;
|
||||
QString quotedNsName() const;
|
||||
/// Returns the schema name and object name with proper quotes
|
||||
QString fullyQualifiedQuotedObjectName() const;
|
||||
QString fullyQualifiedQuotedObjectName() const override;
|
||||
|
||||
const PgNamespace& ns() const;
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -25,6 +25,11 @@ QString PgObject::quotedObjectName() const
|
|||
return quoteIdent(objectName());
|
||||
}
|
||||
|
||||
QString PgObject::fullyQualifiedQuotedObjectName() const
|
||||
{
|
||||
return quotedObjectName();
|
||||
}
|
||||
|
||||
const PgDatabaseCatalog& PgObject::catalog() const
|
||||
{
|
||||
return *m_catalog;
|
||||
|
|
|
|||
|
|
@ -15,6 +15,9 @@ public:
|
|||
const QString& objectName() const;
|
||||
/// Default implementation uses objectName and add quotes when needed.
|
||||
virtual QString quotedObjectName() const;
|
||||
/// By default same as quotedObjectName however for objects that reside in namespaces
|
||||
/// the namespace name is added to the name.
|
||||
virtual QString fullyQualifiedQuotedObjectName() const;
|
||||
virtual QString typeName() const = 0;
|
||||
|
||||
bool operator==(Oid _oid) const { return m_oid == _oid; }
|
||||
|
|
|
|||
|
|
@ -1,32 +0,0 @@
|
|||
#include "PgOwnedObject.h"
|
||||
#include "PgAuthId.h"
|
||||
#include "PgAuthIdContainer.h"
|
||||
#include "PgDatabaseCatalog.h"
|
||||
#include "SqlFormattingUtils.h"
|
||||
|
||||
void PgOwnedObject::setOwnerOid(PgDatabaseCatalog& cat, Oid oid)
|
||||
{
|
||||
m_ownerOid = oid;
|
||||
m_owner = cat.authIds()->getByKey(oid);
|
||||
}
|
||||
|
||||
Oid PgOwnedObject::ownerOid() const
|
||||
{
|
||||
return m_ownerOid;
|
||||
}
|
||||
|
||||
QString PgOwnedObject::ownerName() const
|
||||
{
|
||||
return m_owner->name;
|
||||
}
|
||||
|
||||
const PgAuthId* PgOwnedObject::owner() const
|
||||
{
|
||||
return m_owner;
|
||||
}
|
||||
|
||||
|
||||
QString PgOwnedObject::alterOwnerSql(const QString& ident) const
|
||||
{
|
||||
return QString("\nALTER %1 OWNER TO %2;").arg(ident, quoteIdent(ownerName()));
|
||||
}
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
#ifndef PGOWNEDOBJECT_H
|
||||
#define PGOWNEDOBJECT_H
|
||||
|
||||
#include <QString>
|
||||
#include <libpq-fe.h>
|
||||
#include <memory>
|
||||
|
||||
class PgDatabaseCatalog;
|
||||
class PgAuthId;
|
||||
class PgOwnedObject {
|
||||
public:
|
||||
void setOwnerOid(PgDatabaseCatalog& cat, Oid oid);
|
||||
|
||||
Oid ownerOid() const;
|
||||
QString ownerName() const;
|
||||
const PgAuthId* owner() const;
|
||||
|
||||
QString alterOwnerSql(const QString& ident) const;
|
||||
private:
|
||||
Oid m_ownerOid = InvalidOid;
|
||||
const PgAuthId * m_owner;
|
||||
};
|
||||
|
||||
#endif // PGOWNEDOBJECT_H
|
||||
|
|
@ -344,6 +344,7 @@ const QString& PgProc::createSql() const
|
|||
// + GetGrant(wxT("X"), wxT("FUNCTION ") + qtSig);
|
||||
|
||||
sql += alterOwnerSql("FUNCTION " + quoted_sig);
|
||||
sql += grantSql();
|
||||
|
||||
// if (!GetComment().IsNull())
|
||||
// {
|
||||
|
|
@ -384,3 +385,9 @@ QString PgProc::typeName() const
|
|||
}
|
||||
throw std::runtime_error("Unexpected kind in PgProc::typeName()");
|
||||
}
|
||||
|
||||
QString PgProc::aclAllPattern() const
|
||||
{
|
||||
// X = execute
|
||||
return "X";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
#define PGPROC_H
|
||||
|
||||
#include "PgNamespaceObject.h"
|
||||
#include "PgOwnedObject.h"
|
||||
#include <QString>
|
||||
#include <libpq-fe.h>
|
||||
#include "Pgsql_Value.h"
|
||||
|
|
@ -52,7 +51,7 @@ void operator<<(ParallelMode &s, const Pgsql::Value &v);
|
|||
QString parallelModeToSql(ParallelMode pm, bool explicit_unsafe = false);
|
||||
|
||||
|
||||
class PgProc: public PgNamespaceObject, public PgOwnedObject {
|
||||
class PgProc: public PgNamespaceObject {
|
||||
public:
|
||||
using PgNamespaceObject::PgNamespaceObject;
|
||||
|
||||
|
|
@ -98,6 +97,7 @@ public:
|
|||
bool isWindow() const { return kind == ProcKind::Window; }
|
||||
|
||||
QString typeName() const override;
|
||||
QString aclAllPattern() const override;
|
||||
// bool isTrigger() const
|
||||
// {
|
||||
// return typname == wxT("\"trigger\"") || typname == wxT("trigger") || typname == wxT("event_trigger") || typname == wxT("\"event_trigger\""))
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ PgProc PgProcContainer::loadElem(const Pgsql::Row &row)
|
|||
//ProcKind
|
||||
|
||||
PgProc v(m_catalog, oid, name, namespace_oid);
|
||||
v.setOwnerOid(m_catalog, owner_oid);
|
||||
v.setOwnerOid(owner_oid);
|
||||
col >> v.lang >> v.cost >> v.rows
|
||||
>> v.variadic >> v.transform >> v.secdef >> v.leakproof
|
||||
>> v.isstrict >> v.retset >> v.provolatile >> v.nargs >> v.nargdefaults
|
||||
|
|
|
|||
|
|
@ -1,110 +1,40 @@
|
|||
#include "PgServerObject.h"
|
||||
#include "ArrayParser.h"
|
||||
#include "PgAuthIdContainer.h"
|
||||
#include "PgDatabaseCatalog.h"
|
||||
#include "SqlFormattingUtils.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)
|
||||
void PgServerObject::setOwnerOid(Oid oid)
|
||||
{
|
||||
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");
|
||||
m_ownerOid = oid;
|
||||
m_owner = catalog().authIds()->getByKey(oid);
|
||||
}
|
||||
|
||||
PgAcl::PgAcl(const QString &acl)
|
||||
Oid PgServerObject::ownerOid() const
|
||||
{
|
||||
setFromString(acl);
|
||||
return m_ownerOid;
|
||||
}
|
||||
|
||||
void PgAcl::setFromString(const QString &acl)
|
||||
QString PgServerObject::ownerName() const
|
||||
{
|
||||
m_grantee = acl.section('=', 0, 0);
|
||||
auto t = acl.section('=', 1);
|
||||
m_privileges = t.section('/', 0, 0);
|
||||
m_grantor = t.section('/', 1);
|
||||
return m_owner->name;
|
||||
}
|
||||
|
||||
PrivValue PgAcl::privilege(Privilege priv) const
|
||||
const PgAuthId* PgServerObject::owner() const
|
||||
{
|
||||
char c = privilegeToChar(priv);
|
||||
return privilege(c);
|
||||
return m_owner;
|
||||
}
|
||||
|
||||
PrivValue PgAcl::privilege(char c) const
|
||||
|
||||
QString PgServerObject::alterOwnerSql(const QString& ident) 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())));
|
||||
}
|
||||
return QString("\nALTER %1 OWNER TO %2;").arg(ident, quoteIdent(ownerName()));
|
||||
}
|
||||
|
||||
|
||||
void PgServerObject::setAcls(AclList acls)
|
||||
void PgServerObject::setAcls(boost::optional<AclList> acls)
|
||||
{
|
||||
m_acls = std::move(acls);
|
||||
}
|
||||
|
|
@ -112,100 +42,46 @@ void PgServerObject::setAcls(AclList acls)
|
|||
QString PgServerObject::aclString() const
|
||||
{
|
||||
QString result;
|
||||
for (auto&& acl : m_acls) {
|
||||
if (result.isEmpty()) result += "{";
|
||||
else result += ",";
|
||||
result += acl.singleString();
|
||||
if (m_acls) {
|
||||
for (auto&& acl : *m_acls) {
|
||||
if (result.isEmpty()) result += "{";
|
||||
else result += ",";
|
||||
result += acl.singleString();
|
||||
}
|
||||
if (!result.isEmpty())
|
||||
result += "}";
|
||||
}
|
||||
if (!result.isEmpty())
|
||||
result += "}";
|
||||
return result;
|
||||
}
|
||||
|
||||
QString PgServerObject::grantSql(const QString &all_pattern, const QString &grantee, const QString &column) const
|
||||
QString PgServerObject::grantSql() const
|
||||
{
|
||||
// object_type_and_name => TABLE X
|
||||
// GRANT ??? ON object_type_and_name TO ...
|
||||
|
||||
const QString column; ///< \todo should be set when called on a column object
|
||||
|
||||
QString all_pattern = aclAllPattern();
|
||||
if (all_pattern.isEmpty())
|
||||
return {};
|
||||
|
||||
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));
|
||||
// }
|
||||
// }
|
||||
auto grant_on_object = QString("%1 %2").arg(typeName(), fullyQualifiedQuotedObjectName());
|
||||
if (m_acls) {
|
||||
for (auto&& acl : *m_acls) {
|
||||
grant += acl.sql(all_pattern, grant_on_object, column);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// PUBLIC, no priviliges
|
||||
grant += PgAcl("=").sql(all_pattern, grant_on_object, column);
|
||||
// owner no privileges
|
||||
grant += PgAcl(ownerName() + "=").sql(all_pattern, grant_on_object, column);
|
||||
}
|
||||
return grant;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
QString PgServerObject::aclAllPattern() const
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,56 +3,10 @@
|
|||
|
||||
#include <QString>
|
||||
#include "PgObject.h"
|
||||
#include "Pgsql_Value.h"
|
||||
#include <vector>
|
||||
#include "PgAcl.h"
|
||||
#include <boost/optional.hpp>
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
class PgAuthId;
|
||||
|
||||
/// Base object for objects that belong to a server
|
||||
class PgServerObject: public PgObject {
|
||||
|
|
@ -60,26 +14,36 @@ public:
|
|||
using PgObject::PgObject;
|
||||
|
||||
|
||||
void setOwnerOid(Oid oid);
|
||||
Oid ownerOid() const;
|
||||
QString ownerName() const;
|
||||
const PgAuthId* owner() const;
|
||||
QString alterOwnerSql(const QString& ident) const;
|
||||
|
||||
/**
|
||||
* @brief setAcls Takes the acl array as stored by postgres as a single string
|
||||
* and decodes it directly into an AclList.
|
||||
* @param acls
|
||||
*
|
||||
* @brief setAcls
|
||||
* @param acls Important: pass empty optional when acl IS NULL, pass empty list for empty array
|
||||
*/
|
||||
void setAcls(AclList acls);
|
||||
void setAcls(boost::optional<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;
|
||||
QString grantSql() const;
|
||||
|
||||
/**
|
||||
* @brief Returns a string containing all the possible privileges for this type of object.
|
||||
*
|
||||
* The default implementation returns an empty string.
|
||||
*
|
||||
* @return A string containing all posible privileges for this type of object.
|
||||
*/
|
||||
virtual QString aclAllPattern() const;
|
||||
private:
|
||||
AclList m_acls;
|
||||
Oid m_ownerOid = InvalidOid;
|
||||
const PgAuthId * m_owner;
|
||||
boost::optional<AclList> m_acls;
|
||||
};
|
||||
|
||||
#endif // PGSERVEROBJECT_H
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
#define PGTYPE_H
|
||||
|
||||
#include "PgNamespaceObject.h"
|
||||
#include "PgOwnedObject.h"
|
||||
#include <QString>
|
||||
#include <libpq-fe.h>
|
||||
#include "Pgsql_Value.h"
|
||||
|
|
@ -28,7 +27,7 @@ enum class TypCategory {
|
|||
void operator<<(TypCategory &s, const Pgsql::Value &v);
|
||||
|
||||
|
||||
class PgType: public PgNamespaceObject, public PgOwnedObject {
|
||||
class PgType: public PgNamespaceObject {
|
||||
public:
|
||||
// Oid oid = InvalidOid;
|
||||
// QString name; // formatted name as per database, arrays
|
||||
|
|
|
|||
|
|
@ -26,6 +26,6 @@ PgType PgTypeContainer::loadElem(const Pgsql::Row &row)
|
|||
>> v.ispreferred >> v.isdefined >> v.delim >> v.relid >> v.elem >> v.array >> v.input >> v.output
|
||||
>> v.receive >> v.send >> v.modin >> v.modout >> v.analyze >> v.align >> v.storage >> v.notnull
|
||||
>> v.basetype >> v.typmod >> v.ndims >> v.collation >> v.defaultbin >> v.typdefault >> v.acl;
|
||||
v.setOwnerOid(m_catalog, owner);
|
||||
v.setOwnerOid(owner);
|
||||
return v;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue