New DB layout: CKM_TABLE split into NAME_TABLE and OBJECT_TABLE.
authorMaciej J. Karpiuk <m.karpiuk2@samsung.com>
Fri, 7 Nov 2014 14:38:45 +0000 (15:38 +0100)
committerMaciej J. Karpiuk <m.karpiuk2@samsung.com>
Tue, 17 Feb 2015 10:18:55 +0000 (11:18 +0100)
Change-Id: I3a3666b2a928f45294adf97548bac09d54d133de

src/manager/service/ckm-logic.cpp
src/manager/service/ckm-logic.h
src/manager/service/db-crypto.cpp
src/manager/service/db-crypto.h
tests/DBFixture.cpp

index 81d2478..86ebf2b 100644 (file)
@@ -822,7 +822,7 @@ RawBuffer CKMLogic::getCertificateChain(
 
         retCode = getCertificateChainHelper(cred, certificate, labelNameVector, chainRawVector);
     } catch (const CryptoLogic::Exception::Base &e) {
-        LogError("DBCyptorModule failed with message: " << e.GetMessage());
+        LogError("CryptoLogic failed with message: " << e.GetMessage());
         retCode = CKM_API_ERROR_SERVER_ERROR;
     } catch (const DBCrypto::Exception::Base &e) {
         LogError("DBCrypto failed with message: " << e.GetMessage());
@@ -956,11 +956,8 @@ int CKMLogic::setPermissionHelper(
         const Name &name,
         const Label &label,
         const Label &accessorLabel,
-        const Permission reqRights)
+        const Permission newPermission)
 {
-    if (0 == m_userDataMap.count(cred.uid))
-        return CKM_API_ERROR_DB_LOCKED;
-
     if(cred.smackLabel.empty() || cred.smackLabel==accessorLabel)
         return CKM_API_ERROR_INPUT_PARAM;
 
@@ -975,6 +972,9 @@ int CKMLogic::setPermissionHelper(
     if(access_ec != CKM_API_SUCCESS)
         return access_ec;
 
+    if (0 == m_userDataMap.count(cred.uid))
+        return CKM_API_ERROR_DB_LOCKED;
+
     auto &database = m_userDataMap[cred.uid].database;
     DBCrypto::Transaction transaction(&database);
 
@@ -982,20 +982,16 @@ int CKMLogic::setPermissionHelper(
         return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
 
     // removing non-existing permissions: fail
-    if(reqRights == Permission::NONE)
+    if(newPermission == Permission::NONE)
     {
         if( !database.getPermissionRow(name, ownerLabel, accessorLabel) )
             return CKM_API_ERROR_INPUT_PARAM;
     }
 
-    int retCode = database.setPermission(name,
-                                     ownerLabel,
-                                     accessorLabel,
-                                     reqRights);
-
+    database.setPermission(name, cred.smackLabel, accessorLabel, newPermission);
     transaction.commit();
 
-    return retCode;
+    return CKM_API_SUCCESS;
 }
 
 RawBuffer CKMLogic::setPermission(
@@ -1005,11 +1001,11 @@ RawBuffer CKMLogic::setPermission(
         const Name &name,
         const Label &label,
         const Label &accessorLabel,
-        const Permission reqRights)
+        const Permission newPermission)
 {
     int retCode;
     Try {
-        retCode = setPermissionHelper(cred, name, label, accessorLabel, reqRights);
+        retCode = setPermissionHelper(cred, name, label, accessorLabel, newPermission);
     } Catch (CKM::Exception) {
         LogError("Error in set row!");
         retCode = CKM_API_ERROR_DB_ERROR;
index fd78dd3..07944c4 100644 (file)
@@ -160,7 +160,7 @@ public:
         const Name &name,
         const Label &label,
         const Label &accessor_label,
-        const Permission req_rights);
+        const Permission newPermission);
 
 private:
 
@@ -227,7 +227,7 @@ private:
         const Name &name,
         const Label &ownerLabel,
         const Label &accessorLabel,
-        const Permission reqRights);
+        const Permission newPermission);
 
     std::map<uid_t, UserData> m_userDataMap;
     CertificateStore m_certStore;
