/** @file

  Access control by IP address and HTTP method.

  @section license License

  Licensed to the Apache Software Foundation (ASF) under one
  or more contributor license agreements.  See the NOTICE file
  distributed with this work for additional information
  regarding copyright ownership.  The ASF licenses this file
  to you 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.
 */

/*****************************************************************************
 *
 *  IPAllow.h - Interface to IP Access Control system
 *
 *
 ****************************************************************************/

#pragma once

#include <string>
#include <string_view>
#include <vector>

#include "hdrs/HTTP.h"
#include "ProxyConfig.h"
#include "tscore/IpMap.h"
#include "tscpp/util/TextView.h"
#include "tscore/ts_file.h"

// forward declare in name only so it can be a friend.
struct IpAllowUpdate;
namespace YAML
{
class Node;
}

/** Singleton class for access controls.
 */
class IpAllow : public ConfigInfo
{
  friend struct IpAllowUpdate;

  using MethodNames = std::vector<std::string>;

  static constexpr uint32_t ALL_METHOD_MASK = ~0; // Mask for all methods.

  /** An access control record.
      It has the methods permitted and the source line. This is a POD used by @a ACL.
  */
  struct Record {
    /// Default constructor.
    /// Present only to make Vec<> happy, do not use.
    Record()              = default;
    Record(Record &&that) = default;
    explicit Record(uint32_t method_mask);
    Record(uint32_t method_mask, int line, MethodNames &&nonstandard_methods, bool deny_nonstandard_methods);

    uint32_t _method_mask{0};
    int _src_line{0};
    MethodNames _nonstandard_methods;
    bool _deny_nonstandard_methods{false};
  };

public:
  using self_type     = IpAllow; ///< Self reference type.
  using scoped_config = ConfigProcessor::scoped_config<self_type, self_type>;

  // indicator for whether we should be checking the acl record for src ip or dest ip
  enum match_key_t { SRC_ADDR, DST_ADDR };
  /// Token strings for configuration
  static constexpr ts::TextView OPT_MATCH_SRC{"src_ip"};
  static constexpr ts::TextView OPT_MATCH_DST{"dest_ip"};
  static constexpr ts::TextView OPT_ACTION_TAG{"action"};
  static constexpr ts::TextView OPT_ACTION_ALLOW{"ip_allow"};
  static constexpr ts::TextView OPT_ACTION_DENY{"ip_deny"};
  static constexpr ts::TextView OPT_METHOD{"method"};
  static constexpr ts::TextView OPT_METHOD_ALL{"all"};

  static constexpr ts::TextView YAML_TAG_ROOT{"ip_allow"};
  static constexpr ts::TextView YAML_TAG_IP_ADDRS{"ip_addrs"};
  static constexpr ts::TextView YAML_TAG_APPLY{"apply"};
  static constexpr ts::TextView YAML_VALUE_APPLY_IN{"in"};
  static constexpr ts::TextView YAML_VALUE_APPLY_OUT{"out"};
  static constexpr ts::TextView YAML_TAG_ACTION{"action"};
  static constexpr ts::TextView YAML_VALUE_ACTION_ALLOW{"allow"};
  static constexpr ts::TextView YAML_VALUE_ACTION_DENY{"deny"};
  static constexpr ts::TextView YAML_TAG_METHODS{"methods"};
  static constexpr ts::TextView YAML_VALUE_METHODS_ALL{"all"};

  static constexpr const char *MODULE_NAME = "IPAllow";

  /** An access control record and support data.
   * The primary point of this is to hold the backing configuration in memory while the ACL
   * is in use.
   */
  class ACL
  {
    friend class IpAllow;
    using self_type = ACL; ///< Self reference type.
  public:
    ACL()                  = default;
    ACL(const self_type &) = delete;         // no copies.
    explicit ACL(self_type &&that) noexcept; // move allowed.
    ~ACL();

    self_type &operator=(const self_type &) = delete;
    self_type &operator                     =(self_type &&that) noexcept;

    void clear(); ///< Drop data and config reference.

    static uint32_t MethodIdxToMask(int wksidx);

    /// Check if the ACL is valid (i.e. not uninitialized or missing).
    bool isValid() const;
    /// Check if the ACL denies all access.
    bool isDenyAll() const;
    /// Check if the ACL allows all access.
    bool isAllowAll() const;

    bool isMethodAllowed(int method_wksidx) const;

    bool isNonstandardMethodAllowed(std::string_view method) const;

    /// Return the configuration source line for this ACL.
    int source_line() const;

  private:
    // @a config must already be ref counted.
    ACL(const Record *r, IpAllow *config) noexcept;

    const Record *_r{nullptr}; ///< The actual ACL record.
    IpAllow *_config{nullptr}; ///< The backing configuration.
  };

  explicit IpAllow(const char *config_var);

  void Print() const;

  static ACL match(sockaddr const *ip, match_key_t key);
  static ACL match(IpEndpoint const *ip, match_key_t key);

