Add support for app defined privileges in db 05/114705/7
authorDariusz Michaluk <d.michaluk@samsung.com>
Thu, 9 Feb 2017 11:07:29 +0000 (12:07 +0100)
committerDariusz Michaluk <d.michaluk@samsung.com>
Tue, 21 Feb 2017 10:09:31 +0000 (11:09 +0100)
Change-Id: I4ecf0940fa3716bdfe104e45491d3dc4eac21049

db/db.sql
db/updates/update-db-to-v10.sql [new file with mode: 0644]
src/common/include/privilege_db.h
src/common/privilege_db.cpp

index f22e451..f926e5e 100644 (file)
--- a/db/db.sql
+++ b/db/db.sql
@@ -4,7 +4,7 @@ PRAGMA auto_vacuum = NONE;
 
 BEGIN EXCLUSIVE TRANSACTION;
 
-PRAGMA user_version = 9;
+PRAGMA user_version = 10;
 
 CREATE TABLE IF NOT EXISTS pkg (
 pkg_id INTEGER PRIMARY KEY,
@@ -62,6 +62,14 @@ CREATE TABLE IF NOT EXISTS author (
        UNIQUE (name)
 );
 
+CREATE TABLE IF NOT EXISTS app_defined_privilege (
+app_id INTEGER NOT NULL,
+uid INTEGER NOT NULL,
+privilege VARCHAR NOT NULL,
+type INTEGER NOT NULL CHECK (type >= 0 AND type <= 1),
+FOREIGN KEY (app_id, uid) REFERENCES user_app (app_id, uid) ON UPDATE CASCADE ON DELETE CASCADE
+);
+
 DROP VIEW IF EXISTS user_app_pkg_view;
 CREATE VIEW user_app_pkg_view AS
 SELECT
@@ -202,4 +210,39 @@ BEGIN
     AND app_private_sharing.target_app_name = OLD.target_app_name;
 END;
 
+DROP VIEW IF EXISTS app_defined_privilege_view;
+CREATE VIEW app_defined_privilege_view AS
+SELECT
+    name AS app_name,
+    uid,
+    privilege,
+    type
+FROM app_defined_privilege
+LEFT JOIN app USING (app_id)
+LEFT JOIN user_app USING (uid);
+
+DROP TRIGGER IF EXISTS app_defined_privilege_view_insert_trigger;
+CREATE TRIGGER app_defined_privilege_view_insert_trigger
+INSTEAD OF INSERT ON app_defined_privilege_view
+BEGIN
+    SELECT RAISE(ABORT, 'App defined privilege already defined by different application')
+    WHERE EXISTS (SELECT 1 FROM app_defined_privilege_view
+                  WHERE privilege=NEW.privilege AND app_name!=NEW.app_name);
+
+    SELECT RAISE(ABORT, 'Application was not found')
+    WHERE NOT EXISTS (SELECT 1 FROM user_app_pkg_view
+                      WHERE uid=NEW.uid AND app_name=NEW.app_name);
+
+    INSERT OR IGNORE INTO app_defined_privilege (app_id, uid, privilege, type)
+    VALUES ((SELECT app_id FROM app WHERE name=NEW.app_name), NEW.uid, NEW.privilege, NEW.type);
+END;
+
+DROP TRIGGER IF EXISTS app_defined_privilege_view_delete_trigger;
+CREATE TRIGGER app_defined_privilege_view_delete_trigger
+INSTEAD OF DELETE ON app_defined_privilege_view
+BEGIN
+    DELETE FROM app_defined_privilege
+    WHERE app_id=(SELECT app_id FROM app WHERE name=OLD.app_name) AND uid=OLD.uid;
+END;
+
 COMMIT TRANSACTION;
diff --git a/db/updates/update-db-to-v10.sql b/db/updates/update-db-to-v10.sql
new file mode 100644 (file)
index 0000000..a1b3a65
--- /dev/null
@@ -0,0 +1 @@
+-- Dummy script. We only need to trigger db upgrade so that sql gets called and new table is created
\ No newline at end of file
index 1661b5c..50e5d8f 100644 (file)
@@ -41,6 +41,7 @@
 
 #include "dpl/db/sql_connection.h"
 #include "tzplatform-config.h"
+#include "security-manager-types.h"
 
 #include "pkg-info.h"
 
@@ -80,8 +81,15 @@ enum class StmtType {
     EIsPackageSharedRO,
     EIsPackageHybrid,
     EGetPackagesInfo,
+    EAddAppDefinedPrivilege,
+    ERemoveAppDefinedPrivileges,
+    EGetAppDefinedPrivileges,
+    EGetAppForAppDefinedPrivilege,
 };
 
+typedef std::pair<std::string, int> Privilege;
+typedef std::vector<Privilege> PrivilegesVector;
+
 class PrivilegeDb {
     /**
      * PrivilegeDb database class
@@ -134,6 +142,10 @@ private:
         { StmtType::EIsPackageSharedRO, "SELECT shared_ro FROM pkg WHERE name=?"},
         { StmtType::EIsPackageHybrid, "SELECT is_hybrid FROM pkg WHERE name=?"},
         { StmtType::EGetPackagesInfo, "SELECT name, shared_ro, is_hybrid FROM pkg"},
+        { StmtType::EAddAppDefinedPrivilege, "INSERT INTO app_defined_privilege_view (app_name, uid, privilege, type) VALUES (?, ?, ?, ?)"},
+        { StmtType::ERemoveAppDefinedPrivileges, "DELETE FROM app_defined_privilege_view WHERE app_name = ? AND uid = ?"},
+        { StmtType::EGetAppDefinedPrivileges, "SELECT privilege, type FROM app_defined_privilege_view WHERE app_name = ? AND uid = ?"},
+        { StmtType::EGetAppForAppDefinedPrivilege, "SELECT app_name FROM app_defined_privilege_view WHERE privilege = ? AND uid = ?"},
     };
 
     /**
@@ -527,6 +539,53 @@ public:
      * @exception PrivilegeDb::Exception::ConstraintError on constraint violation
      */
     void GetPackagesInfo(std::vector<PkgInfo> &packages);
+
+    /**
+     * Add new privilege defined by application
+     *
+     * @param[in] appName - application identifier
+     * @param[in] uid - user identifier
+     * @param[in] privilege - privilege identifier
+     *
+     * @exception PrivilegeDb::Exception::InternalError on internal error
+     * @exception PrivilegeDb::Exception::ConstraintError on constraint violation
+     */
+    void AddAppDefinedPrivilege(const std::string &appName, uid_t uid, const Privilege &privilege);
+
+    /**
+     * Remove privileges defined by application
+     *
+     * @param[in] appName - application identifier
+     * @param[in] uid - user identifier
+     *
+     * @exception PrivilegeDb::Exception::InternalError on internal error
+     * @exception PrivilegeDb::Exception::ConstraintError on constraint violation
+     */
+    void RemoveAppDefinedPrivileges(const std::string &appName, uid_t uid);
+
+    /**
+     * Retrieve vector of pairs with privilege (1st value) and privilege type (2nd value)
+     *
+     * @param[in]  appName - application identifier
+     * @param[in]  uid - user identifier
+     * @param[out] privileges - list of privileges
+     *
+     * @exception PrivilegeDb::Exception::InternalError on internal error
+     * @exception PrivilegeDb::Exception::ConstraintError on constraint violation
+     */
+    void GetAppDefinedPrivileges(const std::string &appName, uid_t uid, PrivilegesVector &privileges);
+
+    /**
+     * Retrieve application which define privilege
+     *
+     * @param[in]  privilege - privilege identifier
+     * @param[in]  uid - user identifier
+     * @param[out] appName - application identifier
+     *
+     * @exception PrivilegeDb::Exception::InternalError on internal error
+     * @exception PrivilegeDb::Exception::ConstraintError on constraint violation
+     */
+    void GetAppForAppDefinedPrivilege(const Privilege &privilege, uid_t uid, std::string &appName);
 };
 
 } //namespace SecurityManager
