]> granicus.if.org Git - icinga2/commitdiff
Implement validation for modified attributes
authorGunnar Beutner <gunnar@beutner.name>
Thu, 13 Aug 2015 06:52:00 +0000 (08:52 +0200)
committerGunnar Beutner <gunnar@beutner.name>
Sat, 15 Aug 2015 18:07:11 +0000 (20:07 +0200)
lib/base/dynamicobject.cpp
lib/base/exception.cpp
lib/base/object.cpp
lib/base/object.hpp
tools/mkclass/classcompiler.cpp

index 5f09b1140b8acb63ae1a8c37ceb0ce51f50989e2..229e4e5b314a1e72fce48f39623442a18b87d0a4 100644 (file)
@@ -33,6 +33,7 @@
 #include "base/workqueue.hpp"
 #include "base/context.hpp"
 #include "base/application.hpp"
+#include "config/configitem.hpp"
 #include <fstream>
 #include <boost/foreach.hpp>
 #include <boost/exception/errinfo_api_function.hpp>
@@ -95,6 +96,23 @@ void DynamicObject::ClearExtension(const String& key)
        extensions->Remove(key);
 }
 
+class ModAttrValidationUtils : public ValidationUtils
+{
+public:
+       virtual bool ValidateName(const String& type, const String& name) const override
+       {
+               DynamicType::Ptr dtype = DynamicType::GetByName(type);
+
+               if (!dtype)
+                       return false;
+
+               if (!dtype->GetObject(name))
+                       return false;
+
+               return true;
+       }
+};
+
 void DynamicObject::ModifyAttribute(const String& attr, const Value& value)
 {
        Dictionary::Ptr original_attributes = GetOriginalAttributes();
@@ -118,7 +136,10 @@ void DynamicObject::ModifyAttribute(const String& attr, const Value& value)
                }
        }
 
-       //TODO: validation, vars.os
+       ModAttrValidationUtils utils;
+       ValidateField(fid, value, utils);
+
+       //TODO: vars.os
        SetField(fid, value);
 
        if (updated_original_attributes)
index a079837e56b101d263283b42824bd30ae1a9901e..b48de54aba8f14493f5a2bdd649445ed45352443 100644 (file)
@@ -161,18 +161,20 @@ String icinga::DiagnosticInformation(const std::exception& ex, bool verbose, Sta
                Dictionary::Ptr currentHint = vex->GetDebugHint();
                Array::Ptr messages;
 
-               BOOST_FOREACH(const String& attr, vex->GetAttributePath()) {
-                       Dictionary::Ptr props = currentHint->Get("properties");
+               if (currentHint) {
+                       BOOST_FOREACH(const String& attr, vex->GetAttributePath()) {
+                               Dictionary::Ptr props = currentHint->Get("properties");
 
-                       if (!props)
-                               break;
+                               if (!props)
+                                       break;
 
-                       currentHint = props->Get(attr);
+                               currentHint = props->Get(attr);
 
-                       if (!currentHint)
-                               break;
+                               if (!currentHint)
+                                       break;
 
-                       messages = currentHint->Get("messages");
+                               messages = currentHint->Get("messages");
+                       }
                }
 
                if (messages && messages->GetLength() > 0) {
index 15667f516c71ff35f6faeaffb5a7479a84634a8c..e341640a6fb74c51fdbad74622b1e105f5b67b40 100644 (file)
@@ -92,7 +92,12 @@ Value Object::GetField(int id) const
                BOOST_THROW_EXCEPTION(std::runtime_error("Invalid field ID."));
 }
 
+void Object::ValidateField(int id, const Value& value, const ValidationUtils& utils)
+{
+       /* Nothing to do here. */
+}
+
 void Object::NotifyField(int id, const Value& cookie)
 {
        BOOST_THROW_EXCEPTION(std::runtime_error("Invalid field ID."));
-}
\ No newline at end of file
+}
index d8823d1739912dca7d2f481cd968c63b2af5d71c..3b8f41b1d4b918dc11005826bcd843e0a77562fd 100644 (file)
@@ -48,6 +48,7 @@ class Value;
 class Object;
 class Type;
 class String;
+class ValidationUtils;
 
 extern I2_BASE_API Value Empty;
 
@@ -100,6 +101,7 @@ public:
 
        virtual void SetField(int id, const Value& value, bool suppress_events = false, const Value& cookie = Empty);
        virtual Value GetField(int id) const;
+       virtual void ValidateField(int id, const Value& value, const ValidationUtils& utils);
        virtual void NotifyField(int id, const Value& cookie = Empty);
 
 #ifdef I2_DEBUG
index 636c5fdaf36d5b3ce6f549a73df9ea91c7d31cdd..fafbcb7b07e4e0c529aad90331b7554b1a7aab54 100644 (file)
@@ -596,6 +596,50 @@ void ClassCompiler::HandleClass(const Klass& klass, const ClassDebugInfo&)
 
                m_Impl << "}" << std::endl << std::endl;
                
+               /* ValidateField */
+               m_Header << "protected:" << std::endl
+                        << "\t" << "virtual void ValidateField(int id, const Value& value, const ValidationUtils& utils);" << std::endl;
+
+               m_Impl << "void ObjectImpl<" << klass.Name << ">::ValidateField(int id, const Value& value, const ValidationUtils& utils)" << std::endl
+                      << "{" << std::endl;
+
+               if (!klass.Parent.empty())
+                       m_Impl << "\t" << "int real_id = id - " << klass.Parent << "::TypeInstance->GetFieldCount(); " << std::endl
+                              << "\t" << "if (real_id < 0) { " << klass.Parent << "::ValidateField(id, value, utils); return; }" << std::endl;
+
+               m_Impl << "\t" << "switch (";
+
+               if (!klass.Parent.empty())
+                       m_Impl << "real_id";
+               else
+                       m_Impl << "id";
+
+               m_Impl << ") {" << std::endl;
+
+               num = 0;
+               for (it = klass.Fields.begin(); it != klass.Fields.end(); it++) {
+                       m_Impl << "\t\t" << "case " << num << ":" << std::endl
+                              << "\t\t\t" << "Validate" << it->GetFriendlyName() << "(";
+                       
+                       if (it->Attributes & FAEnum)
+                               m_Impl << "static_cast<" << it->Type.GetRealType() << ">(static_cast<int>(";
+
+                       m_Impl << "value";
+                       
+                       if (it->Attributes & FAEnum)
+                               m_Impl << "))";
+                       
+                       m_Impl << ", utils);" << std::endl
+                              << "\t\t\t" << "break;" << std::endl;
+                       num++;
+               }
+
+               m_Impl << "\t\t" << "default:" << std::endl
+                      << "\t\t\t" << "throw std::runtime_error(\"Invalid field ID.\");" << std::endl
+                      << "\t" << "}" << std::endl;
+
+               m_Impl << "}" << std::endl << std::endl;
+
                /* NotifyField */
                m_Header << "protected:" << std::endl
                         << "\t" << "virtual void NotifyField(int id, const Value& cookie = Empty);" << std::endl;