mirror of
https://github.com/QuasarApp/Heart.git
synced 2025-05-05 22:19:41 +00:00
fix permissions control
This commit is contained in:
parent
93cf082080
commit
f135c38e7c
@ -377,7 +377,7 @@ bool AbstractNode::registerSocket(QAbstractSocket *socket, const HostAddress* cl
|
||||
ParserResult AbstractNode::parsePackage(const Package &pkg,
|
||||
const AbstractNodeInfo *sender) {
|
||||
|
||||
if (!(sender && sender->isValid())) {
|
||||
if (!(sender)) {
|
||||
QuasarAppUtils::Params::log("sender socket is not valid!",
|
||||
QuasarAppUtils::Error);
|
||||
return ParserResult::Error;
|
||||
@ -436,12 +436,7 @@ bool AbstractNode::sendPackage(const Package &pkg, QAbstractSocket *target) cons
|
||||
return false;
|
||||
}
|
||||
|
||||
return QMetaObject::invokeMethod(const_cast<DataSender*>(_dataSender),
|
||||
"sendPackagePrivate",
|
||||
Qt::QueuedConnection,
|
||||
Q_ARG(QByteArray, pkg.toBytes()),
|
||||
Q_ARG(void*, target));
|
||||
|
||||
return _dataSender->sendData(pkg.toBytes(), target, true);
|
||||
}
|
||||
|
||||
bool AbstractNode::sendData(AbstractData *resp,
|
||||
|
@ -51,13 +51,13 @@ bool Async::waitFor(bool *condition, int timeout) const {
|
||||
waitPrivate(*condition, timeout)
|
||||
}
|
||||
|
||||
bool Async::asyncLauncher(const Async::Job &job, bool await) {
|
||||
bool Async::asyncLauncher(const Async::Job &job, bool await) const {
|
||||
if (QThread::currentThread() == thread()) {
|
||||
return job();
|
||||
}
|
||||
|
||||
if (!await) {
|
||||
return QMetaObject::invokeMethod(this,
|
||||
return QMetaObject::invokeMethod(const_cast<Async*>(this),
|
||||
"asyncHandler",
|
||||
Qt::QueuedConnection,
|
||||
Q_ARG(QH::Async::Job, job));
|
||||
@ -65,7 +65,7 @@ bool Async::asyncLauncher(const Async::Job &job, bool await) {
|
||||
|
||||
bool workOfEnd = false, workResult = false;
|
||||
|
||||
bool invockeResult = QMetaObject::invokeMethod(this,
|
||||
bool invockeResult = QMetaObject::invokeMethod(const_cast<Async*>(this),
|
||||
"asyncHandler",
|
||||
Qt::QueuedConnection,
|
||||
Q_ARG(QH::Async::Job, job),
|
||||
|
@ -57,7 +57,7 @@ protected:
|
||||
* @return true if the job function started correctly. IF the await option is true then
|
||||
* this method return result of job function.
|
||||
*/
|
||||
bool asyncLauncher(const Job &job, bool await = false);
|
||||
bool asyncLauncher(const Job &job, bool await = false) const;
|
||||
private slots:
|
||||
|
||||
/**
|
||||
|
@ -16,12 +16,18 @@ namespace QH {
|
||||
DataSender::DataSender() {
|
||||
}
|
||||
|
||||
void QH::DataSender::sendPackagePrivate(QByteArray array, void *target) const {
|
||||
bool DataSender::sendData(const QByteArray &array, void *target, bool await) const {
|
||||
return asyncLauncher(std::bind(&DataSender::sendPackagePrivate, this, array, target), await);
|
||||
}
|
||||
|
||||
bool QH::DataSender::sendPackagePrivate(QByteArray array, void *target) const {
|
||||
auto ptr = static_cast<QAbstractSocket*>(target);
|
||||
if (array.size() != ptr->write(array)) {
|
||||
QuasarAppUtils::Params::log("not writed data to socket", QuasarAppUtils::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -9,7 +9,8 @@
|
||||
#ifndef DATASENDER_H
|
||||
#define DATASENDER_H
|
||||
|
||||
#include <QObject>
|
||||
#include "async.h"
|
||||
|
||||
|
||||
class QAbstractSocket;
|
||||
|
||||
@ -19,19 +20,28 @@ namespace QH {
|
||||
* @brief The DataSender class this class create a queue for sendet data to network.
|
||||
* work on a main thread
|
||||
*/
|
||||
class DataSender: public QObject
|
||||
class DataSender: public Async
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
DataSender();
|
||||
|
||||
public slots:
|
||||
/**
|
||||
* @brief sendPackagePrivate This slot move send package to a main threan
|
||||
* @param array bytes to send
|
||||
* @param target This is pointer of target socket
|
||||
* @param await This option force wait for finishing data sending.
|
||||
*/
|
||||
bool sendData(const QByteArray &array, void *target, bool await = false) const;
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* @brief sendPackagePrivate This slot move send package to a main threan
|
||||
* @param array bytes to send
|
||||
* @param target - this is pointer of target socket
|
||||
*/
|
||||
void sendPackagePrivate(QByteArray array, void *target) const;
|
||||
bool sendPackagePrivate(QByteArray array, void *target) const;
|
||||
};
|
||||
}
|
||||
#endif // DATASENDER_H
|
||||
|
@ -9,7 +9,8 @@ CREATE TABLE IF NOT EXISTS NetworkMembers (
|
||||
-- The MemberPermisions table contains link to anothe database object and links to users of the database with permission lvl.
|
||||
CREATE TABLE IF NOT EXISTS MemberPermisions (
|
||||
memberId VARCHAR(32) NOT NULL,
|
||||
dbAddress BLOB NOT NULL,
|
||||
-- This field contatins a base64 implementation of a sha256 (requariment 44 bytes) hash code of a database address
|
||||
dbAddress VARCHAR(44) NOT NULL,
|
||||
lvl tinyint NOT NULL,
|
||||
|
||||
FOREIGN KEY(memberId) REFERENCES NetworkMembers(id)
|
||||
|
@ -244,7 +244,6 @@ ParserResult DataBaseNode::parsePackage(const Package &pkg,
|
||||
WebSocket obj(pkg);
|
||||
|
||||
QVariant requesterId = getSender(sender, &obj);
|
||||
|
||||
if (!obj.isValid()) {
|
||||
badRequest(sender->networkAddress(), pkg.hdr,
|
||||
{
|
||||
@ -280,7 +279,6 @@ ParserResult DataBaseNode::parsePackage(const Package &pkg,
|
||||
auto obj = QSharedPointer<DeleteObject>::create(pkg);
|
||||
|
||||
auto requesterId = getSender(sender, obj.data());
|
||||
|
||||
if (deleteObject(requesterId, obj) == DBOperationResult::Forbidden) {
|
||||
badRequest(sender->networkAddress(), pkg.hdr, {
|
||||
ErrorCodes::OperatioForbiden,
|
||||
@ -493,15 +491,14 @@ DataBaseNode::changeObjects(const QVariant &requester,
|
||||
return result;
|
||||
}
|
||||
|
||||
const QVariant* DataBaseNode::getSender(const AbstractNodeInfo *connectInfo,
|
||||
QVariant DataBaseNode::getSender(const AbstractNodeInfo *connectInfo,
|
||||
const AbstractData *) const {
|
||||
|
||||
auto info = dynamic_cast<const BaseNodeInfo*>(connectInfo);
|
||||
|
||||
if (!info)
|
||||
return nullptr;
|
||||
return {};
|
||||
|
||||
return &info->id();
|
||||
return info->id();
|
||||
}
|
||||
|
||||
DBOperationResult
|
||||
@ -509,18 +506,14 @@ DataBaseNode::checkPermission(const QVariant &requester,
|
||||
const DbAddress &objectAddress,
|
||||
const Permission& requarimentPermision) const {
|
||||
|
||||
if (!requester.isValid())
|
||||
return DBOperationResult::Unknown;
|
||||
|
||||
if (!_db) {
|
||||
return DBOperationResult::Unknown;
|
||||
}
|
||||
|
||||
auto tmp = _db->getObjectRaw(NetworkMember{requester});
|
||||
|
||||
if (!tmp) {
|
||||
return DBOperationResult::Unknown;
|
||||
}
|
||||
|
||||
auto member = tmp.dynamicCast<AbstractNetworkMember>();
|
||||
|
||||
auto member = _db->getObjectRaw(NetworkMember{requester});
|
||||
if (!member) {
|
||||
return DBOperationResult::Unknown;
|
||||
}
|
||||
|
@ -250,7 +250,7 @@ protected:
|
||||
* @param requestData This is data of request.
|
||||
* @return id of requester member.
|
||||
*/
|
||||
virtual const QVariant *getSender(const AbstractNodeInfo *connectInfo, const PKG::AbstractData *requestData) const;
|
||||
virtual QVariant getSender(const AbstractNodeInfo *connectInfo, const PKG::AbstractData *requestData) const;
|
||||
|
||||
/**
|
||||
* @brief checkPermision This method check a permision of requester to database object with objectAddress.
|
||||
|
@ -8,17 +8,20 @@
|
||||
#include "dbaddress.h"
|
||||
#include <QDataStream>
|
||||
#include <QHash>
|
||||
#include <QCryptographicHash>
|
||||
|
||||
|
||||
namespace QH {
|
||||
|
||||
qint64 qHash(const DbAddress &address) {
|
||||
return qHash(address.table() + address.id().toString());
|
||||
return qHash(address.SHA256Hash());
|
||||
}
|
||||
|
||||
DbAddress::DbAddress(const QString &table, const QVariant &id) {
|
||||
this->_table = table;
|
||||
this->_value = id;
|
||||
recalcHash();
|
||||
|
||||
}
|
||||
|
||||
bool operator==(const DbAddress & left, const DbAddress &other) {
|
||||
@ -28,6 +31,8 @@ bool operator==(const DbAddress & left, const DbAddress &other) {
|
||||
QDataStream &DbAddress::fromStream(QDataStream &stream) {
|
||||
stream >> _value;
|
||||
stream >> _table;
|
||||
recalcHash();
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
@ -38,8 +43,8 @@ QDataStream &DbAddress::toStream(QDataStream &stream) const {
|
||||
}
|
||||
|
||||
QString DbAddress::toString() const {
|
||||
return QString("DbAddress: table:%0, value:%1").
|
||||
arg(_table, _value.toString());
|
||||
return QString("DbAddress: table:%0, value:%1, Sha256:%2").
|
||||
arg(_table, _value.toString(), _SHA256Hash.toHex());
|
||||
}
|
||||
|
||||
bool operator!=(const DbAddress &left, const DbAddress &other) {
|
||||
@ -56,6 +61,7 @@ const QString& DbAddress::table() const {
|
||||
|
||||
void DbAddress::setTable(const QString &table) {
|
||||
_table = table;
|
||||
recalcHash();
|
||||
}
|
||||
|
||||
const QVariant &DbAddress::id() const {
|
||||
@ -64,6 +70,15 @@ const QVariant &DbAddress::id() const {
|
||||
|
||||
void DbAddress::setId(const QVariant &id){
|
||||
_value = id;
|
||||
recalcHash();
|
||||
}
|
||||
|
||||
QByteArray DbAddress::SHA256Hash() const {
|
||||
return _SHA256Hash;
|
||||
}
|
||||
|
||||
void DbAddress::recalcHash() {
|
||||
_SHA256Hash = QCryptographicHash::hash(toBytes(), QCryptographicHash::Sha256);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -78,10 +78,20 @@ public:
|
||||
*/
|
||||
void setId(const QVariant &id);
|
||||
|
||||
/**
|
||||
* @brief SHA256Hash This method return address hash.
|
||||
* This hash using into database.
|
||||
* @return return array of the hash of this address.
|
||||
*/
|
||||
QByteArray SHA256Hash() const;
|
||||
|
||||
private:
|
||||
|
||||
void recalcHash();
|
||||
|
||||
QString _table;
|
||||
QVariant _value;
|
||||
QByteArray _SHA256Hash;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -214,7 +214,7 @@ QString DBObject::condition() const {
|
||||
|
||||
// check all objects fields
|
||||
for (auto it = map.begin(); it != map.end(); ++it) {
|
||||
// if field if unique then to
|
||||
// if field is unique then
|
||||
if (bool(it.value().type & MemberType::Unique)) {
|
||||
QVariant::Type type = it.value().value.type();
|
||||
|
||||
|
@ -58,13 +58,12 @@ uint MemberPermisionObject::dbKey() const {
|
||||
|
||||
bool MemberPermisionObject::fromSqlRecord(const QSqlRecord &q) {
|
||||
|
||||
DbAddress address;
|
||||
address.fromBytes(q.value("dbAddress").toByteArray());
|
||||
PermisionData permision(q.value("memberId"),
|
||||
q.value("dbAddress").toString());
|
||||
|
||||
PermisionData permision(q.value("memberId"), address);
|
||||
setKey(permision);
|
||||
|
||||
setPermisions(static_cast<Permission>(q.value("lvl").toUInt()));
|
||||
|
||||
return isValid();
|
||||
}
|
||||
|
||||
@ -89,7 +88,7 @@ QDataStream &MemberPermisionObject::toStream(QDataStream &stream) const {
|
||||
|
||||
DBVariantMap MemberPermisionObject::variantMap() const {
|
||||
return {{"memberId", {_key.id(), MemberType::InsertUpdate}},
|
||||
{"dbAddress", {_key.address().toBytes(), MemberType::InsertUpdate}},
|
||||
{"dbAddress", {_key.addressHash(), MemberType::InsertUpdate}},
|
||||
{"lvl", {static_cast<unsigned char>(_permision), MemberType::InsertUpdate}}};
|
||||
}
|
||||
|
||||
@ -101,9 +100,9 @@ QString MemberPermisionObject::condition() const {
|
||||
|
||||
if (_key.id().isValid()) {
|
||||
if (result.size()) {
|
||||
result += ", ";
|
||||
result += " AND ";
|
||||
}
|
||||
result += "dbAddress=" + _key.address().toBytes();
|
||||
result += "dbAddress='" + _key.addressHash()+ "'";
|
||||
}
|
||||
|
||||
return result;
|
||||
|
@ -15,7 +15,7 @@
|
||||
namespace QH {
|
||||
|
||||
bool operator ==(const PermisionData &left, const PermisionData &right) {
|
||||
return left._id == right._id && left._address == right._address;
|
||||
return left._id == right._id && left._addressHash == right._addressHash;
|
||||
}
|
||||
|
||||
PermisionData::PermisionData(const QVariant &subject, const DbAddress &objcet) {
|
||||
@ -23,17 +23,22 @@ PermisionData::PermisionData(const QVariant &subject, const DbAddress &objcet) {
|
||||
setAddress(objcet);
|
||||
}
|
||||
|
||||
PermisionData::PermisionData(const QVariant &subject, const QString &objectAddress) {
|
||||
setId(subject);
|
||||
setAddress(objectAddress);
|
||||
}
|
||||
|
||||
unsigned int PermisionData::hash() const {
|
||||
QByteArray data;
|
||||
QDataStream stream(&data, QIODevice::WriteOnly);
|
||||
|
||||
stream << _id;
|
||||
stream << _address;
|
||||
stream << _addressHash;
|
||||
return qHash(data);
|
||||
}
|
||||
|
||||
bool PermisionData::isValid() const {
|
||||
return address().isValid() && _id.isValid();
|
||||
return _addressHash.size() && _id.isValid();
|
||||
}
|
||||
|
||||
bool PermisionData::equal(const AbstractKey *other) const {
|
||||
@ -41,32 +46,36 @@ bool PermisionData::equal(const AbstractKey *other) const {
|
||||
if (!otherObject)
|
||||
return false;
|
||||
|
||||
return _address == otherObject->_address && _id == otherObject->_id;
|
||||
return _addressHash == otherObject->_addressHash && _id == otherObject->_id;
|
||||
}
|
||||
|
||||
QString PermisionData::toString() const {
|
||||
return QString("DBAddress: %0, Owner Id: %1").
|
||||
arg(_address.toString(), _id.toString());
|
||||
return QString("DBAddressHash: %0, Owner Id: %1").
|
||||
arg(_addressHash, _id.toString());
|
||||
}
|
||||
|
||||
const DbAddress& PermisionData::address() const {
|
||||
return _address;
|
||||
const QString& PermisionData::addressHash() const {
|
||||
return _addressHash;
|
||||
}
|
||||
|
||||
void PermisionData::setAddress(const DbAddress &address) {
|
||||
_address = address;
|
||||
setAddress(address.SHA256Hash().toBase64(QByteArray::Base64UrlEncoding));
|
||||
}
|
||||
|
||||
void PermisionData::setAddress(const QString &addressHash) {
|
||||
_addressHash = addressHash;
|
||||
}
|
||||
|
||||
QDataStream &PermisionData::fromStream(QDataStream &stream) {
|
||||
stream >> _id;
|
||||
stream >> _address;
|
||||
stream >> _addressHash;
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
QDataStream &PermisionData::toStream(QDataStream &stream) const {
|
||||
stream << _id;
|
||||
stream << _address;
|
||||
stream << _addressHash;
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
@ -25,6 +25,7 @@ public:
|
||||
|
||||
PermisionData() = default;
|
||||
PermisionData(const QVariant& subject, const DbAddress& objcet);
|
||||
PermisionData(const QVariant& subject, const QString& objectAddress);
|
||||
|
||||
friend bool operator == (const PermisionData& left, const PermisionData& right);
|
||||
unsigned int hash() const override;
|
||||
@ -39,10 +40,11 @@ public:
|
||||
void setId(const QVariant &Id);
|
||||
|
||||
/**
|
||||
* @brief address This method return address of database object.
|
||||
* @brief addressHash This method return sha256 hash of the address of database object.
|
||||
* The hash encoded as a base64.
|
||||
* @return address of database object.
|
||||
*/
|
||||
const DbAddress &address() const;
|
||||
const QString &addressHash() const;
|
||||
|
||||
/**
|
||||
* @brief setAddress This method set address of database object.
|
||||
@ -50,6 +52,12 @@ public:
|
||||
*/
|
||||
void setAddress(const DbAddress &address);
|
||||
|
||||
/**
|
||||
* @brief setAddress This implementation sets sh256 hash og the address (hash must be write in base64 encoding)
|
||||
* @param address This is base64 string of a sh256 hash code.
|
||||
*/
|
||||
void setAddress(const QString &addressHash);
|
||||
|
||||
// StreamBase interface
|
||||
const QVariant &id() const;
|
||||
|
||||
@ -63,7 +71,8 @@ private:
|
||||
QVariant _id;
|
||||
|
||||
/// table of target object (second part of key)
|
||||
DbAddress _address;
|
||||
QString _addressHash;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -196,8 +196,7 @@ bool SingleServer::workWithUserRequest(const QSharedPointer<PKG::UserMember>& ob
|
||||
} else if (request->getRequestCmd() == static_cast<quint8>(PKG::UserRequestType::Remove)) {
|
||||
|
||||
auto requesterId = getSender(sender, obj.data());
|
||||
|
||||
if (requesterId && deleteObject(requesterId, obj) != DBOperationResult::Allowed) {
|
||||
if (deleteObject(requesterId, obj) != DBOperationResult::Allowed) {
|
||||
prepareAndSendBadRequest(sender->networkAddress(), pkg.hdr,
|
||||
ErrorCodes::OperatioForbiden, REQUEST_ERROR);
|
||||
}
|
||||
|
@ -17,6 +17,8 @@ namespace QH {
|
||||
*/
|
||||
class SQLiteDBCachePrivate;
|
||||
|
||||
// TO-DO see task https://github.com/QuasarApp/Heart/issues/15
|
||||
|
||||
/**
|
||||
* @brief The SQLiteDBCache class using sqliete database for save all temp values.
|
||||
* This class use the in memory mode of the sqlite https://sqlite.org/inmemorydb.html
|
||||
|
Loading…
x
Reference in New Issue
Block a user