Restrict 'cd' to the 'prepare' context
The change follows up the previous fix, which blocked 'cd' command in 'prepare' context entirely.
Bug: https://tree.taiga.io/project/jktjkt-netconf-cli/issue/223
Fixes: 218ee7bcbef1c066a2be56f087ab8c824b529188
Change-Id: Iea0902e7981bcf3f9d41425e58cdd64ef6ea0be0
diff --git a/src/interpreter.cpp b/src/interpreter.cpp
index d139e8b..73af6fc 100644
--- a/src/interpreter.cpp
+++ b/src/interpreter.cpp
@@ -57,6 +57,16 @@
return boost::apply_visitor(pathToStringVisitor(), path);
}
+void Interpreter::checkRpcPath(const dataPath_& commandPath) const
+{
+ if (auto inputPath = m_datastore.inputDatastorePath()) {
+ dataPath_ newPath = realPath(m_parser.currentPath(), commandPath);
+ if (!pathToDataString(newPath, Prefixes::WhenNeeded).starts_with(*inputPath)) {
+ throw std::runtime_error("Can't execute `cd` outside of the `prepare` context.");
+ }
+ }
+}
+
void Interpreter::operator()(const commit_&) const
{
m_datastore.commitChanges();
@@ -98,9 +108,7 @@
void Interpreter::operator()(const cd_& cd) const
{
- if (auto rpcInputPath = m_datastore.inputDatastorePath(); rpcInputPath && !pathToDataString(cd.m_path, Prefixes::WhenNeeded).starts_with(m_parser.currentNode())) {
- throw std::runtime_error("Can't cd out of `prepare` context");
- }
+ checkRpcPath(cd.m_path);
m_parser.changeNode(cd.m_path);
}
diff --git a/src/interpreter.hpp b/src/interpreter.hpp
index f2cfd11..3723432 100644
--- a/src/interpreter.hpp
+++ b/src/interpreter.hpp
@@ -36,6 +36,8 @@
void operator()(const quit_&) const;
private:
+ void checkRpcPath(const dataPath_& commandPath) const;
+
[[nodiscard]] std::string buildTypeInfo(const std::string& path) const;
template <typename PathType>
diff --git a/tests/interpreter.cpp b/tests/interpreter.cpp
index 0c03d89..087a9b7 100644
--- a/tests/interpreter.cpp
+++ b/tests/interpreter.cpp
@@ -456,6 +456,9 @@
{
REQUIRE_THROWS(boost::apply_visitor(Interpreter(parser, proxyDatastore), command_{cd_{{}, dataPath_{Scope::Absolute, {dataNode_{module_{{"example"}}, container_{"somewhereElse"}}}}}}));
REQUIRE_THROWS(boost::apply_visitor(Interpreter(parser, proxyDatastore), command_{cd_{{}, dataPath_{Scope::Relative, {dataNode_{nodeup_{}}}}}}));
+
+ // Test that the parser allows to change the current node within the rpc context
+ REQUIRE_NOTHROW(boost::apply_visitor(Interpreter(parser, proxyDatastore), command_{cd_{{}, dataPath_{Scope::Relative, {dataNode_{container_{"payload"}}}}}}));
boost::apply_visitor(Interpreter(parser, proxyDatastore), command_{cancel_{}});
}