  static void startup();
  static void reconfigure();
  /// @return The global instance.
  static IpAllow *acquire();
  /// Release the configuration.
  /// @a config is released and can then be garbage collected.
  static void release(IpAllow *config);
  /// Release this configuration.
  /// @a this is released and can then be garbage collected.
  void release();

  /// A static ACL that permits all methods.
  static ACL makeAllowAllACL();
  /// A static ACL that denies everything.
  static const ACL DENY_ALL_ACL;

  /* @return The previous accept check state
   * This is a global variable that is independent of
   * the ip_allow configuration
   */
  static bool enableAcceptCheck(bool state);

  /* @return The current accept check state
   * This is a global variable that is independent of
   * the ip_allow configuration
   */
  static bool isAcceptCheckEnabled();

  const ts::file::path &get_config_file() const;

private:
  static size_t configid;               ///< Configuration ID for update management.
  static const Record ALLOW_ALL_RECORD; ///< Static record that allows all access.
  static bool accept_check_p;           ///< @c true if deny all can be enforced during accept.

  void PrintMap(const IpMap *map) const;

  int BuildTable();
  int ATSBuildTable(const std::string &);
  int YAMLBuildTable(const std::string &);
  bool YAMLLoadEntry(const YAML::Node &);
  bool YAMLLoadIPAddrRange(const YAML::Node &, IpMap *map, void *mark);
  bool YAMLLoadMethod(const YAML::Node &node, Record &rec);

  ts::file::path config_file; ///< Path to configuration file.
  IpMap _src_map;
  IpMap _dst_map;
  std::vector<Record> _src_acls;
  std::vector<Record> _dst_acls;
};

// ------ Record methods --------

inline IpAllow::Record::Record(uint32_t method_mask) : _method_mask(method_mask) {}

inline IpAllow::Record::Record(uint32_t method_mask, int ln, MethodNames &&nonstandard_methods, bool deny_nonstandard_methods)
  : _method_mask(method_mask),
    _src_line(ln),
    _nonstandard_methods(nonstandard_methods),
    _deny_nonstandard_methods(deny_nonstandard_methods)
{
}

// ------ ACL methods --------

inline IpAllow::ACL::ACL(const IpAllow::Record *r, IpAllow *config) noexcept : _r(r), _config(config) {}

inline IpAllow::ACL::ACL(self_type &&that) noexcept : _r(that._r), _config(that._config)
{
  that._r      = nullptr;
  that._config = nullptr;
}

inline IpAllow::ACL::~ACL()
{
  if (_config != nullptr) {
    _config->release();
  }
}

inline auto
IpAllow::ACL::operator=(self_type &&that) noexcept -> self_type &
{
  // move and clear so @a that doesn't drop the config reference.
  this->_r      = that._r;
  that._r       = nullptr;
  this->_config = that._config;
  that._config  = nullptr;

  return *this;
}

inline uint32_t
IpAllow::ACL::MethodIdxToMask(int wksidx)
{
  return 1U << (wksidx - HTTP_WKSIDX_CONNECT);
}

inline bool
IpAllow::ACL::isValid() const
{
  return _r != nullptr;
}

inline bool
IpAllow::ACL::isDenyAll() const
{
  return _r == nullptr || (_r->_method_mask == 0 && _r->_nonstandard_methods.empty());
}

inline bool
IpAllow::ACL::isAllowAll() const
{
  return _r && _r->_method_mask == ALL_METHOD_MASK;
}

inline bool
IpAllow::ACL::isMethodAllowed(int method_wksidx) const
{
  return _r && 0 != (_r->_method_mask & MethodIdxToMask(method_wksidx));
}

inline bool
IpAllow::ACL::isNonstandardMethodAllowed(std::string_view method) const
{
  if (_r == nullptr) {
    return false;
  } else if (_r->_method_mask == ALL_METHOD_MASK) {
    return true;
  }
  bool method_in_set =
    std::find_if(_r->_nonstandard_methods.begin(), _r->_nonstandard_methods.end(),
                 [method](std::string_view const &s) { return 0 == strcasecmp(s, method); }) != _r->_nonstandard_methods.end();
  return _r->_deny_nonstandard_methods ? !method_in_set : method_in_set;
}

inline void
IpAllow::ACL::clear()
{
  if (_config) {
    _config->release();
    _config = nullptr;
  }
  _r = nullptr;
}

inline int
IpAllow::ACL::source_line() const
{
  return _r ? _r->_src_line : 0;
}

// ------ IpAllow methods --------

inline bool
IpAllow::enableAcceptCheck(bool state)
{
  bool temp      = accept_check_p;
  accept_check_p = state;
  return temp;
}

inline bool
IpAllow::isAcceptCheckEnabled()
{
  return accept_check_p;
}

inline auto
IpAllow::match(IpEndpoint const *ip, match_key_t key) -> ACL
{
  return self_type::match(&ip->sa, key);
}

inline auto
IpAllow::makeAllowAllACL() -> ACL
{
  return {&ALLOW_ALL_RECORD, nullptr};
}

inline const ts::file::path &
IpAllow::get_config_file() const
{
  return config_file;
}