index 5617301..0f0abe0 100644 (file)
@@ -588,4 +588,67 @@ void PrivilegeDb::GetPackagesInfo(std::vector<PkgInfo> &packages)
      });
 }
 
+void PrivilegeDb::AddAppDefinedPrivilege(const std::string &appName, uid_t uid, const Privilege &privilege)
+{
+    try_catch<void>([&] {
+        auto command = getStatement(StmtType::EAddAppDefinedPrivilege);
+        command->BindString(1, appName);
+        command->BindInteger(2, uid);
+        command->BindString(3, privilege.first);
+        command->BindInteger(4, privilege.second);
+
+        if (command->Step())
+            LogDebug("Added privilege: " << privilege.first << " defined by: " << appName <<
+                     " and user: " << uid);
+     });
+}
+
+void PrivilegeDb::RemoveAppDefinedPrivileges(const std::string &appName, uid_t uid)
+{
+    try_catch<void>([&] {
+        auto command = getStatement(StmtType::ERemoveAppDefinedPrivileges);
+        command->BindString(1, appName);
+        command->BindInteger(2, uid);
+
+        if (command->Step())
+            LogDebug("Removed privileges defined by: " << appName << " and user: " << uid);
+     });
+}
+
+void PrivilegeDb::GetAppDefinedPrivileges(const std::string &appName, uid_t uid, PrivilegesVector &privileges)
+{
+    try_catch<void>([&] {
+        privileges.clear();
+
+        auto command = getStatement(StmtType::EGetAppDefinedPrivileges);
+        command->BindString(1, appName);
+        command->BindInteger(2, uid);
+        while (command->Step()) {
+            auto privilege = command->GetColumnString(0);
+            auto type = command->GetColumnInteger(1);
+            LogDebug("App: " << appName << " installed by: " << uid << " defines privilege: " << privilege);
+            privileges.push_back(std::make_pair(privilege, type));
+        }
+    });
+}
+
+void PrivilegeDb::GetAppForAppDefinedPrivilege(const Privilege &privilege, uid_t uid, std::string &appName)
+{
+    try_catch<void>([&] {
+        appName.clear();
+
+        auto command = getStatement(StmtType::EGetAppForAppDefinedPrivilege);
+        command->BindString(1, privilege.first);
+        command->BindInteger(2, uid);
+
+        if (command->Step())
+            appName = command->GetColumnString(0);
+
+        if (!appName.empty())
+            LogDebug("Privilege: " << privilege.first << " defined by " << appName);
+        else
+            LogDebug("Privilege: " << privilege.first << " not exist");
+    });
+}
+
 } //namespace SecurityManager