From 99dcfe9e8c73159018d5d32527e9d40cd7c40036 Mon Sep 17 00:00:00 2001 From: James Swan <122404367+swan-amazon@users.noreply.github.com> Date: Fri, 9 Aug 2024 23:25:54 +0000 Subject: [PATCH] Add initial feature logic for Terms and Conditions (TC) acknowledgements This commit introduces the initial logic for handling Terms and Conditions (TC) acknowledgements in the General Commissioning cluster. The logic includes support for setting and checking TC acknowledgements and versions during the commissioning process. Changes include: - Handling TC acknowledgements and TC acknowledgement version in the pairing command. - Logic to read TC attributes and check TC acceptance in the General Commissioning server. - Introduction of classes to manage TC acceptance logic. - Initialization and use of TC providers in the server setup. - Addition of a new commissioning stage for TC acknowledgements in the commissioning flow. The feature logic is currently disabled and will be enabled in an example in a subsequent commit. --- .../general-commissioning-server.cpp | 157 ++++++++- src/app/common_flags.gni | 4 + src/app/server/BUILD.gn | 42 ++- .../DefaultEnhancedSetupFlowProvider.cpp | 158 +++++++++ .../server/DefaultEnhancedSetupFlowProvider.h | 65 ++++ .../DefaultTermsAndConditionsProvider.cpp | 146 +++++++++ .../DefaultTermsAndConditionsProvider.h | 58 ++++ src/app/server/EnhancedSetupFlowProvider.h | 87 +++++ src/app/server/Server.cpp | 10 +- src/app/server/Server.h | 40 ++- src/app/server/TermsAndConditionsProvider.h | 68 ++++ src/app/tests/BUILD.gn | 6 +- .../TestDefaultEnhancedSetupFlowProvider.cpp | 306 ++++++++++++++++++ .../TestDefaultTermsAndConditionsProvider.cpp | 226 +++++++++++++ src/lib/core/CHIPConfig.h | 54 ++++ src/lib/support/DefaultStorageKeyAllocator.h | 6 +- 16 files changed, 1427 insertions(+), 6 deletions(-) create mode 100644 src/app/server/DefaultEnhancedSetupFlowProvider.cpp create mode 100644 src/app/server/DefaultEnhancedSetupFlowProvider.h create mode 100644 src/app/server/DefaultTermsAndConditionsProvider.cpp create mode 100644 src/app/server/DefaultTermsAndConditionsProvider.h create mode 100644 src/app/server/EnhancedSetupFlowProvider.h create mode 100644 src/app/server/TermsAndConditionsProvider.h create mode 100644 src/app/tests/TestDefaultEnhancedSetupFlowProvider.cpp create mode 100644 src/app/tests/TestDefaultTermsAndConditionsProvider.cpp diff --git a/src/app/clusters/general-commissioning-server/general-commissioning-server.cpp b/src/app/clusters/general-commissioning-server/general-commissioning-server.cpp index 4bf97face53740..d0d9b11de8ec22 100644 --- a/src/app/clusters/general-commissioning-server/general-commissioning-server.cpp +++ b/src/app/clusters/general-commissioning-server/general-commissioning-server.cpp @@ -1,6 +1,6 @@ /** * - * Copyright (c) 2021 Project CHIP Authors + * Copyright (c) 2021-2024 Project CHIP Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -27,6 +27,9 @@ #include #include #include +#if CHIP_CONFIG_TC_REQUIRED +#include +#endif #include #include #include @@ -69,6 +72,12 @@ class GeneralCommissioningAttrAccess : public AttributeAccessInterface CHIP_ERROR ReadIfSupported(CHIP_ERROR (ConfigurationManager::*getter)(uint8_t &), AttributeValueEncoder & aEncoder); CHIP_ERROR ReadBasicCommissioningInfo(AttributeValueEncoder & aEncoder); CHIP_ERROR ReadSupportsConcurrentConnection(AttributeValueEncoder & aEncoder); + template + CHIP_ERROR ReadEnhancedSetupFlowProvider(Provider * const provider, CHIP_ERROR (Provider::*const nonConstGetter)(T &), + AttributeValueEncoder & aEncoder); + template + CHIP_ERROR ReadEnhancedSetupFlowProvider(Provider * const provider, CHIP_ERROR (Provider::*const getter)(T &) const, + AttributeValueEncoder & aEncoder); }; GeneralCommissioningAttrAccess gAttrAccess; @@ -95,6 +104,28 @@ CHIP_ERROR GeneralCommissioningAttrAccess::Read(const ConcreteReadAttributePath case SupportsConcurrentConnection::Id: { return ReadSupportsConcurrentConnection(aEncoder); } +#if CHIP_CONFIG_TC_REQUIRED + case TCAcceptedVersion::Id: { + auto provider = Server::GetInstance().GetEnhancedSetupFlowProvider(); + auto getter = &EnhancedSetupFlowProvider::GetTermsAndConditionsAcceptedAcknowledgementsVersion; + return ReadEnhancedSetupFlowProvider(provider, getter, aEncoder); + } + case TCMinRequiredVersion::Id: { + auto provider = Server::GetInstance().GetEnhancedSetupFlowProvider(); + auto getter = &EnhancedSetupFlowProvider::GetTermsAndConditionsRequiredAcknowledgementsVersion; + return ReadEnhancedSetupFlowProvider(provider, getter, aEncoder); + } + case TCAcknowledgements::Id: { + auto provider = Server::GetInstance().GetEnhancedSetupFlowProvider(); + auto getter = &EnhancedSetupFlowProvider::GetTermsAndConditionsAcceptedAcknowledgements; + return ReadEnhancedSetupFlowProvider(provider, getter, aEncoder); + } + case TCAcknowledgementsRequired::Id: { + auto provider = Server::GetInstance().GetEnhancedSetupFlowProvider(); + auto getter = &EnhancedSetupFlowProvider::IsTermsAndConditionsAcceptanceRequired; + return ReadEnhancedSetupFlowProvider(provider, getter, aEncoder); + } +#endif default: { break; } @@ -144,6 +175,100 @@ CHIP_ERROR GeneralCommissioningAttrAccess::ReadSupportsConcurrentConnection(Attr return aEncoder.Encode(supportsConcurrentConnection); } +template +CHIP_ERROR GeneralCommissioningAttrAccess::ReadEnhancedSetupFlowProvider(Provider * const provider, + CHIP_ERROR (Provider::*const nonConstGetter)(T &), + AttributeValueEncoder & aEncoder) +{ + if (nullptr == provider) + { + return CHIP_ERROR_PERSISTED_STORAGE_FAILED; + } + + T value; + CHIP_ERROR err = (provider->*nonConstGetter)(value); + if (err != CHIP_NO_ERROR) + { + return err; + } + + return aEncoder.Encode(value); +} + +template +CHIP_ERROR GeneralCommissioningAttrAccess::ReadEnhancedSetupFlowProvider(Provider * const provider, + CHIP_ERROR (Provider::*const getter)(T &) const, + AttributeValueEncoder & aEncoder) +{ + // Removing the const qualifier from the getter function pointer because there are a handful of getter functions that are not + // correctly marked as const. + using NonConstGetter = CHIP_ERROR (Provider::*)(T &); + NonConstGetter nonConstGetter = reinterpret_cast(getter); + return ReadEnhancedSetupFlowProvider(provider, nonConstGetter, aEncoder); +} + +} // anonymous namespace +namespace { + +#if CHIP_CONFIG_TC_REQUIRED +CHIP_ERROR checkTermsAndConditionsAcknowledgementsState(CommissioningErrorEnum & errorCode) +{ + EnhancedSetupFlowProvider * enhancedSetupFlowProvider = Server::GetInstance().GetEnhancedSetupFlowProvider(); + + CHIP_ERROR err; + + uint16_t termsAndConditionsAcceptedAcknowledgements; + bool hasRequiredTermAccepted; + bool hasRequiredTermVersionAccepted; + + err = enhancedSetupFlowProvider->GetTermsAndConditionsAcceptedAcknowledgements(termsAndConditionsAcceptedAcknowledgements); + if (!::chip::ChipError::IsSuccess(err)) + { + ChipLogError(AppServer, "Failed to GetTermsAndConditionsAcceptedAcknowledgements"); + return err; + } + + err = enhancedSetupFlowProvider->HasTermsAndConditionsRequiredAcknowledgementsBeenAccepted(hasRequiredTermAccepted); + if (!::chip::ChipError::IsSuccess(err)) + { + ChipLogError(AppServer, "Failed to HasTermsAndConditionsRequiredAcknowledgementsBeenAccepted"); + return err; + } + + err = + enhancedSetupFlowProvider->HasTermsAndConditionsRequiredAcknowledgementsVersionBeenAccepted(hasRequiredTermVersionAccepted); + if (!::chip::ChipError::IsSuccess(err)) + { + ChipLogError(AppServer, "Failed to HasTermsAndConditionsRequiredAcknowledgementsVersionBeenAccepted"); + return err; + } + + if (!hasRequiredTermAccepted) + { + uint16_t requiredAcknowledgements = 0; + (void) enhancedSetupFlowProvider->GetTermsAndConditionsRequiredAcknowledgements(requiredAcknowledgements); + + ChipLogProgress(AppServer, "Required terms and conditions, 0x%04x,have not been accepted", requiredAcknowledgements); + errorCode = (0 == termsAndConditionsAcceptedAcknowledgements) ? CommissioningErrorEnum::kTCAcknowledgementsNotReceived + : CommissioningErrorEnum::kRequiredTCNotAccepted; + return CHIP_NO_ERROR; + } + + if (!hasRequiredTermVersionAccepted) + { + uint16_t requiredAcknowledgementsVersion = 0; + (void) enhancedSetupFlowProvider->GetTermsAndConditionsRequiredAcknowledgementsVersion(requiredAcknowledgementsVersion); + ChipLogProgress(AppServer, "Minimum terms and conditions version, 0x%04x, has not been accepted", + requiredAcknowledgementsVersion); + errorCode = CommissioningErrorEnum::kTCMinVersionNotMet; + return CHIP_NO_ERROR; + } + + errorCode = CommissioningErrorEnum::kOk; + return CHIP_NO_ERROR; +} +#endif + } // anonymous namespace bool emberAfGeneralCommissioningClusterArmFailSafeCallback(app::CommandHandler * commandObj, @@ -239,6 +364,10 @@ bool emberAfGeneralCommissioningClusterCommissioningCompleteCallback( } else { +#if CHIP_CONFIG_TC_REQUIRED + CheckSuccess(checkTermsAndConditionsAcknowledgementsState(response.errorCode), Failure); +#endif + if (failSafe.NocCommandHasBeenInvoked()) { CHIP_ERROR err = fabricTable.CommitPendingFabricData(); @@ -328,6 +457,27 @@ bool emberAfGeneralCommissioningClusterSetRegulatoryConfigCallback(app::CommandH return true; } +bool emberAfGeneralCommissioningClusterSetTCAcknowledgementsCallback( + chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath, + const chip::app::Clusters::GeneralCommissioning::Commands::SetTCAcknowledgements::DecodableType & commandData) +{ +#if !CHIP_CONFIG_TC_REQUIRED + return false; + +#else + MATTER_TRACE_SCOPE("SetTCAcknowledgements", "GeneralCommissioning"); + Commands::SetTCAcknowledgementsResponse::Type response; + EnhancedSetupFlowProvider * const enhancedSetupFlowProvider = Server::GetInstance().GetEnhancedSetupFlowProvider(); + uint16_t acknowledgements = commandData.TCUserResponse; + uint16_t acknowledgementsVersion = commandData.TCVersion; + CheckSuccess(enhancedSetupFlowProvider->SetTermsAndConditionsAcceptance(acknowledgements, acknowledgementsVersion), Failure); + CheckSuccess(checkTermsAndConditionsAcknowledgementsState(response.errorCode), Failure); + commandObj->AddResponse(commandPath, response); + return true; + +#endif +} + namespace { void OnPlatformEventHandler(const DeviceLayer::ChipDeviceEvent * event, intptr_t arg) { @@ -335,6 +485,11 @@ void OnPlatformEventHandler(const DeviceLayer::ChipDeviceEvent * event, intptr_t { // Spec says to reset Breadcrumb attribute to 0. Breadcrumb::Set(0, 0); + +#if CHIP_CONFIG_TC_REQUIRED + // Clear terms and conditions acceptance on failsafe timer expiration + Server::GetInstance().GetEnhancedSetupFlowProvider()->ClearTermsAndConditionsAcceptance(); +#endif } } diff --git a/src/app/common_flags.gni b/src/app/common_flags.gni index be1149b2b67eb5..34e8549a35d1cd 100644 --- a/src/app/common_flags.gni +++ b/src/app/common_flags.gni @@ -18,6 +18,10 @@ declare_args() { chip_enable_read_client = true chip_build_controller_dynamic_server = false + chip_config_tc_required = false + chip_config_tc_required_acknowledgements = 0 + chip_config_tc_required_acknowledgements_version = 0 + # Flag that controls whether the time-to-wait from BUSY responses is # communicated to OperationalSessionSetup API consumers. chip_enable_busy_handling_for_operational_session_setup = true diff --git a/src/app/server/BUILD.gn b/src/app/server/BUILD.gn index 401356d7b753a4..e49513ad398d4f 100644 --- a/src/app/server/BUILD.gn +++ b/src/app/server/BUILD.gn @@ -1,4 +1,4 @@ -# Copyright (c) 2020 Project CHIP Authors +# Copyright (c) 2020-2024 Project CHIP Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -24,6 +24,41 @@ config("server_config") { } } +config("enhanced_setup_flow_config") { + defines = [] + if (chip_config_tc_required) { + defines += [ + "CHIP_CONFIG_TC_REQUIRED=1", + "CHIP_CONFIG_TC_REQUIRED_ACKNOWLEDGEMENTS=${chip_config_tc_required_acknowledgements}", + "CHIP_CONFIG_TC_REQUIRED_ACKNOWLEDGEMENTS_VERSION=${chip_config_tc_required_acknowledgements_version}", + ] + } else { + defines += [ "CHIP_CONFIG_TC_REQUIRED=0" ] + } +} + +source_set("enhanced_setup_flow_interface") { + sources = [ + "DefaultEnhancedSetupFlowProvider.h", + "DefaultTermsAndConditionsProvider.h", + "EnhancedSetupFlowProvider.h", + "TermsAndConditionsProvider.h", + ] + + public_configs = [ ":enhanced_setup_flow_config" ] + + public_deps = [ "${chip_root}/src/lib/core" ] +} + +source_set("enhanced_setup_flow") { + sources = [ + "DefaultEnhancedSetupFlowProvider.cpp", + "DefaultTermsAndConditionsProvider.cpp", + ] + + deps = [ ":enhanced_setup_flow_interface" ] +} + static_library("server") { output_name = "libCHIPAppServer" @@ -51,6 +86,7 @@ static_library("server") { cflags = [ "-Wconversion" ] public_deps = [ + ":enhanced_setup_flow_interface", "${chip_root}/src/app", "${chip_root}/src/app:test-event-trigger", "${chip_root}/src/app/icd/server:check-in-back-off", @@ -79,4 +115,8 @@ static_library("server") { [ "${chip_root}/src/app/icd/server:default-check-in-back-off" ] } } + + if (chip_config_tc_required) { + public_deps += [ ":enhanced_setup_flow" ] + } } diff --git a/src/app/server/DefaultEnhancedSetupFlowProvider.cpp b/src/app/server/DefaultEnhancedSetupFlowProvider.cpp new file mode 100644 index 00000000000000..647e705c2b94db --- /dev/null +++ b/src/app/server/DefaultEnhancedSetupFlowProvider.cpp @@ -0,0 +1,158 @@ +/* + * + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * 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. + */ + +#include "DefaultEnhancedSetupFlowProvider.h" + +#include +#include + +CHIP_ERROR chip::app::DefaultEnhancedSetupFlowProvider::Init(TermsAndConditionsProvider * const inTermsAndConditionsProvider) +{ + VerifyOrReturnError(nullptr != inTermsAndConditionsProvider, CHIP_ERROR_INVALID_ARGUMENT); + + mTermsAndConditionsProvider = inTermsAndConditionsProvider; + + return CHIP_NO_ERROR; +} + +CHIP_ERROR +chip::app::DefaultEnhancedSetupFlowProvider::HasTermsAndConditionsRequiredAcknowledgementsBeenAccepted(bool & outAccepted) const +{ + uint16_t requiredAcknowledgements; + uint16_t requiredAcknowledgementsVersion; + uint16_t acceptedAcknowledgements; + uint16_t acceptedAcknowledgementsVersion; + + VerifyOrReturnError(nullptr != mTermsAndConditionsProvider, CHIP_ERROR_UNINITIALIZED); + ReturnErrorOnFailure(mTermsAndConditionsProvider->GetRequirements(requiredAcknowledgements, requiredAcknowledgementsVersion)); + + if (0 == requiredAcknowledgements) + { + outAccepted = true; + return CHIP_NO_ERROR; + } + + ReturnErrorOnFailure(mTermsAndConditionsProvider->GetAcceptance(acceptedAcknowledgements, acceptedAcknowledgementsVersion)); + + outAccepted = ((requiredAcknowledgements & acceptedAcknowledgements) == requiredAcknowledgements); + + return CHIP_NO_ERROR; +} + +CHIP_ERROR chip::app::DefaultEnhancedSetupFlowProvider::HasTermsAndConditionsRequiredAcknowledgementsVersionBeenAccepted( + bool & outAccepted) const +{ + uint16_t requiredAcknowledgements; + uint16_t requiredAcknowledgementsVersion; + uint16_t acceptedAcknowledgements; + uint16_t acceptedAcknowledgementsVersion; + + VerifyOrReturnError(nullptr != mTermsAndConditionsProvider, CHIP_ERROR_UNINITIALIZED); + ReturnErrorOnFailure(mTermsAndConditionsProvider->GetRequirements(requiredAcknowledgements, requiredAcknowledgementsVersion)); + + if (0 == requiredAcknowledgementsVersion) + { + outAccepted = true; + return CHIP_NO_ERROR; + } + + ReturnErrorOnFailure(mTermsAndConditionsProvider->GetAcceptance(acceptedAcknowledgements, acceptedAcknowledgementsVersion)); + + outAccepted = (acceptedAcknowledgementsVersion >= requiredAcknowledgementsVersion); + + return CHIP_NO_ERROR; +} + +CHIP_ERROR chip::app::DefaultEnhancedSetupFlowProvider::IsTermsAndConditionsAcceptanceRequired(bool & outValue) const +{ + // Default implementation requires terms and conditions check only if not previously accepted. Other implementations may skip + // requiring a terms and conditions check on secondary commissioning, in the case that the required terms and conditions may + // have changed. + return HasTermsAndConditionsRequiredAcknowledgementsVersionBeenAccepted(outValue); +} + +CHIP_ERROR chip::app::DefaultEnhancedSetupFlowProvider::GetTermsAndConditionsRequiredAcknowledgements(uint16_t & outValue) const +{ + uint16_t requiredAcknowledgements; + uint16_t requiredAcknowledgementsVersion; + + VerifyOrReturnError(nullptr != mTermsAndConditionsProvider, CHIP_ERROR_UNINITIALIZED); + ReturnErrorOnFailure(mTermsAndConditionsProvider->GetRequirements(requiredAcknowledgements, requiredAcknowledgementsVersion)); + + outValue = requiredAcknowledgements; + + return CHIP_NO_ERROR; +} + +CHIP_ERROR +chip::app::DefaultEnhancedSetupFlowProvider::GetTermsAndConditionsRequiredAcknowledgementsVersion(uint16_t & outValue) const +{ + uint16_t requiredAcknowledgements; + uint16_t requiredAcknowledgementsVersion; + + VerifyOrReturnError(nullptr != mTermsAndConditionsProvider, CHIP_ERROR_UNINITIALIZED); + ReturnErrorOnFailure(mTermsAndConditionsProvider->GetRequirements(requiredAcknowledgements, requiredAcknowledgementsVersion)); + + outValue = requiredAcknowledgementsVersion; + + return CHIP_NO_ERROR; +} + +CHIP_ERROR chip::app::DefaultEnhancedSetupFlowProvider::GetTermsAndConditionsAcceptedAcknowledgements(uint16_t & outValue) const +{ + uint16_t acceptedAcknowledgements; + uint16_t acceptedAcknowledgementsVersion; + + VerifyOrReturnError(nullptr != mTermsAndConditionsProvider, CHIP_ERROR_UNINITIALIZED); + ReturnErrorOnFailure(mTermsAndConditionsProvider->GetAcceptance(acceptedAcknowledgements, acceptedAcknowledgementsVersion)); + + outValue = acceptedAcknowledgements; + + return CHIP_NO_ERROR; +} + +CHIP_ERROR +chip::app::DefaultEnhancedSetupFlowProvider::GetTermsAndConditionsAcceptedAcknowledgementsVersion(uint16_t & outValue) const +{ + uint16_t acceptedAcknowledgements; + uint16_t acceptedAcknowledgementsVersion; + + VerifyOrReturnError(nullptr != mTermsAndConditionsProvider, CHIP_ERROR_UNINITIALIZED); + ReturnErrorOnFailure(mTermsAndConditionsProvider->GetAcceptance(acceptedAcknowledgements, acceptedAcknowledgementsVersion)); + + outValue = acceptedAcknowledgementsVersion; + + return CHIP_NO_ERROR; +} + +CHIP_ERROR chip::app::DefaultEnhancedSetupFlowProvider::SetTermsAndConditionsAcceptance(uint16_t inTCAcknowledgementsValue, + uint16_t inTCAcknowledgementsVersionValue) +{ + VerifyOrReturnError(nullptr != mTermsAndConditionsProvider, CHIP_ERROR_UNINITIALIZED); + ReturnErrorOnFailure(mTermsAndConditionsProvider->SetAcceptance(inTCAcknowledgementsValue, inTCAcknowledgementsVersionValue)); + + return CHIP_NO_ERROR; +} + +CHIP_ERROR chip::app::DefaultEnhancedSetupFlowProvider::ClearTermsAndConditionsAcceptance() +{ + VerifyOrReturnError(nullptr != mTermsAndConditionsProvider, CHIP_ERROR_UNINITIALIZED); + ReturnErrorOnFailure(mTermsAndConditionsProvider->ClearAcceptance()); + + return CHIP_NO_ERROR; +} diff --git a/src/app/server/DefaultEnhancedSetupFlowProvider.h b/src/app/server/DefaultEnhancedSetupFlowProvider.h new file mode 100644 index 00000000000000..e5b9ed17ef5bfa --- /dev/null +++ b/src/app/server/DefaultEnhancedSetupFlowProvider.h @@ -0,0 +1,65 @@ +/* + * + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * 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 "EnhancedSetupFlowProvider.h" + +#include + +#include +#include + +#include "TermsAndConditionsProvider.h" + +namespace chip { +namespace app { +class DefaultEnhancedSetupFlowProvider : public EnhancedSetupFlowProvider +{ +public: + /** + * @brief Initializes the EnhancedSetupFlowProvider. + * + * @param[in] inTermsAndConditionsProvider The terms and conditions provide dependency. + */ + CHIP_ERROR Init(TermsAndConditionsProvider * const inTermsAndConditionsProvider); + + CHIP_ERROR HasTermsAndConditionsRequiredAcknowledgementsBeenAccepted(bool & outAccepted) const override; + + CHIP_ERROR HasTermsAndConditionsRequiredAcknowledgementsVersionBeenAccepted(bool & outAccepted) const override; + + CHIP_ERROR IsTermsAndConditionsAcceptanceRequired(bool & outValue) const override; + + CHIP_ERROR GetTermsAndConditionsRequiredAcknowledgements(uint16_t & outValue) const override; + + CHIP_ERROR GetTermsAndConditionsRequiredAcknowledgementsVersion(uint16_t & outValue) const override; + + CHIP_ERROR GetTermsAndConditionsAcceptedAcknowledgements(uint16_t & outValue) const override; + + CHIP_ERROR GetTermsAndConditionsAcceptedAcknowledgementsVersion(uint16_t & outValue) const override; + + CHIP_ERROR SetTermsAndConditionsAcceptance(uint16_t aTCAcknowledgements, uint16_t inTCAcknowledgementsVersionValue) override; + + CHIP_ERROR ClearTermsAndConditionsAcceptance() override; + +private: + TermsAndConditionsProvider * mTermsAndConditionsProvider; +}; + +} // namespace app +} // namespace chip diff --git a/src/app/server/DefaultTermsAndConditionsProvider.cpp b/src/app/server/DefaultTermsAndConditionsProvider.cpp new file mode 100644 index 00000000000000..c38390823f04a2 --- /dev/null +++ b/src/app/server/DefaultTermsAndConditionsProvider.cpp @@ -0,0 +1,146 @@ +/* + * + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * 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. + */ + +#include "DefaultTermsAndConditionsProvider.h" + +#include +#include +#include +#include +#include +#include + +namespace { +constexpr chip::TLV::Tag kSerializationVersionTag = chip::TLV::ContextTag(1); +constexpr chip::TLV::Tag kAcceptedAcknowledgementsTag = chip::TLV::ContextTag(2); +constexpr chip::TLV::Tag kAcceptedAcknowledgementsVersionTag = chip::TLV::ContextTag(3); +constexpr uint8_t kSerializationVersion = 1; + +constexpr size_t kEstimatedTlvBufferSize = chip::TLV::EstimateStructOverhead(sizeof(uint8_t), // SerializationVersion + sizeof(uint16_t), // AcceptedAcknowledgements + sizeof(uint16_t) // AcceptedAcknowledgementsVersion + ) * + 2; // Extra space for rollback compatibility +} // namespace + +CHIP_ERROR chip::app::DefaultTermsAndConditionsProvider::Init(chip::PersistentStorageDelegate * const inPersistentStorageDelegate, + uint16_t inRequiredAcknowledgementsValue, + uint16_t inRequiredAcknowledgementsVersionValue) +{ + VerifyOrReturnError(nullptr != inPersistentStorageDelegate, CHIP_ERROR_INVALID_ARGUMENT); + + mPersistentStorageDelegate = inPersistentStorageDelegate; + mRequiredAcknowledgementsValue = inRequiredAcknowledgementsValue; + mRequiredAcknowledgementsVersionValue = inRequiredAcknowledgementsVersionValue; + + return CHIP_NO_ERROR; +} + +CHIP_ERROR chip::app::DefaultTermsAndConditionsProvider::ClearAcceptance() +{ + VerifyOrReturnError(nullptr != mPersistentStorageDelegate, CHIP_ERROR_UNINITIALIZED); + + const chip::StorageKeyName storageKey = DefaultStorageKeyAllocator::TermsAndConditionsAcceptance(); + ReturnErrorOnFailure(mPersistentStorageDelegate->SyncDeleteKeyValue(storageKey.KeyName())); + + return CHIP_NO_ERROR; +} + +CHIP_ERROR chip::app::DefaultTermsAndConditionsProvider::GetAcceptance(uint16_t & outAcknowledgementsValue, + uint16_t & outAcknowledgementsVersionValue) const +{ + uint8_t serializationVersion = 0; + uint16_t acknowledgements = 0; + uint16_t acknowledgementsVersion = 0; + + chip::TLV::TLVReader tlvReader; + chip::TLV::TLVType tlvContainer; + + uint8_t buffer[kEstimatedTlvBufferSize] = { 0 }; + uint16_t bufferSize = sizeof(buffer); + + VerifyOrReturnError(nullptr != mPersistentStorageDelegate, CHIP_ERROR_UNINITIALIZED); + + const chip::StorageKeyName storageKey = DefaultStorageKeyAllocator::TermsAndConditionsAcceptance(); + CHIP_ERROR err = mPersistentStorageDelegate->SyncGetKeyValue(storageKey.KeyName(), &buffer, bufferSize); + if (CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND == err) + { + outAcknowledgementsValue = acknowledgements; + outAcknowledgementsVersionValue = acknowledgementsVersion; + + return CHIP_NO_ERROR; + } + + VerifyOrReturnError(CHIP_NO_ERROR == err, err); + + tlvReader.Init(buffer, bufferSize); + ReturnErrorOnFailure(tlvReader.Next(chip::TLV::kTLVType_Structure, chip::TLV::AnonymousTag())); + ReturnErrorOnFailure(tlvReader.EnterContainer(tlvContainer)); + ReturnErrorOnFailure(tlvReader.Next(kSerializationVersionTag)); + ReturnErrorOnFailure(tlvReader.Get(serializationVersion)); + ReturnErrorOnFailure(tlvReader.Next(kAcceptedAcknowledgementsTag)); + ReturnErrorOnFailure(tlvReader.Get(acknowledgements)); + ReturnErrorOnFailure(tlvReader.Next(kAcceptedAcknowledgementsVersionTag)); + ReturnErrorOnFailure(tlvReader.Get(acknowledgementsVersion)); + ReturnErrorOnFailure(tlvReader.ExitContainer(tlvContainer)); + + if (kSerializationVersion != serializationVersion) + { + return CHIP_ERROR_VERSION_MISMATCH; + } + + outAcknowledgementsValue = acknowledgements; + outAcknowledgementsVersionValue = acknowledgementsVersion; + + return CHIP_NO_ERROR; +} + +CHIP_ERROR chip::app::DefaultTermsAndConditionsProvider::GetRequirements(uint16_t & outAcknowledgementsValue, + uint16_t & outAcknowledgementsVersionValue) const +{ + outAcknowledgementsValue = mRequiredAcknowledgementsValue; + outAcknowledgementsVersionValue = mRequiredAcknowledgementsVersionValue; + + return CHIP_NO_ERROR; +} + +CHIP_ERROR chip::app::DefaultTermsAndConditionsProvider::SetAcceptance(uint16_t inAcceptedAcknowledgementsValue, + uint16_t inAcceptedAcknowledgementsVersionValue) +{ + uint8_t buffer[kEstimatedTlvBufferSize] = { 0 }; + chip::TLV::TLVWriter tlvWriter; + chip::TLV::TLVType tlvContainer; + + VerifyOrReturnError(nullptr != mPersistentStorageDelegate, CHIP_ERROR_UNINITIALIZED); + + tlvWriter.Init(buffer, sizeof(buffer)); + ReturnErrorOnFailure(tlvWriter.StartContainer(chip::TLV::AnonymousTag(), chip::TLV::kTLVType_Structure, tlvContainer)); + ReturnErrorOnFailure(tlvWriter.Put(kSerializationVersionTag, kSerializationVersion)); + ReturnErrorOnFailure(tlvWriter.Put(kAcceptedAcknowledgementsTag, inAcceptedAcknowledgementsValue)); + ReturnErrorOnFailure(tlvWriter.Put(kAcceptedAcknowledgementsVersionTag, inAcceptedAcknowledgementsVersionValue)); + ReturnErrorOnFailure(tlvWriter.EndContainer(tlvContainer)); + ReturnErrorOnFailure(tlvWriter.Finalize()); + uint32_t lengthWritten = tlvWriter.GetLengthWritten(); + VerifyOrReturnError(CanCastTo(lengthWritten), CHIP_ERROR_BUFFER_TOO_SMALL); + + const chip::StorageKeyName storageKey = DefaultStorageKeyAllocator::TermsAndConditionsAcceptance(); + ReturnErrorOnFailure( + mPersistentStorageDelegate->SyncSetKeyValue(storageKey.KeyName(), buffer, static_cast(lengthWritten))); + + return CHIP_NO_ERROR; +} diff --git a/src/app/server/DefaultTermsAndConditionsProvider.h b/src/app/server/DefaultTermsAndConditionsProvider.h new file mode 100644 index 00000000000000..4eec8a67ac04cf --- /dev/null +++ b/src/app/server/DefaultTermsAndConditionsProvider.h @@ -0,0 +1,58 @@ +/* + * + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * 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 "TermsAndConditionsProvider.h" + +#include + +#include +#include + +namespace chip { +namespace app { +class DefaultTermsAndConditionsProvider : public TermsAndConditionsProvider +{ +public: + /** + * @brief Initializes the TermsAndConditionsProvider. + * + * @param[in] inPersistentStorageDelegate Persistent storage delegate dependency. + * @param[in] inRequiredAcknowledgementsValue The bitmask of required acknowledgements. + * @param[in] inRequiredAcknowledgementsVersionValue The version of the required acknowledgements. + */ + CHIP_ERROR Init(PersistentStorageDelegate * const inPersistentStorageDelegate, uint16_t inRequiredAcknowledgementsValue, + uint16_t inRequiredAcknowledgementsVersionValue); + + CHIP_ERROR ClearAcceptance() override; + + CHIP_ERROR GetAcceptance(uint16_t & outAcknowledgementsValue, uint16_t & outAcknowledgementsVersionValue) const override; + + CHIP_ERROR GetRequirements(uint16_t & outAcknowledgementsValue, uint16_t & outAcknowledgementsVersionValue) const override; + + CHIP_ERROR SetAcceptance(uint16_t inAcknowledgementsValue, uint16_t inAcknowledgementsVersionValue) override; + +private: + PersistentStorageDelegate * mPersistentStorageDelegate; + uint16_t mRequiredAcknowledgementsValue; + uint16_t mRequiredAcknowledgementsVersionValue; +}; + +} // namespace app +} // namespace chip diff --git a/src/app/server/EnhancedSetupFlowProvider.h b/src/app/server/EnhancedSetupFlowProvider.h new file mode 100644 index 00000000000000..6a0846f119f513 --- /dev/null +++ b/src/app/server/EnhancedSetupFlowProvider.h @@ -0,0 +1,87 @@ +/* + * + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * 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 + +#include + +namespace chip { +namespace app { + +/** + * This class provides access to the state of the Enhanced Setup Flow feature. + */ +class EnhancedSetupFlowProvider +{ +public: + virtual ~EnhancedSetupFlowProvider() = default; + + /** + * @param[out] outAccepted true if the required acknowledgements have been accepted, false otherwise. + */ + virtual CHIP_ERROR HasTermsAndConditionsRequiredAcknowledgementsBeenAccepted(bool & outAccepted) const = 0; + + /** + * @param[out] outAccepted true if the required acknowledgements version has been accepted, false otherwise. + */ + virtual CHIP_ERROR HasTermsAndConditionsRequiredAcknowledgementsVersionBeenAccepted(bool & outAccepted) const = 0; + + /** + * @param[out] outValue true if terms and conditions acceptance is required before commissioning complete may succeed, false + * otherwise. + */ + virtual CHIP_ERROR IsTermsAndConditionsAcceptanceRequired(bool & outValue) const = 0; + + /** + * @param[out] outValue The version of the required acknowledgements. + */ + virtual CHIP_ERROR GetTermsAndConditionsRequiredAcknowledgements(uint16_t & outValue) const = 0; + + /** + * @param[out] outValue The outValue of the required acknowledgements version. + */ + virtual CHIP_ERROR GetTermsAndConditionsRequiredAcknowledgementsVersion(uint16_t & outValue) const = 0; + + /** + * @param[out] outValue The outValue of the accepted acknowledgements. + */ + virtual CHIP_ERROR GetTermsAndConditionsAcceptedAcknowledgements(uint16_t & outValue) const = 0; + + /** + * @param[out] outValue The outValue of the accepted acknowledgements version. + */ + virtual CHIP_ERROR GetTermsAndConditionsAcceptedAcknowledgementsVersion(uint16_t & outValue) const = 0; + + /** + * @param[in] inTCAcknowledgements The acknowledgements to accept. + * @param[in] inTCAcknowledgementsVersionValue The version of the acknowledgements to accept. + */ + virtual CHIP_ERROR SetTermsAndConditionsAcceptance(uint16_t inTCAcknowledgementsValue, + uint16_t inTCAcknowledgementsVersionValue) = 0; + + /** + * Reset the terms and conditions acceptance. The terms and conditions should be cleared on factory reset or if failure occurs + * during a failsafe context. + */ + virtual CHIP_ERROR ClearTermsAndConditionsAcceptance() = 0; +}; + +} // namespace app +} // namespace chip diff --git a/src/app/server/Server.cpp b/src/app/server/Server.cpp index 22cd274ba87e39..25d03d1645b914 100644 --- a/src/app/server/Server.cpp +++ b/src/app/server/Server.cpp @@ -1,6 +1,6 @@ /* * - * Copyright (c) 2021 Project CHIP Authors + * Copyright (c) 2021-2024 Project CHIP Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -185,6 +185,11 @@ CHIP_ERROR Server::Init(const ServerInitParams & initParams) mReportScheduler = initParams.reportScheduler; +#if CHIP_CONFIG_TC_REQUIRED + mTermsAndConditionsProvider = initParams.termsAndConditionsProvider; + mEnhancedSetupFlowProvider = initParams.enhancedSetupFlowProvider; +#endif + mTestEventTriggerDelegate = initParams.testEventTriggerDelegate; if (mTestEventTriggerDelegate == nullptr) { @@ -586,6 +591,9 @@ void Server::ScheduleFactoryReset() GetInstance().GetFabricTable().DeleteAllFabrics(); PlatformMgr().HandleServerShuttingDown(); ConfigurationMgr().InitiateFactoryReset(); +#if CHIP_CONFIG_TC_REQUIRED + // Clear accepted terms and conditions +#endif }); } diff --git a/src/app/server/Server.h b/src/app/server/Server.h index 2f6126a4ace635..cb8ab12f40f547 100644 --- a/src/app/server/Server.h +++ b/src/app/server/Server.h @@ -1,6 +1,6 @@ /* * - * Copyright (c) 2020 Project CHIP Authors + * Copyright (c) 2020-2024 Project CHIP Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -33,6 +33,12 @@ #include #include #include +#if CHIP_CONFIG_TC_REQUIRED +#include +#include +#include +#include +#endif #include #include #include @@ -179,6 +185,12 @@ struct ServerInitParams // Optional. Support for the ICD Check-In BackOff strategy. Must be initialized before being provided. // If the ICD Check-In protocol use-case is supported and no strategy is provided, server will use the default strategy. app::ICDCheckInBackOffStrategy * icdCheckInBackOffStrategy = nullptr; +#if CHIP_CONFIG_TC_REQUIRED + // Optional. Enhanced setup flow provider to support terms and conditions acceptance check. + app::EnhancedSetupFlowProvider * enhancedSetupFlowProvider = nullptr; + // Optional. Terms and conditions provider to support enhanced setup flow feature. + app::TermsAndConditionsProvider * termsAndConditionsProvider = nullptr; +#endif }; /** @@ -300,6 +312,24 @@ struct CommonCaseDeviceServerInitParams : public ServerInitParams } #endif +#if CHIP_CONFIG_TC_REQUIRED + static app::DefaultEnhancedSetupFlowProvider sDefaultEnhancedSetupFlowProviderInstance; + static app::DefaultTermsAndConditionsProvider sDefaultTermsAndConditionsProviderInstance; + if (this->termsAndConditionsProvider == nullptr) + { + ReturnErrorOnFailure(sDefaultTermsAndConditionsProviderInstance.Init(this->persistentStorageDelegate, + CHIP_CONFIG_TC_REQUIRED_ACKNOWLEDGEMENTS, + CHIP_CONFIG_TC_REQUIRED_ACKNOWLEDGEMENTS_VERSION)); + this->termsAndConditionsProvider = &sDefaultTermsAndConditionsProviderInstance; + } + + if (this->enhancedSetupFlowProvider == nullptr) + { + ReturnErrorOnFailure(sDefaultEnhancedSetupFlowProviderInstance.Init(this->termsAndConditionsProvider)); + this->enhancedSetupFlowProvider = &sDefaultEnhancedSetupFlowProviderInstance; + } +#endif + return CHIP_NO_ERROR; } @@ -402,6 +432,10 @@ class Server app::reporting::ReportScheduler * GetReportScheduler() { return mReportScheduler; } +#if CHIP_CONFIG_TC_REQUIRED + app::EnhancedSetupFlowProvider * GetEnhancedSetupFlowProvider() { return mEnhancedSetupFlowProvider; } +#endif + #if CHIP_CONFIG_ENABLE_ICD_SERVER app::ICDManager & GetICDManager() { return mICDManager; } @@ -675,6 +709,10 @@ class Server GroupDataProviderListener mListener; ServerFabricDelegate mFabricDelegate; app::reporting::ReportScheduler * mReportScheduler; +#if CHIP_CONFIG_TC_REQUIRED + app::EnhancedSetupFlowProvider * mEnhancedSetupFlowProvider; + app::TermsAndConditionsProvider * mTermsAndConditionsProvider; +#endif Access::AccessControl mAccessControl; app::AclStorage * mAclStorage; diff --git a/src/app/server/TermsAndConditionsProvider.h b/src/app/server/TermsAndConditionsProvider.h new file mode 100644 index 00000000000000..201b3b983d466d --- /dev/null +++ b/src/app/server/TermsAndConditionsProvider.h @@ -0,0 +1,68 @@ +/* + * + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * 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 + +#include +#include + +namespace chip { +namespace app { + +/** + * @brief Data access layer for the required terms and conditions and the store for the user acceptance. + */ +class TermsAndConditionsProvider +{ +public: + virtual ~TermsAndConditionsProvider() = default; + + /** + * @brief Sets the acceptance status of the required terms and conditions. + */ + virtual CHIP_ERROR ClearAcceptance() = 0; + + /** + * @brief Retrieves the acceptance status of the required terms and conditions. + * + * @param[out] outAcknowledgementsValue The bitmask of acknowledgements accepted. + * @param[out] outAcknowledgementsVersionValue The version of the accepted acknowledgements. + */ + virtual CHIP_ERROR GetAcceptance(uint16_t & outAcknowledgementsValue, uint16_t & outAcknowledgementsVersionValue) const = 0; + + /** + * @brief Retrieves the requirements of the terms and conditions. + * + * @param[out] outAcknowledgementsValue The bitmask of required acknowledgements. + * @param[out] outAcknowledgementsVersionValue The version of the required acknowledgements. + */ + virtual CHIP_ERROR GetRequirements(uint16_t & outAcknowledgementsValue, uint16_t & outAcknowledgementsVersionValue) const = 0; + + /** + * @brief Sets the acceptance status of the required terms and conditions. + * + * @param[in] inAcknowledgementsValue The bitmask of acknowledgements that was accepted. + * @param[in] inAcknowledgementsVersionValue The version of the acknowledgements that was accepted. + */ + virtual CHIP_ERROR SetAcceptance(uint16_t inAcknowledgementsValue, uint16_t inAcknowledgementsVersionValue) = 0; +}; + +} // namespace app +} // namespace chip diff --git a/src/app/tests/BUILD.gn b/src/app/tests/BUILD.gn index 1bce08d55e0571..9da370d705d940 100644 --- a/src/app/tests/BUILD.gn +++ b/src/app/tests/BUILD.gn @@ -1,4 +1,4 @@ -# Copyright (c) 2020 Project CHIP Authors +# Copyright (c) 2020-2024 Project CHIP Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -198,7 +198,9 @@ chip_test_suite("tests") { "TestCommandPathParams.cpp", "TestConcreteAttributePath.cpp", "TestDataModelSerialization.cpp", + "TestDefaultEnhancedSetupFlowProvider.cpp", "TestDefaultOTARequestorStorage.cpp", + "TestDefaultTermsAndConditionsProvider.cpp", "TestDefaultThreadNetworkDirectoryStorage.cpp", "TestEventLoggingNoUTCTime.cpp", "TestEventOverflow.cpp", @@ -236,6 +238,8 @@ chip_test_suite("tests") { "${chip_root}/src/app/codegen-data-model-provider:instance-header", "${chip_root}/src/app/common:cluster-objects", "${chip_root}/src/app/icd/client:manager", + "${chip_root}/src/app/server:enhanced_setup_flow", + "${chip_root}/src/app/server:server", "${chip_root}/src/app/tests:helpers", "${chip_root}/src/app/util/mock:mock_codegen_data_model", "${chip_root}/src/app/util/mock:mock_ember", diff --git a/src/app/tests/TestDefaultEnhancedSetupFlowProvider.cpp b/src/app/tests/TestDefaultEnhancedSetupFlowProvider.cpp new file mode 100644 index 00000000000000..d29a18824e23f6 --- /dev/null +++ b/src/app/tests/TestDefaultEnhancedSetupFlowProvider.cpp @@ -0,0 +1,306 @@ +/* + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * 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. + */ + +#include "app/server/DefaultEnhancedSetupFlowProvider.h" + +#include +#include +#include + +class FakeTermsAndConditionsProvider : public chip::app::TermsAndConditionsProvider +{ +public: + FakeTermsAndConditionsProvider(uint16_t inAcceptedAcknowledgements, uint16_t inAcceptedAcknowledgementsVersion, + uint16_t inRequiredAcknowledgements, uint16_t inRequiredAcknowledgementsVersion) : + mAcceptedAcknowledgements(inAcceptedAcknowledgements), + mAcceptedAcknowledgementsVersion(inAcceptedAcknowledgementsVersion), mRequiredAcknowledgements(inRequiredAcknowledgements), + mRequiredAcknowledgementsVersion(inRequiredAcknowledgementsVersion) + {} + + CHIP_ERROR GetAcceptance(uint16_t & outAcknowledgements, uint16_t & outAcknowledgementsVersion) const override + { + outAcknowledgements = mAcceptedAcknowledgements; + outAcknowledgementsVersion = mAcceptedAcknowledgementsVersion; + return CHIP_NO_ERROR; + } + + CHIP_ERROR GetRequirements(uint16_t & outAcknowledgements, uint16_t & outAcknowledgementsVersion) const override + { + outAcknowledgements = mRequiredAcknowledgements; + outAcknowledgementsVersion = mRequiredAcknowledgementsVersion; + return CHIP_NO_ERROR; + } + + CHIP_ERROR SetAcceptance(uint16_t inAcknowledgements, uint16_t inAcknowledgementsVersion) override + { + mAcceptedAcknowledgements = inAcknowledgements; + mAcceptedAcknowledgementsVersion = inAcknowledgementsVersion; + return CHIP_NO_ERROR; + } + + CHIP_ERROR ClearAcceptance() override + { + mAcceptedAcknowledgements = 0; + mAcceptedAcknowledgementsVersion = 0; + return CHIP_NO_ERROR; + } + +private: + uint16_t mAcceptedAcknowledgements; + uint16_t mAcceptedAcknowledgementsVersion; + uint16_t mRequiredAcknowledgements; + uint16_t mRequiredAcknowledgementsVersion; +}; + +TEST(DefaultEnhancedSetupFlowProvider, TestNoAcceptanceRequiredCheckAcknowledgementsAcceptedSuccess) +{ + CHIP_ERROR err; + bool hasTermsBeenAccepted; + + FakeTermsAndConditionsProvider tncProvider(0, 0, 0, 0); + chip::app::DefaultEnhancedSetupFlowProvider esfProvider; + + err = esfProvider.Init(&tncProvider); + EXPECT_EQ(CHIP_NO_ERROR, err); + + err = esfProvider.HasTermsAndConditionsRequiredAcknowledgementsBeenAccepted(hasTermsBeenAccepted); + EXPECT_EQ(CHIP_NO_ERROR, err); + EXPECT_TRUE(hasTermsBeenAccepted); +} + +TEST(DefaultEnhancedSetupFlowProvider, TestNoAcceptanceRequiredCheckAcknowledgementsVersionAcceptedSuccess) +{ + CHIP_ERROR err; + bool hasTermsVersionBeenAccepted; + + FakeTermsAndConditionsProvider tncProvider(0, 0, 0, 0); + chip::app::DefaultEnhancedSetupFlowProvider esfProvider; + + err = esfProvider.Init(&tncProvider); + EXPECT_EQ(CHIP_NO_ERROR, err); + + err = esfProvider.HasTermsAndConditionsRequiredAcknowledgementsVersionBeenAccepted(hasTermsVersionBeenAccepted); + EXPECT_EQ(CHIP_NO_ERROR, err); + EXPECT_TRUE(hasTermsVersionBeenAccepted); +} + +TEST(DefaultEnhancedSetupFlowProvider, TestAcceptanceRequiredNoTermsAcceptedCheckAcknowledgementsAcceptedFailure) +{ + CHIP_ERROR err; + bool hasTermsBeenAccepted; + + FakeTermsAndConditionsProvider tncProvider(0, 0, 1, 1); + chip::app::DefaultEnhancedSetupFlowProvider esfProvider; + + err = esfProvider.Init(&tncProvider); + EXPECT_EQ(CHIP_NO_ERROR, err); + + err = esfProvider.HasTermsAndConditionsRequiredAcknowledgementsBeenAccepted(hasTermsBeenAccepted); + EXPECT_EQ(CHIP_NO_ERROR, err); + EXPECT_FALSE(hasTermsBeenAccepted); +} + +TEST(DefaultEnhancedSetupFlowProvider, + TestAcceptanceRequiredTermsAcceptedTermsVersionOutdatedCheckAcknowledgementsVersionAcceptedFailure) +{ + CHIP_ERROR err; + bool hasTermsBeenAccepted; + bool hasTermsVersionBeenAccepted; + + FakeTermsAndConditionsProvider tncProvider(0, 0, 1, 1); + chip::app::DefaultEnhancedSetupFlowProvider esfProvider; + + err = esfProvider.Init(&tncProvider); + EXPECT_EQ(CHIP_NO_ERROR, err); + + err = esfProvider.SetTermsAndConditionsAcceptance(1, 0); + EXPECT_EQ(CHIP_NO_ERROR, err); + + err = esfProvider.HasTermsAndConditionsRequiredAcknowledgementsBeenAccepted(hasTermsBeenAccepted); + EXPECT_EQ(CHIP_NO_ERROR, err); + EXPECT_TRUE(hasTermsBeenAccepted); + + err = esfProvider.HasTermsAndConditionsRequiredAcknowledgementsVersionBeenAccepted(hasTermsVersionBeenAccepted); + EXPECT_EQ(CHIP_NO_ERROR, err); + EXPECT_FALSE(hasTermsVersionBeenAccepted); +} + +TEST(DefaultEnhancedSetupFlowProvider, TestAcceptanceRequiredTermsAcceptedFutureVersionCheckAcknowledgementsAcceptedSuccess) +{ + CHIP_ERROR err; + bool hasTermsBeenAccepted; + bool hasTermsVersionBeenAccepted; + + uint16_t acceptedTerms = 1; + uint16_t requiredTerms = 1; + uint16_t acceptedTermsVersion = 2; + uint16_t requiredTermsVersion = 1; + + FakeTermsAndConditionsProvider tncProvider(acceptedTerms, acceptedTermsVersion, requiredTerms, requiredTermsVersion); + chip::app::DefaultEnhancedSetupFlowProvider esfProvider; + + err = esfProvider.Init(&tncProvider); + EXPECT_EQ(CHIP_NO_ERROR, err); + + err = esfProvider.HasTermsAndConditionsRequiredAcknowledgementsBeenAccepted(hasTermsBeenAccepted); + EXPECT_EQ(CHIP_NO_ERROR, err); + EXPECT_TRUE(hasTermsBeenAccepted); + + err = esfProvider.HasTermsAndConditionsRequiredAcknowledgementsVersionBeenAccepted(hasTermsVersionBeenAccepted); + EXPECT_EQ(CHIP_NO_ERROR, err); + EXPECT_TRUE(hasTermsVersionBeenAccepted); +} + +TEST(DefaultEnhancedSetupFlowProvider, TestAcceptanceRequiredTermsAcceptedSuccess) +{ + CHIP_ERROR err; + bool hasTermsBeenAccepted; + bool hasTermsVersionBeenAccepted; + + FakeTermsAndConditionsProvider tncProvider(0, 0, 1, 1); + chip::app::DefaultEnhancedSetupFlowProvider esfProvider; + + err = esfProvider.Init(&tncProvider); + EXPECT_EQ(CHIP_NO_ERROR, err); + + err = esfProvider.SetTermsAndConditionsAcceptance(1, 1); + EXPECT_EQ(CHIP_NO_ERROR, err); + + err = esfProvider.HasTermsAndConditionsRequiredAcknowledgementsBeenAccepted(hasTermsBeenAccepted); + EXPECT_EQ(CHIP_NO_ERROR, err); + EXPECT_TRUE(hasTermsBeenAccepted); + + err = esfProvider.HasTermsAndConditionsRequiredAcknowledgementsVersionBeenAccepted(hasTermsVersionBeenAccepted); + EXPECT_EQ(CHIP_NO_ERROR, err); + EXPECT_TRUE(hasTermsVersionBeenAccepted); +} + +TEST(DefaultEnhancedSetupFlowProvider, TestAcceptanceRequiredTermsMissingFailure) +{ + CHIP_ERROR err; + bool hasTermsBeenAccepted; + bool hasTermsVersionBeenAccepted; + + uint16_t acceptedTerms = 0b0111'1111'1111'1111; + uint16_t requiredTerms = 0b1111'1111'1111'1111; + uint16_t acceptedTermsVersion = 1; + uint16_t requiredTermsVersion = 1; + + FakeTermsAndConditionsProvider tncProvider(acceptedTerms, acceptedTermsVersion, requiredTerms, requiredTermsVersion); + chip::app::DefaultEnhancedSetupFlowProvider esfProvider; + + err = esfProvider.Init(&tncProvider); + EXPECT_EQ(CHIP_NO_ERROR, err); + + err = esfProvider.HasTermsAndConditionsRequiredAcknowledgementsBeenAccepted(hasTermsBeenAccepted); + EXPECT_EQ(CHIP_NO_ERROR, err); + EXPECT_FALSE(hasTermsBeenAccepted); + + err = esfProvider.HasTermsAndConditionsRequiredAcknowledgementsVersionBeenAccepted(hasTermsVersionBeenAccepted); + EXPECT_EQ(CHIP_NO_ERROR, err); + EXPECT_TRUE(hasTermsVersionBeenAccepted); +} + +TEST(DefaultEnhancedSetupFlowProvider, TestAcceptanceRequiredAllTermsAcceptedCheckAcknowledgementsAcceptedSuccess) +{ + CHIP_ERROR err; + bool hasTermsBeenAccepted; + bool hasTermsVersionBeenAccepted; + + uint16_t acceptedTerms = 0b1111'1111'1111'1111; + uint16_t requiredTerms = 0b1111'1111'1111'1111; + uint16_t acceptedTermsVersion = 1; + uint16_t requiredTermsVersion = 1; + + FakeTermsAndConditionsProvider tncProvider(acceptedTerms, acceptedTermsVersion, requiredTerms, requiredTermsVersion); + chip::app::DefaultEnhancedSetupFlowProvider esfProvider; + + err = esfProvider.Init(&tncProvider); + EXPECT_EQ(CHIP_NO_ERROR, err); + + err = esfProvider.HasTermsAndConditionsRequiredAcknowledgementsBeenAccepted(hasTermsBeenAccepted); + EXPECT_EQ(CHIP_NO_ERROR, err); + EXPECT_TRUE(hasTermsBeenAccepted); + + err = esfProvider.HasTermsAndConditionsRequiredAcknowledgementsVersionBeenAccepted(hasTermsVersionBeenAccepted); + EXPECT_EQ(CHIP_NO_ERROR, err); + EXPECT_TRUE(hasTermsVersionBeenAccepted); +} + +TEST(DefaultEnhancedSetupFlowProvider, TestClearAcceptanceRetainsRequirements) +{ + CHIP_ERROR err; + + uint16_t initialAcceptedTermsAndConditions = 0; + uint16_t initialRequiredTermsAndConditions = 0b1111'1111'1111'1111; + uint16_t initialAcceptedTermsAndConditionsVersion = 0; + uint16_t initialRequiredTermsAndConditionsVersion = 1; + + uint16_t outAcceptedTermsAndConditions; + uint16_t outRequiredTermsAndConditions; + uint16_t outAcceptedTermsAndConditionsVersion; + uint16_t outRequiredTermsAndConditionsVersion; + + uint16_t updatedAcceptedTermsAndConditions = 0b1111'1111'1111'1111; + uint16_t updatedAcceptedTermsAndConditionsVersion = 1; + + FakeTermsAndConditionsProvider tncProvider(initialAcceptedTermsAndConditions, initialAcceptedTermsAndConditionsVersion, + initialRequiredTermsAndConditions, initialRequiredTermsAndConditionsVersion); + + chip::app::DefaultEnhancedSetupFlowProvider esfProvider; + + err = esfProvider.Init(&tncProvider); + EXPECT_EQ(CHIP_NO_ERROR, err); + + err = esfProvider.SetTermsAndConditionsAcceptance(updatedAcceptedTermsAndConditions, updatedAcceptedTermsAndConditionsVersion); + EXPECT_EQ(CHIP_NO_ERROR, err); + + err = esfProvider.GetTermsAndConditionsRequiredAcknowledgements(outRequiredTermsAndConditions); + EXPECT_EQ(CHIP_NO_ERROR, err); + EXPECT_EQ(outRequiredTermsAndConditions, initialRequiredTermsAndConditions); + + err = esfProvider.GetTermsAndConditionsRequiredAcknowledgementsVersion(outRequiredTermsAndConditionsVersion); + EXPECT_EQ(CHIP_NO_ERROR, err); + EXPECT_EQ(outRequiredTermsAndConditionsVersion, initialRequiredTermsAndConditionsVersion); + + err = esfProvider.GetTermsAndConditionsAcceptedAcknowledgements(outAcceptedTermsAndConditions); + EXPECT_EQ(CHIP_NO_ERROR, err); + EXPECT_EQ(outAcceptedTermsAndConditions, updatedAcceptedTermsAndConditions); + + err = esfProvider.GetTermsAndConditionsAcceptedAcknowledgementsVersion(outAcceptedTermsAndConditionsVersion); + EXPECT_EQ(CHIP_NO_ERROR, err); + EXPECT_EQ(outAcceptedTermsAndConditionsVersion, updatedAcceptedTermsAndConditionsVersion); + + err = esfProvider.ClearTermsAndConditionsAcceptance(); + EXPECT_EQ(CHIP_NO_ERROR, err); + + err = esfProvider.GetTermsAndConditionsRequiredAcknowledgements(outRequiredTermsAndConditions); + EXPECT_EQ(CHIP_NO_ERROR, err); + EXPECT_EQ(outRequiredTermsAndConditions, initialRequiredTermsAndConditions); + + err = esfProvider.GetTermsAndConditionsRequiredAcknowledgementsVersion(outRequiredTermsAndConditionsVersion); + EXPECT_EQ(CHIP_NO_ERROR, err); + EXPECT_EQ(outRequiredTermsAndConditionsVersion, initialRequiredTermsAndConditionsVersion); + + err = esfProvider.GetTermsAndConditionsAcceptedAcknowledgements(outAcceptedTermsAndConditions); + EXPECT_EQ(CHIP_NO_ERROR, err); + EXPECT_EQ(outAcceptedTermsAndConditions, 0); + + err = esfProvider.GetTermsAndConditionsAcceptedAcknowledgementsVersion(outAcceptedTermsAndConditionsVersion); + EXPECT_EQ(CHIP_NO_ERROR, err); + EXPECT_EQ(outAcceptedTermsAndConditionsVersion, 0); +} diff --git a/src/app/tests/TestDefaultTermsAndConditionsProvider.cpp b/src/app/tests/TestDefaultTermsAndConditionsProvider.cpp new file mode 100644 index 00000000000000..be09c703a64f10 --- /dev/null +++ b/src/app/tests/TestDefaultTermsAndConditionsProvider.cpp @@ -0,0 +1,226 @@ +/* + * + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * 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. + */ + +#include "app/server/DefaultTermsAndConditionsProvider.h" + +#include +#include +#include +#include + +TEST(DefaultTermsAndConditionsProvider, TestInitSuccess) +{ + CHIP_ERROR err; + + chip::TestPersistentStorageDelegate storageDelegate; + chip::app::DefaultTermsAndConditionsProvider tncProvider; + + uint16_t requiredAcknowledgements = 1; + uint16_t requiredAcknowledgementsVersion = 1; + err = tncProvider.Init(&storageDelegate, requiredAcknowledgements, requiredAcknowledgementsVersion); + EXPECT_EQ(CHIP_NO_ERROR, err); +} + +TEST(DefaultTermsAndConditionsProvider, TestNoRequirementsGetRequirementsSuccess) +{ + CHIP_ERROR err; + + chip::TestPersistentStorageDelegate storageDelegate; + chip::app::DefaultTermsAndConditionsProvider tncProvider; + + uint16_t requiredAcknowledgements = 0; + uint16_t requiredAcknowledgementsVersion = 0; + err = tncProvider.Init(&storageDelegate, requiredAcknowledgements, requiredAcknowledgementsVersion); + EXPECT_EQ(CHIP_NO_ERROR, err); + + uint16_t outAcceptance; + uint16_t outAcknowledgementsVersion; + err = tncProvider.GetAcceptance(outAcceptance, outAcknowledgementsVersion); + EXPECT_EQ(CHIP_NO_ERROR, err); + EXPECT_EQ(0, outAcceptance); + EXPECT_EQ(0, outAcknowledgementsVersion); +} + +TEST(DefaultTermsAndConditionsProvider, TestNeverAcceptanceGetAcceptanceSuccess) +{ + CHIP_ERROR err; + + chip::TestPersistentStorageDelegate storageDelegate; + chip::app::DefaultTermsAndConditionsProvider tncProvider; + + uint16_t requiredAcknowledgements = 0b1111'1111'1111'1111; + uint16_t requiredAcknowledgementsVersion = 1; + err = tncProvider.Init(&storageDelegate, requiredAcknowledgements, requiredAcknowledgementsVersion); + EXPECT_EQ(CHIP_NO_ERROR, err); + + uint16_t outAcceptance; + uint16_t outAcknowledgementsVersion; + err = tncProvider.GetAcceptance(outAcceptance, outAcknowledgementsVersion); + EXPECT_EQ(CHIP_NO_ERROR, err); + EXPECT_EQ(0, outAcceptance); + EXPECT_EQ(0, outAcknowledgementsVersion); +} + +TEST(DefaultTermsAndConditionsProvider, TestTermsAcceptedPersistsSuccess) +{ + CHIP_ERROR err; + + chip::TestPersistentStorageDelegate storageDelegate; + chip::app::DefaultTermsAndConditionsProvider tncProvider; + chip::app::DefaultTermsAndConditionsProvider anotherTncProvider; + + uint16_t requiredAcknowledgements = 1; + uint16_t requiredAcknowledgementsVersion = 1; + err = tncProvider.Init(&storageDelegate, requiredAcknowledgements, requiredAcknowledgementsVersion); + EXPECT_EQ(CHIP_NO_ERROR, err); + + uint16_t acceptedTermsAndConditions = 1; + uint16_t acceptedTermsAndConditionsVersion = 1; + err = tncProvider.SetAcceptance(acceptedTermsAndConditions, acceptedTermsAndConditionsVersion); + EXPECT_EQ(CHIP_NO_ERROR, err); + + uint16_t outAcceptance; + uint16_t outAcknowledgementsVersion; + err = tncProvider.GetAcceptance(outAcceptance, outAcknowledgementsVersion); + EXPECT_EQ(CHIP_NO_ERROR, err); + EXPECT_EQ(1, outAcceptance); + EXPECT_EQ(1, outAcknowledgementsVersion); + + err = anotherTncProvider.Init(&storageDelegate, requiredAcknowledgements, requiredAcknowledgementsVersion); + EXPECT_EQ(CHIP_NO_ERROR, err); + + err = anotherTncProvider.GetAcceptance(outAcceptance, outAcknowledgementsVersion); + EXPECT_EQ(CHIP_NO_ERROR, err); + EXPECT_EQ(1, outAcceptance); + EXPECT_EQ(1, outAcknowledgementsVersion); +} + +TEST(DefaultTermsAndConditionsProvider, TestTermsRequiredGetRequirementsSuccess) +{ + CHIP_ERROR err; + + chip::TestPersistentStorageDelegate storageDelegate; + chip::app::DefaultTermsAndConditionsProvider tncProvider; + + uint16_t initialRequiredAcknowledgements = 1; + uint16_t initialRequiredAcknowledgementsVersion = 1; + err = tncProvider.Init(&storageDelegate, initialRequiredAcknowledgements, initialRequiredAcknowledgementsVersion); + EXPECT_EQ(CHIP_NO_ERROR, err); + + uint16_t outRequiredAcknowledgements; + uint16_t outRequiredAcknowledgementsVersion; + err = tncProvider.GetRequirements(outRequiredAcknowledgements, outRequiredAcknowledgementsVersion); + EXPECT_EQ(CHIP_NO_ERROR, err); + EXPECT_EQ(1, outRequiredAcknowledgements); + EXPECT_EQ(1, outRequiredAcknowledgementsVersion); +} + +TEST(DefaultTermsAndConditionsProvider, TestSetAcceptanceGetAcceptanceSuccess) +{ + CHIP_ERROR err; + + chip::TestPersistentStorageDelegate storageDelegate; + chip::app::DefaultTermsAndConditionsProvider tncProvider; + + uint16_t requiredAcknowledgements = 1; + uint16_t requiredAcknowledgementsVersion = 1; + err = tncProvider.Init(&storageDelegate, requiredAcknowledgements, requiredAcknowledgementsVersion); + EXPECT_EQ(CHIP_NO_ERROR, err); + + uint16_t acceptedTermsAndConditions = 1; + uint16_t acceptedTermsAndConditionsVersion = 1; + err = tncProvider.SetAcceptance(acceptedTermsAndConditions, acceptedTermsAndConditionsVersion); + EXPECT_EQ(CHIP_NO_ERROR, err); + + uint16_t outAcceptance; + uint16_t outAcknowledgementsVersion; + err = tncProvider.GetAcceptance(outAcceptance, outAcknowledgementsVersion); + EXPECT_EQ(CHIP_NO_ERROR, err); + EXPECT_EQ(1, outAcceptance); + EXPECT_EQ(1, outAcknowledgementsVersion); +} + +TEST(DefaultTermsAndConditionsProvider, TestClearAcceptanceGetAcceptanceSuccess) +{ + CHIP_ERROR err; + + chip::TestPersistentStorageDelegate storageDelegate; + chip::app::DefaultTermsAndConditionsProvider tncProvider; + + uint16_t requiredAcknowledgements = 1; + uint16_t requiredAcknowledgementsVersion = 1; + err = tncProvider.Init(&storageDelegate, requiredAcknowledgements, requiredAcknowledgementsVersion); + EXPECT_EQ(CHIP_NO_ERROR, err); + + uint16_t acceptedTermsAndConditions = 1; + uint16_t acceptedTermsAndConditionsVersion = 1; + err = tncProvider.SetAcceptance(acceptedTermsAndConditions, acceptedTermsAndConditionsVersion); + EXPECT_EQ(CHIP_NO_ERROR, err); + + uint16_t outAcceptance; + uint16_t outAcknowledgementsVersion; + err = tncProvider.GetAcceptance(outAcceptance, outAcknowledgementsVersion); + EXPECT_EQ(CHIP_NO_ERROR, err); + EXPECT_EQ(1, outAcceptance); + EXPECT_EQ(1, outAcknowledgementsVersion); + + err = tncProvider.ClearAcceptance(); + EXPECT_EQ(CHIP_NO_ERROR, err); + + uint16_t outAcceptance2; + uint16_t outAcknowledgementsVersion2; + err = tncProvider.GetAcceptance(outAcceptance2, outAcknowledgementsVersion2); + EXPECT_EQ(CHIP_NO_ERROR, err); + EXPECT_EQ(0, outAcceptance2); + EXPECT_EQ(0, outAcknowledgementsVersion2); +} + +TEST(DefaultTermsAndConditionsProvider, TestAcceptanceRequiredTermsMissingFailure) +{ + CHIP_ERROR err; + + chip::TestPersistentStorageDelegate storageDelegate; + chip::app::DefaultTermsAndConditionsProvider tncProvider; + + uint16_t requiredAcknowledgements = 1; + uint16_t requiredAcknowledgementsVersion = 1; + err = tncProvider.Init(&storageDelegate, requiredAcknowledgements, requiredAcknowledgementsVersion); + EXPECT_EQ(CHIP_NO_ERROR, err); + + uint16_t acceptedTermsAndConditions = 1; + uint16_t acceptedTermsAndConditionsVersion = 1; + err = tncProvider.SetAcceptance(acceptedTermsAndConditions, acceptedTermsAndConditionsVersion); + EXPECT_EQ(CHIP_NO_ERROR, err); + + uint16_t outAcceptance; + uint16_t outAcknowledgementsVersion; + err = tncProvider.GetAcceptance(outAcceptance, outAcknowledgementsVersion); + EXPECT_EQ(CHIP_NO_ERROR, err); + EXPECT_EQ(1, outAcceptance); + EXPECT_EQ(1, outAcknowledgementsVersion); + + err = tncProvider.ClearAcceptance(); + EXPECT_EQ(CHIP_NO_ERROR, err); + + uint16_t outRequiredAcknowledgements; + uint16_t outRequiredAcknowledgementsVersion; + err = tncProvider.GetRequirements(outRequiredAcknowledgements, outRequiredAcknowledgementsVersion); + EXPECT_EQ(CHIP_NO_ERROR, err); + EXPECT_EQ(1, outRequiredAcknowledgements); + EXPECT_EQ(1, outRequiredAcknowledgementsVersion); +} diff --git a/src/lib/core/CHIPConfig.h b/src/lib/core/CHIPConfig.h index e9c317dfc79d5c..d739017e401179 100644 --- a/src/lib/core/CHIPConfig.h +++ b/src/lib/core/CHIPConfig.h @@ -1785,6 +1785,60 @@ extern const char CHIP_NON_PRODUCTION_MARKER[]; #define CHIP_CONFIG_MAX_BDX_LOG_TRANSFERS 5 #endif // CHIP_CONFIG_MAX_BDX_LOG_TRANSFERS +/** + * @file + * Configuration settings for Terms and Conditions (TC) acknowledgements during device commissioning. + */ + +/** + * @def CHIP_CONFIG_TC_REQUIRED + * + * @brief Indicates whether terms and conditions are required during commissioning. + * + * This macro defines whether the device commissioning process requires the user to acknowledge terms and conditions. + * - 1: Terms and conditions are required. + * - 0: Terms and conditions are not required. + * + * If this is set to 1, both CHIP_CONFIG_TC_REQUIRED_ACKNOWLEDGEMENTS and + * CHIP_CONFIG_TC_REQUIRED_ACKNOWLEDGEMENTS_VERSION must be defined. + */ +#ifndef CHIP_CONFIG_TC_REQUIRED +#define CHIP_CONFIG_TC_REQUIRED (0) +#endif + +#if CHIP_CONFIG_TC_REQUIRED + +/** + * @def CHIP_CONFIG_TC_REQUIRED_ACKNOWLEDGEMENTS + * + * @brief Configures the required terms and conditions acknowledgements bitmask. + * + * This macro defines the required terms and conditions acknowledgements bitmask. The bit-field is 16 bits long, so the possible + * value range is [0, 65535). This setting can be used to require that terms and conditions are presented to the user during + * commissioning. + */ +#ifndef CHIP_CONFIG_TC_REQUIRED_ACKNOWLEDGEMENTS +#error "CHIP_CONFIG_TC_REQUIRED_ACKNOWLEDGEMENTS must be defined when CHIP_CONFIG_TC_REQUIRED is enabled." +#endif + +/** + * @def CHIP_CONFIG_TC_REQUIRED_ACKNOWLEDGEMENTS_VERSION + * + * @brief Configures the latest known version of the terms and conditions. + * + * This macro defines the version number of the latest terms and conditions. It allows the application to iterate on revisions of + * the terms and conditions. A value of 0 indicates that no specific version is required. This setting can be used to enforce + * version-specific terms and conditions acknowledgements in the application. When the set of terms and conditions needs to be + * changed, the version number should be monotonically increased. If the latest terms and conditions version is updated (most + * likely during an OTA), then this may signal to the Administrator that updated terms and conditions should be presented to the + * user. + */ +#ifndef CHIP_CONFIG_TC_REQUIRED_ACKNOWLEDGEMENTS_VERSION +#error "CHIP_CONFIG_TC_REQUIRED_ACKNOWLEDGEMENTS_VERSION must be defined when CHIP_CONFIG_TC_REQUIRED is enabled." +#endif + +#endif // CHIP_CONFIG_TC_REQUIRED + /** * @} */ diff --git a/src/lib/support/DefaultStorageKeyAllocator.h b/src/lib/support/DefaultStorageKeyAllocator.h index 9ed8a2f56cfd77..b0de78d085e48d 100644 --- a/src/lib/support/DefaultStorageKeyAllocator.h +++ b/src/lib/support/DefaultStorageKeyAllocator.h @@ -1,6 +1,6 @@ /* * - * Copyright (c) 2021 Project CHIP Authors + * Copyright (c) 2021-2024 Project CHIP Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -256,6 +256,10 @@ class DefaultStorageKeyAllocator // when new fabric is created, this list needs to be updated, // when client init DefaultICDClientStorage, this table needs to be loaded. static StorageKeyName ICDFabricList() { return StorageKeyName::FromConst("g/icdfl"); } + + // Terms and Conditions Acceptance Key + // Stores the terms and conditions acceptance including terms and conditions revision, TLV encoded + static StorageKeyName TermsAndConditionsAcceptance() { return StorageKeyName::FromConst("g/tc"); } }; } // namespace chip