bool PluginRootContext::parsePluginConfig()

in plugins/wasm-cpp/extensions/key_auth/plugin.cc [59:291]


bool PluginRootContext::parsePluginConfig(const json& configuration,
                                          KeyAuthConfigRule& rule) {
  if ((configuration.find("consumers") != configuration.end()) &&
      (configuration.find("credentials") != configuration.end())) {
    LOG_WARN("The consumers field and the credentials field cannot appear at the same level");
    return false;
  }
  if ((configuration.find("consumers") == configuration.end()) &&
      (configuration.find("credentials") == configuration.end())) {
    LOG_WARN("No consumers and no credentials");
    return false;
  }
  if (configuration.find("credentials") != configuration.end()) {
    if (!JsonArrayIterate(
          configuration, "credentials", [&](const json& credentials) -> bool {
            auto credential = JsonValueAs<std::string>(credentials);
            if (credential.second != Wasm::Common::JsonParserResultDetail::OK) {
              return false;
            }
            rule.credentials.insert(credential.first.value());
            return true;
          })) {
      LOG_WARN("failed to parse configuration for credentials.");
      return false;
    }
    if (!JsonArrayIterate(configuration, "keys", [&](const json& item) -> bool {
          auto key = JsonValueAs<std::string>(item);
          if (key.second != Wasm::Common::JsonParserResultDetail::OK) {
            return false;
          }
          rule.keys.push_back(key.first.value());
          return true;
        })) {
      LOG_WARN("failed to parse configuration for keys.");
      return false;
    }
    if (rule.keys.empty()) {
      LOG_WARN("at least one key has to be configured for a rule.");
      return false;
    }
    rule.keys.push_back(OriginalAuthKey);
    auto it = configuration.find("realm");
    if (it != configuration.end()) {
      auto realm_string = JsonValueAs<std::string>(it.value());
      if (realm_string.second != Wasm::Common::JsonParserResultDetail::OK) {
        return false;
      }
      rule.realm = realm_string.first.value();
    }
    it = configuration.find("in_query");
    if (it != configuration.end()) {
      auto in_query = JsonValueAs<bool>(it.value());
      if (in_query.second != Wasm::Common::JsonParserResultDetail::OK ||
          !in_query.first) {
        LOG_WARN("failed to parse 'in_query' field in filter configuration.");
        return false;
      }
      rule.in_query = in_query.first.value();
    }
    it = configuration.find("in_header");
    if (it != configuration.end()) {
      auto in_header = JsonValueAs<bool>(it.value());
      if (in_header.second != Wasm::Common::JsonParserResultDetail::OK ||
          !in_header.first) {
        LOG_WARN("failed to parse 'in_header' field in filter configuration.");
        return false;
      }
      rule.in_header = in_header.first.value();
    }
    if (!rule.in_query && !rule.in_header) {
      LOG_WARN("at least one of 'in_query' and 'in_header' must set to true");
      return false;
    }
    // LOG_DEBUG(rule.debugString("parse phase, credentials branch"));
  }
  if (configuration.find("consumers") != configuration.end()) {
    bool need_global_keys = false;
    if (!JsonArrayIterate(
        configuration, "consumers", [&](const json& consumer) -> bool {
          Consumer c;
          auto item = consumer.find("name");
          if (item == consumer.end()) {
            LOG_WARN("can't find 'name' field in consumer.");
            return false;
          }
          auto name = JsonValueAs<std::string>(item.value());
          if (name.second != Wasm::Common::JsonParserResultDetail::OK ||
              !name.first) {
            return false;
          }
          c.name = name.first.value();
          if (consumer.find("credential") != consumer.end() &&
              consumer.find("credentials") != consumer.end()) {
            LOG_WARN("'credential' and 'credentials' can't appear at the same time.");
            return false;
          }
          if (consumer.find("credential") == consumer.end() &&
              consumer.find("credentials") == consumer.end()) {
            LOG_WARN("at least one of 'credential' and 'credentials' should be set.");
            return false;
          }
          item = consumer.find("credential");
          if (item != consumer.end()) {
            auto credential = JsonValueAs<std::string>(item.value());
            if (credential.second != Wasm::Common::JsonParserResultDetail::OK ||
                !credential.first) {
              return false;
            }
            c.credentials.insert(credential.first.value());
            if (rule.credential_to_name.find(credential.first.value()) !=
                rule.credential_to_name.end()) {
              LOG_WARN(absl::StrCat("duplicate consumer credential: ",
                                    credential.first.value()));
              return false;
            }
            rule.credentials.insert(credential.first.value());
            rule.credential_to_name.emplace(
                std::make_pair(credential.first.value(), name.first.value()));
          }
          item = consumer.find("credentials");
          if (item != consumer.end()) {
              if (!JsonArrayIterate(
                    consumer, "credentials", [&](const json& credential_json) -> bool {
                      auto credential = JsonValueAs<std::string>(credential_json);
                      if (credential.second != Wasm::Common::JsonParserResultDetail::OK ||
                          !credential.first) {
                        return false;
                      }
                      c.credentials.insert(credential.first.value());
                      if (rule.credential_to_name.find(credential.first.value()) !=
                          rule.credential_to_name.end()) {
                        LOG_WARN(absl::StrCat("duplicate consumer credential: ",
                                              credential.first.value()));
                        return false;
                      }
                      rule.credentials.insert(credential.first.value());
                      rule.credential_to_name.emplace(
                          std::make_pair(credential.first.value(), name.first.value()));
                      return true;
                    })) {
                LOG_WARN(absl::StrCat("failed to parse credentials for consumer: ", c.name));
                return false;
              }
          }
          item = consumer.find("keys");
          if (item == consumer.end()) {
            LOG_WARN("not found keys configuration for consumer " + c.name + ", will use global configuration to extract keys");
            need_global_keys = true;
          } else {
            c.keys = std::vector<std::string>{OriginalAuthKey};
            if (!JsonArrayIterate(
                  consumer, "keys", [&](const json& key_json) -> bool {
                    auto key = JsonValueAs<std::string>(key_json);
                    if (key.second !=
                        Wasm::Common::JsonParserResultDetail::OK) {
                      return false;
                    }
                    c.keys->push_back(key.first.value());
                    return true;
                  })) {
              LOG_WARN("failed to parse configuration for consumer keys.");
              return false;
            }
            item = consumer.find("in_query");
            if (item != consumer.end()) {
              auto in_query = JsonValueAs<bool>(item.value());
              if (in_query.second != Wasm::Common::JsonParserResultDetail::OK || !in_query.first) {
                LOG_WARN("failed to parse 'in_query' field in consumer configuration.");
                return false;
              }
              c.in_query = in_query.first;
            }
            item = consumer.find("in_header");
            if (item != consumer.end()) {
              auto in_header = JsonValueAs<bool>(item.value());
              if (in_header.second !=
                      Wasm::Common::JsonParserResultDetail::OK ||
                  !in_header.first) {
                LOG_WARN(
                    "failed to parse 'in_header' field in consumer "
                    "configuration.");
                return false;
              }
              c.in_header = in_header.first;
            }
          }
          rule.consumers.push_back(std::move(c));
          return true;
        })) {
      LOG_WARN("failed to parse configuration for credentials.");
      return false;
    }
    if (need_global_keys) {
      if (!JsonArrayIterate(configuration, "keys", [&](const json& item) -> bool {
            auto key = JsonValueAs<std::string>(item);
            if (key.second != Wasm::Common::JsonParserResultDetail::OK) {
              return false;
            }
            rule.keys.push_back(key.first.value());
            return true;
          })) {
        LOG_WARN("failed to parse configuration for keys.");
        return false;
      }
      auto it = configuration.find("in_query");
      if (it != configuration.end()) {
        auto in_query = JsonValueAs<bool>(it.value());
        if (in_query.second != Wasm::Common::JsonParserResultDetail::OK ||
            !in_query.first) {
          LOG_WARN("failed to parse 'in_query' field in filter configuration.");
          return false;
        }
        rule.in_query = in_query.first.value();
      }
      it = configuration.find("in_header");
      if (it != configuration.end()) {
        auto in_header = JsonValueAs<bool>(it.value());
        if (in_header.second != Wasm::Common::JsonParserResultDetail::OK ||
            !in_header.first) {
          LOG_WARN("failed to parse 'in_header' field in filter configuration.");
          return false;
        }
        rule.in_header = in_header.first.value();
      }
      if (!rule.in_query && !rule.in_header) {
        LOG_WARN("at least one of 'in_query' and 'in_header' must set to true");
        return false;
      }
    }
    // LOG_DEBUG(rule.debugString("parse phase, consumers branch"));
  }
  return true;
}