index 92ba10a..a67bae0 100644 (file)
 #pragma GCC diagnostic warning "-Wdeprecated-declarations"
 
 namespace {
-    const char *main_table = "CKM_TABLE";
-    const char *key_table = "KEY_TABLE";
-    const char *permission_table = "PERMISSION_TABLE";
+    const char *TABLE_NAME          = "NAME_TABLE";
+    const char *TABLE_OBJECT        = "OBJECT_TABLE";
+    const char *TABLE_KEY           = "KEY_TABLE";
+    const char *TABLE_PERMISSION    = "PERMISSION_TABLE";
 
-// CKM_TABLE (name TEXT, label TEXT, restricted INT, exportable INT, dataType INT, algorithmType INT,
-//            encryptionScheme INT, iv BLOB, dataSize INT, data BLOB, tag BLOB, idx INT )
-
-    const char *db_create_main_cmd =
-            "CREATE TABLE CKM_TABLE("
+    const char *DB_CMD_NAME_CREATE =
+            "CREATE TABLE NAME_TABLE("
             "   name TEXT NOT NULL,"
             "   label TEXT NOT NULL,"
+            "   idx INTEGER PRIMARY KEY AUTOINCREMENT,"
+            "   UNIQUE(name, label)"
+            "); CREATE INDEX name_index_idx ON NAME_TABLE(idx);";
+
+    const char *DB_CMD_NAME_INSERT =
+            "INSERT INTO NAME_TABLE("
+            "   name, label) "
+            "   VALUES(?101, ?102);";
+
+    // any idea how to do it using constexpr ?
+    #define DB_CMD_NAME_LOOKUP_IDX \
+            "(SELECT idx FROM NAME_TABLE WHERE name=?101 and label=?102)"
+
+    const char *DB_CMD_NAME_COUNT_ROWS =
+            "SELECT COUNT(idx) FROM NAME_TABLE WHERE name=?101 AND label=?102;";
+
+    const char *DB_CMD_NAME_DELETE =
+            "DELETE FROM NAME_TABLE WHERE name=?101 AND label=?102;";
+
+    const char *DB_CMD_NAME_DELETE_BY_LABEL =
+            "DELETE FROM NAME_TABLE WHERE label=?102;";
+
+    const char *DB_CMD_OBJECT_CREATE =
+            "CREATE TABLE OBJECT_TABLE("
             "   exportable INTEGER NOT NULL,"
             "   dataType INTEGER NOT NULL,"
             "   algorithmType INTEGER NOT NULL,"
@@ -48,90 +70,73 @@ namespace {
             "   dataSize INTEGER NOT NULL,"
             "   data BLOB NOT NULL,"
             "   tag BLOB NOT NULL,"
-            "   idx INTEGER PRIMARY KEY AUTOINCREMENT,"
-            "   UNIQUE(name, label)"
-            "); CREATE INDEX ckm_index_label ON CKM_TABLE(label);"; // based on ANALYZE and performance test result
-
-    const char *insert_main_cmd =
-            "INSERT INTO CKM_TABLE("
-            //      1   2       3
-            "   name, label, exportable,"
-            //      4           5           6
-            "   dataType, algorithmType, encryptionScheme,"
-            //  7       8       9    10
-            "   iv, dataSize, data, tag) "
-            "VALUES("
-            "   ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);";
-
-    const char *select_check_name_cmd =
-            "SELECT dataType FROM CKM_TABLE WHERE name=?001 AND label=?002;";
-
-    const char *select_row_by_name_label_type_cmd =
-            "SELECT * FROM CKM_TABLE WHERE name=?001 AND label=?002"
-            " AND dataType BETWEEN ?003 AND ?004;";
-
-    const char *select_count_rows_cmd =
-            "SELECT COUNT(idx) FROM CKM_TABLE WHERE name=?001 AND label=?002;";
+            "   idx INTEGER NOT NULL,"
+            "   FOREIGN KEY(idx) REFERENCES NAME_TABLE(idx) ON DELETE CASCADE,"
+            "   PRIMARY KEY(idx, dataType)"
+            ");"; // TODO: index and performance tests
 
-    const char *delete_name_cmd =
-            "DELETE FROM CKM_TABLE WHERE name=?001 AND label=?002;";
+    const char *DB_CMD_OBJECT_INSERT =
+            "INSERT INTO OBJECT_TABLE("
+            "   exportable, dataType,"
+            "   algorithmType, encryptionScheme,"
+            "   iv, dataSize, data, tag, idx) "
+            "   VALUES(?001, ?002, ?003, ?004, ?005, "
+            "          ?006, ?007, ?008, " DB_CMD_NAME_LOOKUP_IDX ");";
 
-    const char *delete_data_with_key_cmd =
-            //                                 1
-            "DELETE FROM CKM_TABLE WHERE label=?;";
+    const char *DB_CMD_OBJECT_SELECT_BY_NAME_AND_LABEL =
+            "SELECT * FROM OBJECT_TABLE WHERE "
+            " (dataType BETWEEN ?001 AND ?002) AND "
+            " idx=" DB_CMD_NAME_LOOKUP_IDX ";";
 
-// KEY_TABLE (label TEXT, key BLOB)
 
-    const char *db_create_key_cmd =
+    const char *DB_CMD_KEY_CREATE =
             "CREATE TABLE KEY_TABLE("
             "   label TEXT PRIMARY KEY,"
             "   key BLOB NOT NULL"
             ");";
 
-    const char *insert_key_cmd =
+    const char *DB_CMD_KEY_INSERT =
             "INSERT INTO KEY_TABLE(label, key) VALUES (?, ?);";
-    const char *select_key_cmd =
+    const char *DB_CMD_KEY_SELECT =
             "SELECT key FROM KEY_TABLE WHERE label=?;";
-    const char *delete_key_cmd =
+    const char *DB_CMD_KEY_DELETE =
             "DELETE FROM KEY_TABLE WHERE label=?";
 
 
-// PERMISSION_TABLE (label TEXT, access_flags TEXT, idx INT)
-
-    const char *db_create_permission_cmd =
+    const char *DB_CMD_PERMISSION_CREATE =
             "CREATE TABLE PERMISSION_TABLE("
             "   label TEXT NOT NULL,"
             "   accessFlags TEXT NOT NULL,"
             "   idx INTEGER NOT NULL,"
-            "   FOREIGN KEY(idx) REFERENCES CKM_TABLE(idx) ON DELETE CASCADE,"
+            "   FOREIGN KEY(idx) REFERENCES NAME_TABLE(idx) ON DELETE CASCADE,"
             "   PRIMARY KEY(label, idx)"
             "); CREATE INDEX perm_index_idx ON PERMISSION_TABLE(idx);"; // based on ANALYZE and performance test result
 
-    const char *set_permission_name_cmd =
+    const char *DB_CMD_PERMISSION_SET =
             "REPLACE INTO PERMISSION_TABLE(label, accessFlags, idx) "
-            " VALUES (?001, ?002, "
-            " (SELECT idx FROM CKM_TABLE WHERE name = ?003 and label = ?004)); ";
+            " VALUES (?001, ?002, " DB_CMD_NAME_LOOKUP_IDX ");";
 
-    const char *select_permission_cmd =
-            "SELECT accessFlags FROM PERMISSION_TABLE WHERE label=?001 AND idx IN (SELECT idx FROM CKM_TABLE WHERE name=?002 AND label=?003);";
+    const char *DB_CMD_PERMISSION_SELECT =
+            "SELECT accessFlags FROM PERMISSION_TABLE WHERE label=?001 AND "
+            " idx=" DB_CMD_NAME_LOOKUP_IDX ";";
 
-    const char *delete_permission_cmd =
-            "DELETE FROM PERMISSION_TABLE WHERE label=?003 AND "
-            " idx IN (SELECT idx FROM CKM_TABLE WHERE name = ?001 AND label = ?002); ";
+    const char *DB_CMD_PERMISSION_DELETE =
+            "DELETE FROM PERMISSION_TABLE WHERE label=?001 AND "
+            " idx=" DB_CMD_NAME_LOOKUP_IDX ";";
 
 
-// CKM_TABLE x PERMISSION_TABLE
-
-    const char *select_key_type_cross_cmd =
-            "SELECT C.label, C.name FROM CKM_TABLE AS C LEFT JOIN PERMISSION_TABLE AS P ON C.idx=P.idx WHERE "
-            " C.dataType>=?001 AND C.dataType<=?002 AND "
-            "(C.label=?003 OR (P.label=?003 AND P.accessFlags IS NOT NULL)) GROUP BY C.name; ";
+    const char *DB_CMD_NAME_SELECT_BY_TYPE_AND_PERMISSION =
+            "SELECT N.label, N.name FROM NAME_TABLE AS N "
+            " JOIN OBJECT_TABLE AS O ON O.idx=N.idx "
+            " LEFT JOIN PERMISSION_TABLE AS P ON P.idx=N.idx "
+            " WHERE O.dataType>=?001 AND O.dataType<=?002 AND "
+            " (N.label=?003 OR (P.label=?003 AND P.accessFlags IS NOT NULL));";
 }
 
 namespace CKM {
 using namespace DB;
-    DBCrypto::DBCrypto(const std::string& path,
-                         const RawBuffer &rawPass) {
+    DBCrypto::DBCrypto(const std::string& path, const RawBuffer &rawPass)
+    {
         m_connection = NULL;
         m_inUserTransaction = false;
         Try {
@@ -156,7 +161,8 @@ using namespace DB;
 
     DBCrypto::DBCrypto(DBCrypto &&other) :
             m_connection(other.m_connection),
-            m_inUserTransaction(other.m_inUserTransaction){
+            m_inUserTransaction(other.m_inUserTransaction)
+    {
         other.m_connection = NULL;
         other.m_inUserTransaction = false;
     }
@@ -196,30 +202,25 @@ using namespace DB;
 
     void DBCrypto::initDatabase() {
         Transaction transaction(this);
-        if(!m_connection->CheckTableExist(main_table)) {
-            createTable(db_create_main_cmd, main_table);
+        if(!m_connection->CheckTableExist(TABLE_NAME)) {
+            createTable(DB_CMD_NAME_CREATE, TABLE_NAME);
+        }
+        if(!m_connection->CheckTableExist(TABLE_OBJECT)) {
+            createTable(DB_CMD_OBJECT_CREATE, TABLE_OBJECT);
         }
-        if(!m_connection->CheckTableExist(key_table)) {
-            createTable(db_create_key_cmd, key_table);
+        if(!m_connection->CheckTableExist(TABLE_KEY)) {
+            createTable(DB_CMD_KEY_CREATE, TABLE_KEY);
         }
-        if(!m_connection->CheckTableExist(permission_table)) {
-            createTable(db_create_permission_cmd, permission_table);
+        if(!m_connection->CheckTableExist(TABLE_PERMISSION)) {
+            createTable(DB_CMD_PERMISSION_CREATE, TABLE_PERMISSION);
         }
         transaction.commit();
     }
 
     bool DBCrypto::isNameLabelPresent(const Name &name, const Label &owner) const {
         Try {
-            SqlConnection::DataCommandUniquePtr checkCmd =
-                    m_connection->PrepareDataCommand(select_check_name_cmd);
-            checkCmd->BindString(1, name.c_str());
-            checkCmd->BindString(2, owner.c_str());
-            if(checkCmd->Step()) {
-                LogDebug("Private name '" << name  << "' exists already for type "
-                        << checkCmd->GetColumnInteger(0));
-                return true;
-            }
-            return false;
+            NameTable nameTable(this->m_connection);
+            return nameTable.isPresent(name, owner);
         } Catch(SqlConnection::Exception::SyntaxError) {
             LogError("Couldn't prepare insert statement");
         } Catch(SqlConnection::Exception::InternalError) {
@@ -231,24 +232,12 @@ using namespace DB;
 
     void DBCrypto::saveDBRow(const DBRow &row){
         Try {
-            // Sqlite does not support partial index in our version,
-            // so we do it by hand
-            SqlConnection::DataCommandUniquePtr insertCommand =
-                    m_connection->PrepareDataCommand(insert_main_cmd);
-            insertCommand->BindString(1, row.name.c_str());
-            insertCommand->BindString(2, row.ownerLabel.c_str());
-            insertCommand->BindInteger(3, row.exportable);
-            insertCommand->BindInteger(4, static_cast<int>(row.dataType));
-            insertCommand->BindInteger(5, static_cast<int>(row.algorithmType));
-            insertCommand->BindInteger(6, row.encryptionScheme);
-            insertCommand->BindBlob(7, row.iv);
-            insertCommand->BindInteger(8, row.dataSize);
-            insertCommand->BindBlob(9, row.data);
-            insertCommand->BindBlob(10, row.tag);
-
-            insertCommand->Step();
+            // transaction is present in the layer above
+            NameTable nameTable(this->m_connection);
+            ObjectTable objectTable(this->m_connection);
+            nameTable.addRow(row.name, row.ownerLabel);
+            objectTable.addRow(row);
             return;
-
         } Catch(SqlConnection::Exception::SyntaxError) {
             LogError("Couldn't prepare insert statement");
         } Catch(SqlConnection::Exception::InternalError) {
@@ -258,18 +247,43 @@ using namespace DB;
                 "Couldn't save DBRow");
     }
 
-    DBRow DBCrypto::getRow(const SqlConnection::DataCommandUniquePtr &selectCommand) {
+    bool DBCrypto::deleteDBRow(
+            const Name &name,
+            const Label &ownerLabel)
+    {
+        Try {
+            // transaction is present in the layer above
+            NameTable nameTable(this->m_connection);
+            if(nameTable.isPresent(name, ownerLabel))
+            {
+                nameTable.deleteRow(name, ownerLabel);
+                return true;
+            }
+            return false;
+        } Catch (SqlConnection::Exception::SyntaxError) {
+            LogError("Couldn't prepare delete statement");
+        } Catch (SqlConnection::Exception::InternalError) {
+            LogError("Couldn't execute delete statement");
+        }
+        ThrowMsg(DBCrypto::Exception::InternalError,
+                "Couldn't delete DBRow for name " << name << " using ownerLabel " << ownerLabel);
+    }
+
+    DBRow DBCrypto::getRow(
+            const Name &name,
+            const Label &ownerLabel,
+            const SqlConnection::DataCommandUniquePtr &selectCommand) const {
         DBRow row;
-        row.name = selectCommand->GetColumnString(0);
-        row.ownerLabel = selectCommand->GetColumnString(1);
-        row.exportable = selectCommand->GetColumnInteger(2);
-        row.dataType = static_cast<DBDataType>(selectCommand->GetColumnInteger(3));
-        row.algorithmType = static_cast<DBCMAlgType>(selectCommand->GetColumnInteger(4));
-        row.encryptionScheme = selectCommand->GetColumnInteger(5);
-        row.iv = selectCommand->GetColumnBlob(6);
-        row.dataSize = selectCommand->GetColumnInteger(7);
-        row.data = selectCommand->GetColumnBlob(8);
-        row.tag = selectCommand->GetColumnBlob(9);
+        row.name = name;
+        row.ownerLabel = ownerLabel;
+        row.exportable = selectCommand->GetColumnInteger(0);
+        row.dataType = static_cast<DBDataType>(selectCommand->GetColumnInteger(1));
+        row.algorithmType = static_cast<DBCMAlgType>(selectCommand->GetColumnInteger(2));
+        row.encryptionScheme = selectCommand->GetColumnInteger(3);
+        row.iv = selectCommand->GetColumnBlob(4);
+        row.dataSize = selectCommand->GetColumnInteger(5);
+        row.data = selectCommand->GetColumnBlob(6);
+        row.tag = selectCommand->GetColumnBlob(7);
         return row;
     }
 
@@ -278,15 +292,9 @@ using namespace DB;
         const Label &ownerLabel,
         const Label &accessorLabel) const
     {
-        Try{
-            SqlConnection::DataCommandUniquePtr selectCommand =
-                            m_connection->PrepareDataCommand(select_permission_cmd);
-            selectCommand->BindString(1, accessorLabel.c_str());
-            selectCommand->BindString(2, name.c_str());
-            selectCommand->BindString(3, ownerLabel.c_str());
-
-            if(selectCommand->Step())
-                return PermissionOptional(toPermission(selectCommand->GetColumnString(0)));
+        Try {
+            PermissionTable permissionTable(this->m_connection);
+            return permissionTable.getPermissionRow(name, ownerLabel, accessorLabel);
         } Catch (SqlConnection::Exception::InvalidColumn) {
             LogError("Select statement invalid column error");
         } Catch (SqlConnection::Exception::SyntaxError) {
@@ -312,16 +320,18 @@ using namespace DB;
     {
         Try {
             SqlConnection::DataCommandUniquePtr selectCommand =
-                    m_connection->PrepareDataCommand(select_row_by_name_label_type_cmd);
-            selectCommand->BindString(1, name.c_str());
-            selectCommand->BindString(2, ownerLabel.c_str());
-            selectCommand->BindInteger(3, static_cast<int>(typeRangeStart));
-            selectCommand->BindInteger(4, static_cast<int>(typeRangeStop));
+                    m_connection->PrepareDataCommand(DB_CMD_OBJECT_SELECT_BY_NAME_AND_LABEL);
+            selectCommand->BindInteger(1, static_cast<int>(typeRangeStart));
+            selectCommand->BindInteger(2, static_cast<int>(typeRangeStop));
+
+            // name table reference
+            selectCommand->BindString (101, name.c_str());
+            selectCommand->BindString (102, ownerLabel.c_str());
 
             if(selectCommand->Step())
             {
                 // extract data
-                DBRow current_row = getRow(selectCommand);
+                DBRow current_row = getRow(name, ownerLabel, selectCommand);
 
                 // all okay, proceed
                 return DBRowOptional(current_row);
@@ -359,7 +369,7 @@ using namespace DB;
         Try{
             Transaction transaction(this);
             SqlConnection::DataCommandUniquePtr selectCommand =
-                            m_connection->PrepareDataCommand(select_key_type_cross_cmd);
+                            m_connection->PrepareDataCommand(DB_CMD_NAME_SELECT_BY_TYPE_AND_PERMISSION);
             selectCommand->BindInteger(1, static_cast<int>(typeRangeStart));
             selectCommand->BindInteger(2, static_cast<int>(typeRangeStop));
             selectCommand->BindString(3, smackLabel.c_str());
@@ -384,45 +394,7 @@ using namespace DB;
                 " accessible to client label " << smackLabel);
     }
 
-    bool DBCrypto::deleteDBRow(const Name &name, const Label &ownerLabel)
-    {
-        Try {
-            if(countRows(name, ownerLabel) > 0)
-            {
-                SqlConnection::DataCommandUniquePtr deleteCommand =
-                        m_connection->PrepareDataCommand(delete_name_cmd);
-                deleteCommand->BindString(1, name.c_str());
-                deleteCommand->BindString(2, ownerLabel.c_str());
 
-                // Step() result code does not provide information whether
-                // anything was removed.
-                deleteCommand->Step();
-
-                return true;
-            }
-            return false;
-        } Catch (SqlConnection::Exception::SyntaxError) {
-            LogError("Couldn't prepare delete statement");
-        } Catch (SqlConnection::Exception::InternalError) {
-            LogError("Couldn't execute delete statement");
-        }
-        ThrowMsg(DBCrypto::Exception::InternalError,
-                "Couldn't delete DBRow for name " << name << " using client label " << ownerLabel);
-    }
-
-    int DBCrypto::countRows(const Name &name, const Label &ownerLabel) const
-    {
-        SqlConnection::DataCommandUniquePtr checkCmd =
-                    m_connection->PrepareDataCommand(select_count_rows_cmd);
-        checkCmd->BindString(1, name.c_str());
-        checkCmd->BindString(2, ownerLabel.c_str());
-        if(checkCmd->Step()) {
-            return checkCmd->GetColumnInteger(0);
-        } else {
-            LogDebug("Row does not exist for name=" << name << "and label=" << ownerLabel);
-            return 0;
-        }
-    }
 
     void DBCrypto::saveKey(
             const Label& label,
@@ -430,7 +402,7 @@ using namespace DB;
     {
         Try {
             SqlConnection::DataCommandUniquePtr insertCommand =
-                    m_connection->PrepareDataCommand(insert_key_cmd);
+                    m_connection->PrepareDataCommand(DB_CMD_KEY_INSERT);
             insertCommand->BindString(1, label.c_str());
             insertCommand->BindBlob(2, key);
             insertCommand->Step();
@@ -448,7 +420,7 @@ using namespace DB;
     {
         Try {
             SqlConnection::DataCommandUniquePtr selectCommand =
-                    m_connection->PrepareDataCommand(select_key_cmd);
+                    m_connection->PrepareDataCommand(DB_CMD_KEY_SELECT);
             selectCommand->BindString(1, label.c_str());
 
             if (selectCommand->Step()) {
@@ -474,14 +446,12 @@ using namespace DB;
             Transaction transaction(this);
 
             SqlConnection::DataCommandUniquePtr deleteCommand =
-                    m_connection->PrepareDataCommand(delete_key_cmd);
+                    m_connection->PrepareDataCommand(DB_CMD_KEY_DELETE);
             deleteCommand->BindString(1, label.c_str());
             deleteCommand->Step();
 
-            SqlConnection::DataCommandUniquePtr deleteData =
-                m_connection->PrepareDataCommand(delete_data_with_key_cmd);
-            deleteData->BindString(1, label.c_str());
-            deleteData->Step();
+            NameTable nameTable(this->m_connection);
+            nameTable.deleteAllRows(label);
 
             transaction.commit();
             return;
@@ -494,35 +464,16 @@ using namespace DB;
                 "Couldn't delete key for label " << label);
     }
 
-    int DBCrypto::setPermission(
+    void DBCrypto::setPermission(
             const Name &name,
             const Label& ownerLabel,
             const Label& accessorLabel,
             const Permission permissions)
     {
         Try {
-            if(permissions == Permission::NONE)
-            {
-                // clear access rights
-                SqlConnection::DataCommandUniquePtr deletePermissionCommand =
-                    m_connection->PrepareDataCommand(delete_permission_cmd);
-                deletePermissionCommand->BindString(1, name.c_str());
-                deletePermissionCommand->BindString(2, ownerLabel.c_str());
-                deletePermissionCommand->BindString(3, accessorLabel.c_str());
-                deletePermissionCommand->Step();
-            }
-            else
-            {
-                // add new rights
-                SqlConnection::DataCommandUniquePtr setPermissionCommand =
-                    m_connection->PrepareDataCommand(set_permission_name_cmd);
-                setPermissionCommand->BindString(1, accessorLabel.c_str());
-                setPermissionCommand->BindString(2, toDBPermission(permissions));
-                setPermissionCommand->BindString(3, name.c_str());
-                setPermissionCommand->BindString(4, ownerLabel.c_str());
-                setPermissionCommand->Step();
-            }
-            return CKM_API_SUCCESS;
+            PermissionTable permissionTable(this->m_connection);
+            permissionTable.setPermission(name, ownerLabel, accessorLabel, permissions);
+            return;
         } Catch (SqlConnection::Exception::SyntaxError) {
             LogError("Couldn't prepare set statement");
         } Catch (SqlConnection::Exception::InternalError) {
@@ -532,6 +483,128 @@ using namespace DB;
                 "Couldn't set permissions for name " << name );
     }
 
+    void DBCrypto::PermissionTable::setPermission(
+            const Name &name,
+            const Label& ownerLabel,
+            const Label& accessorLabel,
+            const Permission permissions)
+    {
+        if(permissions == Permission::NONE)
+        {
+            // clear permissions
+            SqlConnection::DataCommandUniquePtr deletePermissionCommand =
+                m_connection->PrepareDataCommand(DB_CMD_PERMISSION_DELETE);
+            deletePermissionCommand->BindString(1, accessorLabel.c_str());
+            deletePermissionCommand->BindString(101, name.c_str());
+            deletePermissionCommand->BindString(102, ownerLabel.c_str());
+            deletePermissionCommand->Step();
+        }
+        else
+        {
+            // add new permissions
+            SqlConnection::DataCommandUniquePtr setPermissionCommand =
+                m_connection->PrepareDataCommand(DB_CMD_PERMISSION_SET);
+            setPermissionCommand->BindString(1, accessorLabel.c_str());
+            setPermissionCommand->BindString(2, toDBPermission(permissions));
+            setPermissionCommand->BindString(101, name.c_str());
+            setPermissionCommand->BindString(102, ownerLabel.c_str());
+            setPermissionCommand->Step();
+        }
+    }
+
+    PermissionOptional DBCrypto::PermissionTable::getPermissionRow(
+            const Name &name,
+            const Label &ownerLabel,
+            const Label &accessorLabel) const
+    {
+        SqlConnection::DataCommandUniquePtr selectCommand =
+                m_connection->PrepareDataCommand(DB_CMD_PERMISSION_SELECT);
+        selectCommand->BindString(1, accessorLabel.c_str());
+
+        // name table reference
+        selectCommand->BindString(101, name.c_str());
+        selectCommand->BindString(102, ownerLabel.c_str());
+
+        if(selectCommand->Step())
+        {
+            // there is entry for the <name, ownerLabel> pair
+            return PermissionOptional(toPermission(selectCommand->GetColumnString(0)));
+        }
+        return PermissionOptional();
+    }
+
+    void DBCrypto::NameTable::addRow(
+            const Name &name,
+            const Label &ownerLabel)
+    {
+        // insert NAME_TABLE item
+        SqlConnection::DataCommandUniquePtr insertNameCommand =
+                m_connection->PrepareDataCommand(DB_CMD_NAME_INSERT);
+        insertNameCommand->BindString (101, name.c_str());
+        insertNameCommand->BindString (102, ownerLabel.c_str());
+        insertNameCommand->Step();
+    }
+
+    void DBCrypto::NameTable::deleteRow(
+            const Name &name,
+            const Label &ownerLabel)
+    {
+        SqlConnection::DataCommandUniquePtr deleteCommand =
+                m_connection->PrepareDataCommand(DB_CMD_NAME_DELETE);
+        deleteCommand->BindString(101, name.c_str());
+        deleteCommand->BindString(102, ownerLabel.c_str());
+
+        // Step() result code does not provide information whether
+        // anything was removed.
+        deleteCommand->Step();
+    }
+
+    void DBCrypto::NameTable::deleteAllRows(const Label &ownerLabel)
+    {
+        SqlConnection::DataCommandUniquePtr deleteData =
+                m_connection->PrepareDataCommand(DB_CMD_NAME_DELETE_BY_LABEL);
+        deleteData->BindString(102, ownerLabel.c_str());
+
+        // Step() result code does not provide information whether
+        // anything was removed.
+        deleteData->Step();
+    }
+
+    bool DBCrypto::NameTable::isPresent(const Name &name, const Label &ownerLabel) const
+    {
+        SqlConnection::DataCommandUniquePtr checkCmd =
+                m_connection->PrepareDataCommand(DB_CMD_NAME_COUNT_ROWS);
+        checkCmd->BindString(101, name.c_str());
+        checkCmd->BindString(102, ownerLabel.c_str());
+        if(checkCmd->Step()) {
+            int element_count = checkCmd->GetColumnInteger(0);
+            LogDebug("Item name: " << name  << " ownerLabel: " << ownerLabel <<
+                     " hit count: " << element_count);
+            if(element_count > 0)
+                return true;
+        }
+        return false;
+    }
+
+    void DBCrypto::ObjectTable::addRow(const DBRow &row)
+    {
+        SqlConnection::DataCommandUniquePtr insertObjectCommand =
+                m_connection->PrepareDataCommand(DB_CMD_OBJECT_INSERT);
+        insertObjectCommand->BindInteger(1, row.exportable);
+        insertObjectCommand->BindInteger(2, static_cast<int>(row.dataType));
+        insertObjectCommand->BindInteger(3, static_cast<int>(row.algorithmType));
+        insertObjectCommand->BindInteger(4, row.encryptionScheme);
+        insertObjectCommand->BindBlob   (5, row.iv);
+        insertObjectCommand->BindInteger(6, row.dataSize);
+        insertObjectCommand->BindBlob   (7, row.data);
+        insertObjectCommand->BindBlob   (8, row.tag);
+
+        // name table reference
+        insertObjectCommand->BindString (101, row.name.c_str());
+        insertObjectCommand->BindString (102, row.ownerLabel.c_str());
+
+        insertObjectCommand->Step();
+    }
 } // namespace CKM
 
 #pragma GCC diagnostic pop
index adb4e6f..8d5d92c 100644 (file)
@@ -43,7 +43,7 @@ namespace CKM {
             typedef boost::optional<RawBuffer> RawBufferOptional;
             class Exception
             {
-              public:
+            public:
                 DECLARE_EXCEPTION_TYPE(CKM::Exception, Base)
                 DECLARE_EXCEPTION_TYPE(Base, InternalError)
                 DECLARE_EXCEPTION_TYPE(Base, TransactionError)
@@ -63,7 +63,12 @@ namespace CKM {
 
             virtual ~DBCrypto();
 
-            void saveDBRow(const DBRow &row);
+            void saveDBRow(
+                    const DBRow &row);
+
+            bool isNameLabelPresent(
+                    const Name &name,
+                    const Label &owner) const;
 
             DBRowOptional getDBRow(
                     const Name &name,
@@ -91,7 +96,6 @@ namespace CKM {
                     const Name &name,
                     const Label &ownerLabel);
 
-
             // keys
             void saveKey(const Label& label, const RawBuffer &key);
             RawBufferOptional getKey(const Label& label);
@@ -99,11 +103,7 @@ namespace CKM {
 
 
             // permissions
-            bool isNameLabelPresent(
-                    const Name &name,
-                    const Label &owner) const;
-
-            int setPermission(
+            void setPermission(
                     const Name &name,
                     const Label &ownerLabel,
                     const Label &accessorLabel,
@@ -192,15 +192,67 @@ namespace CKM {
             bool m_inUserTransaction;
 
             void initDatabase();
-            DBRow getRow(const DB::SqlConnection::DataCommandUniquePtr &selectCommand);
+            DBRow getRow(
+                    const Name &name,
+                    const Label &ownerLabel,
+                    const DB::SqlConnection::DataCommandUniquePtr &selectCommand) const;
 
             void createTable(
                     const char *create_cmd,
                     const char *table_name);
 
-            int countRows(
-                    const Name &name,
-                    const Label &label) const;
+            class NameTable {
+            public:
+                explicit NameTable(DB::SqlConnection* connection) : m_connection(connection) {}
+
+                void addRow(
+                        const Name &name,
+                        const Label &ownerLabel);
+
+                void deleteRow(
+                        const Name &name,
+                        const Label &ownerLabel);
+
+                void deleteAllRows(
+                        const Label &ownerLabel);
+
+                bool isPresent(
+                        const Name &name,
+                        const Label &ownerLabel) const;
+
+            private:
+                DB::SqlConnection* m_connection;
+            };
+
+            class ObjectTable {
+            public:
+                explicit ObjectTable(DB::SqlConnection* connection) : m_connection(connection) {}
+
+                void addRow(
+                        const DBRow &row);
+
+            private:
+                DB::SqlConnection* m_connection;
+            };
+
+            class PermissionTable {
+            public:
+                explicit PermissionTable(DB::SqlConnection* connection) : m_connection(connection) {}
+
+                void setPermission(
+                        const Name &name,
+                        const Label &ownerLabel,
+                        const Label &accessorLabel,
+                        const Permission rights);
+
+                PermissionOptional getPermissionRow(
+                        const Name &name,
+                        const Label &ownerLabel,
+                        const Label &accessorLabel) const;
+
+            private:
+                DB::SqlConnection* m_connection;
+            };
     };
 } // namespace CKM
 
index db6c46f..4857ef7 100644 (file)
@@ -185,12 +185,10 @@ void DBFixture::delete_row(const Name &name, const Label &owner_label)
 
 void DBFixture::add_permission(const Name &name, const Label &owner_label, const Label &accessor_label)
 {
-    int ec;
-    BOOST_REQUIRE_NO_THROW(ec = m_db.setPermission(name,
-                                                     owner_label,
-                                                     accessor_label,
-                                                     CKM::Permission::READ_REMOVE));
-    BOOST_REQUIRE_MESSAGE(CKM_API_SUCCESS == ec, "add permission failed: " << ec);
+    BOOST_REQUIRE_NO_THROW(m_db.setPermission(name,
+                                              owner_label,
+                                              accessor_label,
+                                              CKM::Permission::READ_REMOVE));
 }
 
 void DBFixture::read_row_expect_success(const Name &name, const Label &owner_label)