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:
eelke 2018-12-25 13:17:04 +01:00
parent cc0b28e8e0
commit c2c01cf431
23 changed files with 358 additions and 312 deletions

View file

@ -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 {};
}