From 4b940f809647068e751e4b483f48b0d87434ec08 Mon Sep 17 00:00:00 2001 From: Nikita Poltorapavlo Date: Mon, 27 Nov 2023 10:59:29 +0200 Subject: [PATCH] RDK-45037 : Secure Storage Thunder Plugin Reason for change: Enhancements to PersistentStore plugin to support Scope, Time To Live. Use of the RPC COM and JSON RPC interfaces. Test Procedure: None Risks: None Signed-off-by: Nikita Poltorapavlo --- interfaces/IStore2.h | 54 ++++ interfaces/IStoreInspector.h | 54 ++++ interfaces/Ids.h | 4 + jsonrpc/PersistentStore.json | 480 +++++++++++++++++++++++++++++++++++ 4 files changed, 592 insertions(+) create mode 100644 interfaces/IStore2.h create mode 100644 interfaces/IStoreInspector.h create mode 100644 jsonrpc/PersistentStore.json diff --git a/interfaces/IStore2.h b/interfaces/IStore2.h new file mode 100644 index 00000000..d385231a --- /dev/null +++ b/interfaces/IStore2.h @@ -0,0 +1,54 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 Metrological + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include "Module.h" + +namespace WPEFramework { +namespace Exchange { + + struct EXTERNAL IStore2 : virtual public Core::IUnknown { + enum { ID = ID_STORE2 }; + + virtual ~IStore2() override = default; + + enum class ScopeType : uint8_t { + DEVICE, + ACCOUNT + }; + + struct EXTERNAL INotification : virtual public Core::IUnknown { + enum { ID = ID_STORE2_NOTIFICATION }; + + virtual ~INotification() override = default; + + virtual void ValueChanged(const string& ns, const string& key, const string& value, const ScopeType scope) = 0; + }; + + virtual uint32_t Register(Exchange::IStore2::INotification* notification) = 0; + virtual uint32_t Unregister(Exchange::IStore2::INotification* notification) = 0; + virtual uint32_t SetValue(const string& ns, const string& key, const string& value, const ScopeType scope, const uint32_t ttl) = 0; + virtual uint32_t GetValue(const string& ns, const string& key, const ScopeType scope, string& value /* @out */, uint32_t& ttl /* @out */) = 0; + virtual uint32_t DeleteKey(const string& ns, const string& key, const ScopeType scope) = 0; + virtual uint32_t DeleteNamespace(const string& ns, const ScopeType scope) = 0; + }; + +} // namespace Exchange +} // namespace WPEFramework diff --git a/interfaces/IStoreInspector.h b/interfaces/IStoreInspector.h new file mode 100644 index 00000000..51dcb13f --- /dev/null +++ b/interfaces/IStoreInspector.h @@ -0,0 +1,54 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 Metrological + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include "Module.h" + +// @stubgen:include + +namespace WPEFramework { +namespace Exchange { + + struct EXTERNAL IStoreInspector : virtual public Core::IUnknown { + enum { ID = ID_STORE_INSPECTOR }; + + virtual ~IStoreInspector() override = default; + + enum class ScopeType : uint8_t { + DEVICE, + ACCOUNT + }; + + struct NamespaceSize { + string ns; + uint32_t size; + }; + + using INamespaceSizeIterator = RPC::IIteratorType; + + virtual uint32_t SetNamespaceLimit(const string& ns, const uint32_t size, const ScopeType scope) = 0; + virtual uint32_t GetNamespaceLimit(const string& ns, const ScopeType scope, uint32_t& size /* @out */) = 0; + virtual uint32_t GetKeys(const string& ns, const ScopeType scope, RPC::IStringIterator*& keys /* @out */) = 0; + virtual uint32_t GetNamespaces(const ScopeType scope, RPC::IStringIterator*& namespaces /* @out */) = 0; + virtual uint32_t GetNamespaceSizes(const ScopeType scope, INamespaceSizeIterator*& namespaceSizes /* @out */) = 0; + }; + +} // namespace Exchange +} // namespace WPEFramework diff --git a/interfaces/Ids.h b/interfaces/Ids.h index 0d97ae4d..e6c4856b 100644 --- a/interfaces/Ids.h +++ b/interfaces/Ids.h @@ -317,6 +317,10 @@ namespace Exchange { ID_STORE = RPC::IDS::ID_EXTERNAL_INTERFACE_OFFSET + 0x440, ID_STORE_NOTIFICATION = ID_STORE + 1, ID_STORE_CACHE = ID_STORE + 2, + ID_STORE2 = ID_STORE + 3, + ID_STORE2_NOTIFICATION = ID_STORE + 4, + ID_STORE_INSPECTOR = ID_STORE + 5, + ID_STORE_INSPECTOR_NAMESPACE_SIZE_ITERATOR = ID_STORE + 6, ID_LISA = RPC::IDS::ID_EXTERNAL_INTERFACE_OFFSET + 0x450, ID_LISA_NOTIFICATION = ID_LISA + 1, diff --git a/jsonrpc/PersistentStore.json b/jsonrpc/PersistentStore.json new file mode 100644 index 00000000..0eab3418 --- /dev/null +++ b/jsonrpc/PersistentStore.json @@ -0,0 +1,480 @@ +{ + "$schema": "interface.schema.json", + "jsonrpc": "2.0", + "info": { + "title": "PertsistentStore API", + "class": "PersistentStore", + "description": "Persistent Store JSON-RPC interface" + }, + "common": { + "$ref": "common.json" + }, + "definitions": { + "namespace": { + "summary": "Namespace", + "type": "string", + "example": "ns1" + }, + "key": { + "summary": "Key", + "type": "string", + "example": "key1" + }, + "value": { + "summary": "Value", + "type": "string", + "example": "value1" + }, + "scope": { + "summary": "Scope", + "type": "string", + "enum": [ + "device", + "account" + ], + "default": "device", + "example": "device" + }, + "size": { + "summary": "Size in bytes", + "type": "number", + "example": 100 + }, + "ttl": { + "summary": "Time in seconds", + "type": "number", + "example": 100 + }, + "success": { + "summary": "Legacy parameter (always true)", + "type": "boolean", + "default": true, + "example": true + } + }, + "methods": { + "deleteKey": { + "summary": "Deletes a key from the specified namespace", + "params": { + "type": "object", + "properties": { + "namespace": { + "$ref": "#/definitions/namespace" + }, + "key": { + "$ref": "#/definitions/key" + }, + "scope": { + "$ref": "#/definitions/scope" + } + }, + "required": [ + "namespace", + "key" + ] + }, + "result": { + "type": "object", + "properties": { + "success": { + "$ref": "#/definitions/success" + } + }, + "required": [ + "success" + ] + }, + "errors": [ + { + "description": "Unknown error", + "$ref": "#/common/errors/general" + } + ] + }, + "deleteNamespace": { + "summary": "Deletes the specified namespace", + "params": { + "type": "object", + "properties": { + "namespace": { + "$ref": "#/definitions/namespace" + }, + "scope": { + "$ref": "#/definitions/scope" + } + }, + "required": [ + "namespace" + ] + }, + "result": { + "type": "object", + "properties": { + "success": { + "$ref": "#/definitions/success" + } + }, + "required": [ + "success" + ] + }, + "errors": [ + { + "description": "Unknown error", + "$ref": "#/common/errors/general" + } + ] + }, + "flushCache": { + "summary": "Flushes the device cache", + "result": { + "type": "object", + "properties": { + "success": { + "$ref": "#/definitions/success" + } + }, + "required": [ + "success" + ] + }, + "errors": [ + { + "description": "Unknown error", + "$ref": "#/common/errors/general" + } + ] + }, + "getKeys": { + "summary": "Returns the keys that are stored in the specified namespace", + "params": { + "type": "object", + "properties": { + "namespace": { + "$ref": "#/definitions/namespace" + }, + "scope": { + "$ref": "#/definitions/scope" + } + }, + "required": [ + "namespace" + ] + }, + "result": { + "type": "object", + "properties": { + "keys": { + "type": "array", + "items": { + "$ref": "#/definitions/key" + } + }, + "success": { + "$ref": "#/definitions/success" + } + }, + "required": [ + "keys", + "success" + ] + }, + "errors": [ + { + "description": "Unknown error", + "$ref": "#/common/errors/general" + } + ] + }, + "getNamespaces": { + "summary": "Returns the namespaces", + "params": { + "type": "object", + "properties": { + "scope": { + "$ref": "#/definitions/scope" + } + }, + "required": [] + }, + "result": { + "type": "object", + "properties": { + "namespaces": { + "type": "array", + "items": { + "$ref": "#/definitions/namespace" + } + }, + "success": { + "$ref": "#/definitions/success" + } + }, + "required": [ + "namespaces", + "success" + ] + }, + "errors": [ + { + "description": "Unknown error", + "$ref": "#/common/errors/general" + } + ] + }, + "getStorageSizes": { + "summary": "Returns the size occupied by each namespace", + "params": { + "type": "object", + "properties": { + "scope": { + "$ref": "#/definitions/scope" + } + }, + "required": [] + }, + "result": { + "type": "object", + "properties": { + "storageList": { + "type": "array", + "items": { + "type": "object", + "properties": { + "namespace": { + "$ref": "#/definitions/namespace" + }, + "size": { + "$ref": "#/definitions/size" + } + }, + "required": [ + "namespace", + "size" + ] + } + } + }, + "required": [ + "storageList" + ] + }, + "errors": [ + { + "description": "Unknown error", + "$ref": "#/common/errors/general" + } + ] + }, + "getValue": { + "summary": "Returns the value of a key from the specified namespace", + "params": { + "type": "object", + "properties": { + "namespace": { + "$ref": "#/definitions/namespace" + }, + "key": { + "$ref": "#/definitions/key" + }, + "scope": { + "$ref": "#/definitions/scope" + } + }, + "required": [ + "namespace", + "key" + ] + }, + "result": { + "type": "object", + "properties": { + "value": { + "$ref": "#/definitions/value" + }, + "success": { + "$ref": "#/definitions/success" + }, + "ttl": { + "$ref": "#/definitions/ttl" + } + }, + "required": [ + "value", + "success" + ] + }, + "errors": [ + { + "description": "Time is not synced", + "$ref": "#/common/errors/pendingconditions" + }, + { + "description": "Unknown namespace", + "$ref": "#/common/errors/notexist" + }, + { + "description": "Unknown key", + "$ref": "#/common/errors/unknownkey" + }, + { + "description": "Unknown error", + "$ref": "#/common/errors/general" + } + ] + }, + "setValue": { + "summary": "Sets the value of a key in the the specified namespace", + "params": { + "type": "object", + "properties": { + "namespace": { + "$ref": "#/definitions/namespace" + }, + "key": { + "$ref": "#/definitions/key" + }, + "value": { + "$ref": "#/definitions/value" + }, + "scope": { + "$ref": "#/definitions/scope" + }, + "ttl": { + "$ref": "#/definitions/ttl" + } + }, + "required": [ + "namespace", + "key", + "value" + ] + }, + "result": { + "type": "object", + "properties": { + "success": { + "$ref": "#/definitions/success" + } + }, + "required": [ + "success" + ] + }, + "errors": [ + { + "description": "Time is not synced", + "$ref": "#/common/errors/pendingconditions" + }, + { + "description": "Empty/too large namespace or key, or the storage doesn't have enough space", + "$ref": "#/common/errors/invalidinputlength" + }, + { + "description": "Unknown error", + "$ref": "#/common/errors/general" + } + ] + }, + "setNamespaceStorageLimit": { + "summary": "Sets the storage limit for a given namespace", + "params": { + "type": "object", + "properties": { + "namespace": { + "$ref": "#/definitions/namespace" + }, + "storageLimit": { + "$ref": "#/definitions/size" + }, + "scope": { + "$ref": "#/definitions/scope" + } + }, + "required": [ + "namespace", + "storageLimit" + ] + }, + "result": { + "$ref": "#/common/results/void" + }, + "errors": [ + { + "description": "Empty/too large namespace, or the storage doesn't have enough space", + "$ref": "#/common/errors/invalidinputlength" + }, + { + "description": "Unknown error", + "$ref": "#/common/errors/general" + } + ] + }, + "getNamespaceStorageLimit": { + "summary": "Returns the storage limit for a given namespace", + "params": { + "type": "object", + "properties": { + "namespace": { + "$ref": "#/definitions/namespace" + }, + "scope": { + "$ref": "#/definitions/scope" + } + }, + "required": [ + "namespace" + ] + }, + "result": { + "type": "object", + "properties": { + "storageLimit": { + "$ref": "#/definitions/size" + } + }, + "required": [ + "storageLimit" + ] + }, + "errors": [ + { + "description": "Unknown namespace", + "$ref": "#/common/errors/notexist" + }, + { + "description": "Unknown error", + "$ref": "#/common/errors/general" + } + ] + } + }, + "events": { + "onValueChanged": { + "summary": "Triggered whenever any of the values stored are changed using setValue", + "params": { + "type": "object", + "properties": { + "namespace": { + "$ref": "#/definitions/namespace" + }, + "key": { + "$ref": "#/definitions/key" + }, + "value": { + "$ref": "#/definitions/value" + }, + "scope": { + "$ref": "#/definitions/scope" + } + }, + "required": [ + "namespace", + "key", + "value", + "scope" + ] + } + } + } +} \ No newline at end of file