2020-04-14 10:45:36 -05:00
|
|
|
# Django settings
|
|
|
|
|
|
|
|
import os
|
2022-04-12 16:39:19 -04:00
|
|
|
import sys
|
2020-04-14 10:45:36 -05:00
|
|
|
|
|
|
|
import django.conf.global_settings
|
2022-09-12 09:34:19 -04:00
|
|
|
import django.conf.locale
|
2023-10-24 20:17:03 +03:00
|
|
|
import redis
|
2022-04-12 16:39:19 -04:00
|
|
|
import structlog
|
2023-10-24 20:17:03 +03:00
|
|
|
import urllib3
|
2020-04-14 10:45:36 -05:00
|
|
|
|
2022-01-10 14:34:16 +01:00
|
|
|
from mainsite.oauth2.scopes import SupportedScopes
|
|
|
|
|
2020-04-14 10:45:36 -05:00
|
|
|
_DEFAULT_ARG = object()
|
|
|
|
|
|
|
|
|
2020-09-29 18:07:56 +00:00
|
|
|
def non_zipcode_countries():
|
|
|
|
return {
|
|
|
|
"AE": "United Arab Emirates",
|
|
|
|
"AG": "Antigua and Barbuda",
|
|
|
|
"AN": "Netherlands Antilles",
|
|
|
|
"AO": "Angola",
|
|
|
|
"AW": "Aruba",
|
|
|
|
"BF": "Burkina Faso",
|
|
|
|
"BI": "Burundi",
|
|
|
|
"BJ": "Benin",
|
|
|
|
"BS": "Bahamas",
|
|
|
|
"BW": "Botswana",
|
|
|
|
"BZ": "Belize",
|
|
|
|
"CD": "Congo, the Democratic Republic of the",
|
|
|
|
"CF": "Central African Republic",
|
|
|
|
"CG": "Congo",
|
|
|
|
"CI": "Cote d'Ivoire",
|
|
|
|
"CK": "Cook Islands",
|
|
|
|
"CM": "Cameroon",
|
|
|
|
"DJ": "Djibouti",
|
|
|
|
"DM": "Dominica",
|
|
|
|
"ER": "Eritrea",
|
|
|
|
"FJ": "Fiji",
|
|
|
|
"GD": "Grenada",
|
|
|
|
"GH": "Ghana",
|
|
|
|
"GM": "Gambia",
|
|
|
|
"GN": "Guinea",
|
|
|
|
"GQ": "Equatorial Guinea",
|
|
|
|
"GY": "Guyana",
|
|
|
|
"HK": "Hong Kong",
|
|
|
|
"IE": "Ireland",
|
|
|
|
"JM": "Jamaica",
|
|
|
|
"KE": "Kenya",
|
|
|
|
"KI": "Kiribati",
|
|
|
|
"KM": "Comoros",
|
|
|
|
"KN": "Saint Kitts and Nevis",
|
|
|
|
"KP": "North Korea",
|
|
|
|
"LC": "Saint Lucia",
|
|
|
|
"ML": "Mali",
|
|
|
|
"MO": "Macao",
|
|
|
|
"MR": "Mauritania",
|
|
|
|
"MS": "Montserrat",
|
|
|
|
"MU": "Mauritius",
|
|
|
|
"MW": "Malawi",
|
|
|
|
"NR": "Nauru",
|
|
|
|
"NU": "Niue",
|
|
|
|
"PA": "Panama",
|
|
|
|
"QA": "Qatar",
|
|
|
|
"RW": "Rwanda",
|
|
|
|
"SB": "Solomon Islands",
|
|
|
|
"SC": "Seychelles",
|
|
|
|
"SL": "Sierra Leone",
|
|
|
|
"SO": "Somalia",
|
|
|
|
"SR": "Suriname",
|
|
|
|
"ST": "Sao Tome and Principe",
|
|
|
|
"SY": "Syria",
|
|
|
|
"TF": "French Southern Territories",
|
|
|
|
"TK": "Tokelau",
|
|
|
|
"TL": "Timor-Leste",
|
|
|
|
"TO": "Tonga",
|
|
|
|
"TT": "Trinidad and Tobago",
|
|
|
|
"TV": "Tuvalu",
|
|
|
|
"TZ": "Tanzania, United Republic of",
|
|
|
|
"UG": "Uganda",
|
|
|
|
"VU": "Vanuatu",
|
|
|
|
"YE": "Yemen",
|
|
|
|
"ZA": "South Africa",
|
|
|
|
"ZW": "Zimbabwe",
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-04-14 10:45:36 -05:00
|
|
|
def print_debug(*args, **kwargs):
|
|
|
|
if DEBUG:
|
|
|
|
print(*args, **kwargs)
|
|
|
|
|
|
|
|
|
|
|
|
def get_locale_name(code):
|
2021-07-10 10:12:35 -05:00
|
|
|
"""Gets the readble name for a locale code."""
|
2020-04-14 10:45:36 -05:00
|
|
|
language_map = dict(django.conf.global_settings.LANGUAGES)
|
|
|
|
|
|
|
|
# check for exact match
|
|
|
|
if code in language_map:
|
|
|
|
return language_map[code]
|
|
|
|
|
|
|
|
# try for the language, fall back to just using the code
|
|
|
|
language = code.split("-")[0]
|
|
|
|
return language_map.get(language, code)
|
|
|
|
|
|
|
|
|
2021-01-13 20:35:07 +00:00
|
|
|
def set_from_env(name, default=_DEFAULT_ARG):
|
|
|
|
return _set_from_env(name, globals(), default)
|
2020-04-14 10:45:36 -05:00
|
|
|
|
|
|
|
|
2021-01-13 20:35:07 +00:00
|
|
|
def _set_from_env(name, context, default):
|
2020-04-14 10:45:36 -05:00
|
|
|
"""
|
|
|
|
Sets a global variable from a environment variable of the same name.
|
|
|
|
|
2021-01-13 20:35:07 +00:00
|
|
|
This is useful to leave the option unset and use Django's default
|
|
|
|
(which may change).
|
2020-04-14 10:45:36 -05:00
|
|
|
"""
|
|
|
|
if default is _DEFAULT_ARG and name not in os.environ:
|
|
|
|
return
|
|
|
|
|
2021-01-13 20:35:07 +00:00
|
|
|
context[name] = os.environ.get(name, default)
|
2020-04-14 10:45:36 -05:00
|
|
|
|
|
|
|
|
2021-01-13 20:35:07 +00:00
|
|
|
def set_option(name, value, envvar_type=None):
|
|
|
|
return _set_option(name, value, globals(), envvar_type)
|
|
|
|
|
2020-04-14 10:45:36 -05:00
|
|
|
|
2021-01-13 20:35:07 +00:00
|
|
|
def _set_option(name, value, context, envvar_type=None):
|
|
|
|
"""
|
|
|
|
Sets an option, first checking for env vars,
|
|
|
|
then checking for value already set,
|
|
|
|
then going to the default value if passed.
|
|
|
|
Environment variables are always strings, but
|
|
|
|
we try to coerce them to the correct type first by checking
|
|
|
|
the type of the default value provided. If the default
|
|
|
|
value is None, then we check the optional envvar_type arg.
|
|
|
|
"""
|
|
|
|
|
|
|
|
# If value is in True or False we
|
|
|
|
# call set_bool to take advantage of
|
|
|
|
# its type checking for environment variables
|
|
|
|
if isinstance(value, bool):
|
2022-05-10 16:56:30 +03:00
|
|
|
_set_bool(name, value, context)
|
|
|
|
return
|
2021-01-13 20:35:07 +00:00
|
|
|
|
2022-02-15 16:50:13 +02:00
|
|
|
# If value is a list call set_list
|
|
|
|
if isinstance(value, list):
|
2022-05-10 16:56:30 +03:00
|
|
|
_set_list(name, value, context)
|
|
|
|
return
|
2022-02-15 16:50:13 +02:00
|
|
|
|
2021-01-13 20:35:07 +00:00
|
|
|
if value is not None:
|
|
|
|
envvar_type = type(value)
|
|
|
|
else:
|
|
|
|
# If value is None, we'll use the provided envvar_type, if it is not None
|
|
|
|
if envvar_type is None:
|
|
|
|
raise ValueError(
|
|
|
|
f"If no default value is provided for the setting {name} the envvar_type argument must be set."
|
|
|
|
)
|
|
|
|
|
|
|
|
if name in os.environ:
|
|
|
|
env_var = os.environ.get(name)
|
|
|
|
# Coerce type based on provided value
|
|
|
|
context[name] = envvar_type(env_var)
|
|
|
|
# If the environment variable isn't set
|
|
|
|
else:
|
|
|
|
_set_default(name, value, context)
|
2020-04-14 10:45:36 -05:00
|
|
|
|
|
|
|
|
|
|
|
def set_bool(name, value):
|
2021-01-13 20:35:07 +00:00
|
|
|
return _set_bool(name, value, globals())
|
|
|
|
|
|
|
|
|
|
|
|
def _set_bool(name, value, context):
|
2021-07-10 10:12:35 -05:00
|
|
|
"""Sets and option, first checking for env vars, then checking for value already set, then going to the default value if passed."""
|
2020-04-14 10:45:36 -05:00
|
|
|
if name in os.environ:
|
|
|
|
envval = os.environ.get(name).lower()
|
|
|
|
if envval in ["1", "true", "y", "yes"]:
|
2021-01-13 20:35:07 +00:00
|
|
|
context[name] = True
|
2020-04-14 10:45:36 -05:00
|
|
|
elif envval in ["0", "false", "n", "no"]:
|
2021-01-13 20:35:07 +00:00
|
|
|
context[name] = False
|
2020-04-14 10:45:36 -05:00
|
|
|
else:
|
2021-07-10 10:12:35 -05:00
|
|
|
raise ValueError(f"{name} is a boolean, cannot match '{os.environ[name]}'")
|
2020-04-14 10:45:36 -05:00
|
|
|
|
2021-01-13 20:35:07 +00:00
|
|
|
_set_default(name, value, context)
|
|
|
|
|
|
|
|
|
2022-02-15 16:50:13 +02:00
|
|
|
def _set_list(name, value, context):
|
|
|
|
"""
|
|
|
|
For list types we split the env variable value using a comma as a delimiter
|
|
|
|
"""
|
|
|
|
|
|
|
|
if name in os.environ:
|
|
|
|
context[name] = os.environ.get(name).lower().split(",")
|
|
|
|
|
|
|
|
_set_default(name, value, context)
|
|
|
|
|
|
|
|
|
2021-01-13 20:35:07 +00:00
|
|
|
def set_default(name, value):
|
|
|
|
return _set_default(name, value, globals())
|
|
|
|
|
|
|
|
|
|
|
|
def _set_default(name, value, context):
|
2021-07-10 10:12:35 -05:00
|
|
|
"""Sets the default value for the option if it's not already set."""
|
2021-01-13 20:35:07 +00:00
|
|
|
if name not in context:
|
|
|
|
context[name] = value
|
2020-04-14 10:45:36 -05:00
|
|
|
|
|
|
|
|
|
|
|
def try_include(filename):
|
2021-07-10 10:12:35 -05:00
|
|
|
"""Tries to include another file from the settings directory."""
|
2020-09-30 01:13:38 +00:00
|
|
|
print_debug(f"including {filename} {RELEASE_ENV}")
|
2020-04-14 10:45:36 -05:00
|
|
|
try:
|
|
|
|
with open(filename) as f:
|
|
|
|
exec(compile(f.read(), filename, "exec"), globals())
|
|
|
|
|
2020-09-30 01:13:38 +00:00
|
|
|
print_debug(f"loaded additional settings file '{filename}'")
|
2020-04-14 10:45:36 -05:00
|
|
|
|
|
|
|
except FileNotFoundError:
|
2020-09-30 01:13:38 +00:00
|
|
|
print_debug(f"additional settings file '{filename}' was not found, skipping")
|
2020-04-14 10:45:36 -05:00
|
|
|
|
|
|
|
|
|
|
|
def read_file(name):
|
|
|
|
with open(name) as fh:
|
|
|
|
return fh.read()
|
|
|
|
|
|
|
|
|
2022-01-10 14:34:16 +01:00
|
|
|
def set_from_file(name, path, default=_DEFAULT_ARG, envvar_type=None):
|
|
|
|
try:
|
|
|
|
value = read_file(path).strip()
|
2022-07-15 21:47:59 +03:00
|
|
|
except OSError:
|
2022-01-10 14:34:16 +01:00
|
|
|
value = default
|
|
|
|
|
|
|
|
set_option(name, value, envvar_type)
|
|
|
|
|
|
|
|
|
2023-10-24 20:17:03 +03:00
|
|
|
def can_ping_redis(host, port, password):
|
|
|
|
"""
|
|
|
|
Check if Redis is available.
|
|
|
|
"""
|
|
|
|
client = redis.StrictRedis(host=host, port=port, password=password)
|
|
|
|
try:
|
|
|
|
return client.ping()
|
|
|
|
except redis.ConnectionError:
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
2023-09-13 04:54:04 +03:00
|
|
|
def get_cache_backend(cache_name):
|
|
|
|
"""
|
2023-10-24 20:17:03 +03:00
|
|
|
Function to get cache backend based on environment variable.
|
2023-09-13 04:54:04 +03:00
|
|
|
"""
|
|
|
|
cache_backend = globals().get(f"{cache_name.upper()}_CACHE_BACKEND", "RedisCache")
|
|
|
|
|
|
|
|
options = {}
|
|
|
|
|
|
|
|
if cache_name == "error_emails":
|
|
|
|
options["MAX_ENTRIES"] = 2
|
|
|
|
elif cache_name == "default":
|
|
|
|
options["MAX_ENTRIES"] = CACHE_MAX_ENTRIES
|
|
|
|
options["CULL_FREQUENCY"] = 10
|
|
|
|
|
|
|
|
if cache_backend == "RedisCache":
|
2023-10-24 20:17:03 +03:00
|
|
|
if can_ping_redis(REDIS_HOST, REDIS_PORT, REDIS_PASSWORD):
|
2023-10-25 17:48:52 +03:00
|
|
|
print_debug("Was able to ping Redis, using RedisCache")
|
2023-10-24 20:17:03 +03:00
|
|
|
return {
|
|
|
|
"BACKEND": "django.core.cache.backends.redis.RedisCache",
|
|
|
|
"LOCATION": f"redis://:{REDIS_PASSWORD}@{REDIS_HOST}:{REDIS_PORT}",
|
|
|
|
"OPTIONS": {},
|
|
|
|
}
|
|
|
|
else:
|
|
|
|
# fall back to DatabseCache if cache_name is sessions else
|
|
|
|
# LocMemCache
|
|
|
|
cache_backend = (
|
|
|
|
"DatabaseCache" if cache_name == "session" else "LocMemCache"
|
|
|
|
)
|
2023-10-25 17:48:52 +03:00
|
|
|
print_debug(f"Was not able to ping Redis, falling back to {cache_backend}")
|
2023-10-24 20:17:03 +03:00
|
|
|
|
|
|
|
if cache_backend == "LocMemCache":
|
2023-09-13 04:54:04 +03:00
|
|
|
return {
|
|
|
|
"BACKEND": "django.core.cache.backends.locmem.LocMemCache",
|
|
|
|
"LOCATION": cache_name,
|
|
|
|
"OPTIONS": options,
|
|
|
|
}
|
2023-10-24 20:17:03 +03:00
|
|
|
|
|
|
|
if cache_backend == "DatabaseCache":
|
2023-09-13 04:54:04 +03:00
|
|
|
return {
|
|
|
|
"BACKEND": "django.core.cache.backends.db.DatabaseCache",
|
|
|
|
"LOCATION": "django_cache",
|
|
|
|
"OPTIONS": options,
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-04-14 10:45:36 -05:00
|
|
|
_ = lambda s: s
|
|
|
|
|
|
|
|
BASE_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", ".."))
|
|
|
|
|
2023-09-13 04:54:04 +03:00
|
|
|
# initial CACHES object so it can be used by release env specific
|
|
|
|
# setup files
|
|
|
|
|
|
|
|
CACHES = {}
|
|
|
|
|
2020-04-14 10:45:36 -05:00
|
|
|
# set RELEASE_ENV, usually one of dev, beta, tutor, prod
|
|
|
|
set_option("RELEASE_ENV", "dev")
|
|
|
|
|
|
|
|
if RELEASE_ENV == "dev":
|
|
|
|
set_bool("DEBUG", True)
|
2020-04-14 21:29:02 +00:00
|
|
|
else:
|
|
|
|
set_bool("DEBUG", False)
|
2020-04-14 10:45:36 -05:00
|
|
|
|
|
|
|
# look for mainsite/settings/${RELEASE_ENV}.py and load if it exists
|
2020-09-30 01:13:38 +00:00
|
|
|
env_file = os.path.join(os.path.dirname(__file__), f"{RELEASE_ENV}.py")
|
2020-04-14 10:45:36 -05:00
|
|
|
try_include(env_file)
|
|
|
|
|
2020-09-30 01:13:38 +00:00
|
|
|
print_debug(f"Release env is '{RELEASE_ENV}'")
|
2020-04-14 10:45:36 -05:00
|
|
|
|
|
|
|
# set version, default from /srv/www.peeringdb.com/etc/VERSION
|
|
|
|
set_option(
|
|
|
|
"PEERINGDB_VERSION", read_file(os.path.join(BASE_DIR, "etc/VERSION")).strip()
|
|
|
|
)
|
|
|
|
|
2021-01-13 20:35:07 +00:00
|
|
|
MIGRATION_MODULES = {"django_peeringdb": None}
|
2020-12-03 19:10:02 +00:00
|
|
|
|
2020-04-14 10:45:36 -05:00
|
|
|
# Contact email, from address, support email
|
|
|
|
set_from_env("SERVER_EMAIL")
|
|
|
|
|
2021-08-20 07:32:52 -05:00
|
|
|
# Error emails are dispatched to this address
|
|
|
|
set_option("OPERATIONS_EMAIL", SERVER_EMAIL)
|
|
|
|
|
2020-04-14 10:45:36 -05:00
|
|
|
set_from_env("SECRET_KEY")
|
|
|
|
|
|
|
|
# database
|
|
|
|
set_option("DATABASE_ENGINE", "mysql")
|
|
|
|
set_option("DATABASE_HOST", "127.0.0.1")
|
|
|
|
set_option("DATABASE_PORT", "")
|
|
|
|
set_option("DATABASE_NAME", "peeringdb")
|
|
|
|
set_option("DATABASE_USER", "peeringdb")
|
|
|
|
set_option("DATABASE_PASSWORD", "")
|
|
|
|
|
2023-09-13 04:54:04 +03:00
|
|
|
# redis
|
|
|
|
set_option("REDIS_HOST", "127.0.0.1")
|
|
|
|
set_option("REDIS_PORT", "6379")
|
|
|
|
set_from_env("REDIS_PASSWORD")
|
2022-01-12 12:33:32 -06:00
|
|
|
|
2023-09-13 04:54:04 +03:00
|
|
|
# API Cache
|
2022-01-12 12:33:32 -06:00
|
|
|
set_option("API_CACHE_ENABLED", True)
|
|
|
|
set_option("API_CACHE_ROOT", os.path.join(BASE_DIR, "api-cache"))
|
|
|
|
set_option("API_CACHE_LOG", os.path.join(BASE_DIR, "var/log/api-cache.log"))
|
|
|
|
|
2023-10-24 20:17:03 +03:00
|
|
|
# KMZ export file
|
|
|
|
set_option("KMZ_EXPORT_FILE", os.path.join(API_CACHE_ROOT, "peeringdb.kmz"))
|
|
|
|
set_option("KMZ_DOWNLOAD_PATH", "^export/kmz/$")
|
|
|
|
if RELEASE_ENV == "dev":
|
|
|
|
# setting to blank means KMZ_DOWNLOAD_PATH is used instead and
|
|
|
|
# the file is served from the local filesystem
|
|
|
|
set_option("KMZ_DOWNLOAD_URL", "")
|
|
|
|
else:
|
|
|
|
# setting this will override KMZ_DOWNLOAD_PATH to an absolute / external
|
|
|
|
# url. We do this by default if the release env is not dev
|
|
|
|
set_option("KMZ_DOWNLOAD_URL", "https://public.peeringdb.com/peeringdb.kmz")
|
|
|
|
|
2020-04-14 10:45:36 -05:00
|
|
|
# Keys
|
2021-05-19 09:11:30 -04:00
|
|
|
set_from_env("MELISSA_KEY")
|
2020-04-14 10:45:36 -05:00
|
|
|
set_from_env("GOOGLE_GEOLOC_API_KEY")
|
|
|
|
|
|
|
|
set_from_env("RDAP_LACNIC_APIKEY")
|
|
|
|
|
|
|
|
set_from_env("RECAPTCHA_PUBLIC_KEY")
|
|
|
|
set_from_env("RECAPTCHA_SECRET_KEY")
|
|
|
|
|
|
|
|
set_from_env("DESKPRO_KEY")
|
|
|
|
set_from_env("DESKPRO_URL")
|
|
|
|
|
2022-01-12 12:33:32 -06:00
|
|
|
set_from_env(
|
|
|
|
"OIDC_RSA_PRIVATE_KEY_ACTIVE_PATH", os.path.join(API_CACHE_ROOT, "keys", "oidc.key")
|
|
|
|
)
|
2022-01-10 14:34:16 +01:00
|
|
|
|
2022-11-08 13:42:17 +02:00
|
|
|
# Google tags
|
|
|
|
|
|
|
|
# Analytics
|
|
|
|
|
|
|
|
set_option("GOOGLE_ANALYTICS_ID", "")
|
2022-04-12 16:39:19 -04:00
|
|
|
|
2020-04-14 10:45:36 -05:00
|
|
|
# Limits
|
|
|
|
|
|
|
|
API_THROTTLE_ENABLED = True
|
2021-07-07 17:57:04 -05:00
|
|
|
set_option("API_THROTTLE_RATE_ANON", "100/second")
|
|
|
|
set_option("API_THROTTLE_RATE_USER", "100/second")
|
|
|
|
set_option("API_THROTTLE_RATE_FILTER_DISTANCE", "10/minute")
|
2021-08-18 08:21:22 -05:00
|
|
|
set_option("API_THROTTLE_IXF_IMPORT", "1/minute")
|
2021-07-07 17:57:04 -05:00
|
|
|
|
2022-04-12 16:39:19 -04:00
|
|
|
# Configuration for melissa request rate limiting in the api (#1124)
|
|
|
|
|
2022-06-15 15:23:26 +03:00
|
|
|
set_option("API_THROTTLE_MELISSA_ENABLED_ADMIN", False)
|
|
|
|
set_option("API_THROTTLE_MELISSA_RATE_ADMIN", "10/minute")
|
|
|
|
|
2022-04-12 16:39:19 -04:00
|
|
|
set_option("API_THROTTLE_MELISSA_ENABLED_USER", False)
|
|
|
|
set_option("API_THROTTLE_MELISSA_RATE_USER", "10/minute")
|
|
|
|
|
|
|
|
set_option("API_THROTTLE_MELISSA_ENABLED_ORG", False)
|
|
|
|
set_option("API_THROTTLE_MELISSA_RATE_ORG", "10/minute")
|
|
|
|
|
|
|
|
set_option("API_THROTTLE_MELISSA_ENABLED_IP", False)
|
|
|
|
set_option("API_THROTTLE_MELISSA_RATE_IP", "1/minute")
|
|
|
|
|
|
|
|
# Configuration for response-size rate limiting in the api (#1126)
|
|
|
|
|
|
|
|
|
|
|
|
# Anonymous (ip-address) - Size threshold (bytes, default = 1MB)
|
2022-11-08 19:25:32 +02:00
|
|
|
set_option("API_THROTTLE_REPEATED_REQUEST_THRESHOLD_IP", 1000000)
|
2022-04-12 16:39:19 -04:00
|
|
|
# Anonymous (ip-address) - Rate limit
|
2022-11-08 19:25:32 +02:00
|
|
|
set_option("API_THROTTLE_REPEATED_REQUEST_RATE_IP", "10/minute")
|
2022-04-12 16:39:19 -04:00
|
|
|
# Anonymous (ip-address) - On/Off toggle
|
2022-11-08 19:25:32 +02:00
|
|
|
set_option("API_THROTTLE_REPEATED_REQUEST_ENABLED_IP", False)
|
2022-04-12 16:39:19 -04:00
|
|
|
|
|
|
|
|
|
|
|
# Anonymous (cidr ipv4/24, ipv6/64) - Size threshold (bytes, default = 1MB)
|
2022-11-08 19:25:32 +02:00
|
|
|
set_option("API_THROTTLE_REPEATED_REQUEST_THRESHOLD_CIDR", 1000000)
|
2022-04-12 16:39:19 -04:00
|
|
|
# Anonymous (cidr ipv4/24, ipv6/64) - Rate limit
|
2022-11-08 19:25:32 +02:00
|
|
|
set_option("API_THROTTLE_REPEATED_REQUEST_RATE_CIDR", "10/minute")
|
2022-04-12 16:39:19 -04:00
|
|
|
# Anonymous (cidr ipv4/24, ipv6/64) - On/Off toggle
|
2022-11-08 19:25:32 +02:00
|
|
|
set_option("API_THROTTLE_REPEATED_REQUEST_ENABLED_CIDR", False)
|
2022-04-12 16:39:19 -04:00
|
|
|
|
|
|
|
|
|
|
|
# User - Size threshold (bytes, default = 1MB)
|
2022-11-08 19:25:32 +02:00
|
|
|
set_option("API_THROTTLE_REPEATED_REQUEST_THRESHOLD_USER", 1000000)
|
2022-04-12 16:39:19 -04:00
|
|
|
# User - Rate limit
|
2022-11-08 19:25:32 +02:00
|
|
|
set_option("API_THROTTLE_REPEATED_REQUEST_RATE_USER", "10/minute")
|
2022-04-12 16:39:19 -04:00
|
|
|
# User - On/Off toggle
|
2022-11-08 19:25:32 +02:00
|
|
|
set_option("API_THROTTLE_REPEATED_REQUEST_ENABLED_USER", False)
|
2022-04-12 16:39:19 -04:00
|
|
|
|
|
|
|
|
|
|
|
# Organization- Size threshold (bytes, default = 1MB)
|
2022-11-08 19:25:32 +02:00
|
|
|
set_option("API_THROTTLE_REPEATED_REQUEST_THRESHOLD_ORG", 1000000)
|
2022-04-12 16:39:19 -04:00
|
|
|
# Organization - Rate limit
|
2022-11-08 19:25:32 +02:00
|
|
|
set_option("API_THROTTLE_REPEATED_REQUEST_RATE_ORG", "10/minute")
|
2022-04-12 16:39:19 -04:00
|
|
|
# Organization - On/Off toggle
|
2022-11-08 19:25:32 +02:00
|
|
|
set_option("API_THROTTLE_REPEATED_REQUEST_ENABLED_ORG", False)
|
2022-04-12 16:39:19 -04:00
|
|
|
|
2022-11-08 19:25:32 +02:00
|
|
|
# Expected repeated requests are cached for n seconds (default = 31 days)
|
|
|
|
set_option("API_THROTTLE_REPEATED_REQUEST_CACHE_EXPIRY", 86400 * 31)
|
2022-04-12 16:39:19 -04:00
|
|
|
|
|
|
|
|
2021-07-07 17:57:04 -05:00
|
|
|
# spatial queries require user auth
|
|
|
|
set_option("API_DISTANCE_FILTER_REQUIRE_AUTH", True)
|
|
|
|
|
|
|
|
# spatial queries required verified user
|
|
|
|
set_option("API_DISTANCE_FILTER_REQUIRE_VERIFIED", True)
|
|
|
|
|
|
|
|
# specifies the expiry period of cached geo-coordinates
|
|
|
|
# in seconds (default 30days)
|
|
|
|
set_option("GEOCOORD_CACHE_EXPIRY", 86400 * 30)
|
2020-04-14 10:45:36 -05:00
|
|
|
|
|
|
|
# maximum value to allow in network.info_prefixes4
|
2023-03-13 20:24:09 -05:00
|
|
|
set_option("DATA_QUALITY_MAX_PREFIX_V4_LIMIT", 1200000)
|
2020-04-14 10:45:36 -05:00
|
|
|
|
|
|
|
# maximum value to allow in network.info_prefixes6
|
2023-03-13 20:24:09 -05:00
|
|
|
set_option("DATA_QUALITY_MAX_PREFIX_V6_LIMIT", 180000)
|
2020-04-14 10:45:36 -05:00
|
|
|
|
|
|
|
# minimum value to allow for prefix length on a v4 prefix
|
|
|
|
set_option("DATA_QUALITY_MIN_PREFIXLEN_V4", 18)
|
|
|
|
|
|
|
|
# maximum value to allow for prefix length on a v4 prefix
|
|
|
|
set_option("DATA_QUALITY_MAX_PREFIXLEN_V4", 28)
|
|
|
|
|
|
|
|
# minimum value to allow for prefix length on a v6 prefix
|
|
|
|
set_option("DATA_QUALITY_MIN_PREFIXLEN_V6", 64)
|
|
|
|
|
|
|
|
# maximum value to allow for prefix length on a v6 prefix
|
|
|
|
set_option("DATA_QUALITY_MAX_PREFIXLEN_V6", 116)
|
|
|
|
|
2020-04-17 19:57:23 -05:00
|
|
|
# maximum value to allow for irr set hierarchy depth
|
|
|
|
set_option("DATA_QUALITY_MAX_IRR_DEPTH", 3)
|
|
|
|
|
2020-09-29 18:07:56 +00:00
|
|
|
# minimum value to allow for speed on an netixlan (currently 100Mbit)
|
|
|
|
set_option("DATA_QUALITY_MIN_SPEED", 100)
|
|
|
|
|
2022-06-15 15:23:26 +03:00
|
|
|
# maximum value to allow for speed on an netixlan (currently 5Tbit)
|
|
|
|
set_option("DATA_QUALITY_MAX_SPEED", 5000000)
|
2020-09-29 18:07:56 +00:00
|
|
|
|
2023-04-12 00:04:36 +03:00
|
|
|
# validate parent status when saving objects (e.g., ensure an active object cannot have a deleted parent)
|
|
|
|
# this SHOULD BE ENABLED in 99% of cases
|
|
|
|
# developers may disable before running pdb_load if the sync source has broken parent -> child status relationships
|
|
|
|
set_option("DATA_QUALITY_VALIDATE_PARENT_STATUS", True)
|
|
|
|
|
2021-01-13 20:35:07 +00:00
|
|
|
set_option(
|
|
|
|
"RATELIMITS",
|
|
|
|
{
|
|
|
|
"request_login_POST": "4/m",
|
|
|
|
"request_translation": "2/m",
|
|
|
|
"resend_confirmation_mail": "2/m",
|
|
|
|
"view_request_ownership_POST": "3/m",
|
|
|
|
"view_request_ownership_GET": "3/m",
|
|
|
|
"view_affiliate_to_org_POST": "3/m",
|
|
|
|
"view_verify_POST": "2/m",
|
|
|
|
"view_username_retrieve_initiate": "2/m",
|
|
|
|
"view_import_ixlan_ixf_preview": "1/m",
|
|
|
|
"view_import_net_ixf_postmortem": "1/m",
|
2023-10-24 20:17:03 +03:00
|
|
|
"view_verified_update_POST": "3/m",
|
|
|
|
"view_verified_update_accept_POST": "4/m",
|
2021-01-13 20:35:07 +00:00
|
|
|
},
|
|
|
|
)
|
2020-04-14 10:45:36 -05:00
|
|
|
|
2020-04-01 11:08:12 +00:00
|
|
|
# maximum number of affiliation requests a user can have pending
|
2020-12-03 19:10:02 +00:00
|
|
|
set_option("MAX_USER_AFFILIATION_REQUESTS", 5)
|
2020-04-14 10:45:36 -05:00
|
|
|
|
2020-06-24 12:55:01 -05:00
|
|
|
# Determines age of network contact objects that get hard deleted
|
|
|
|
# during `pdb_delete_poc` execution. (days)
|
|
|
|
set_option("POC_DELETION_PERIOD", 30)
|
|
|
|
|
2020-09-29 18:07:56 +00:00
|
|
|
# Sets maximum age for a user-request in the verification queue
|
|
|
|
# Otherwise we delete with the pdb_cleanup_vq tool
|
|
|
|
set_option("VQUEUE_USER_MAX_AGE", 90)
|
2020-06-24 12:55:01 -05:00
|
|
|
|
2023-09-13 04:54:04 +03:00
|
|
|
# NEGATIVE CACHE
|
|
|
|
|
|
|
|
# 401 - unauthorized - 1 minute
|
|
|
|
set_option("NEGATIVE_CACHE_EXPIRY_401", 60)
|
|
|
|
|
|
|
|
# 403 - forbidden - 10 seconds (permission check failure)
|
|
|
|
# it is recommended to keep this low as some permission checks
|
|
|
|
# on write (POST, PUT) requests check the payload to determine
|
|
|
|
# permission namespaces
|
|
|
|
set_option("NEGATIVE_CACHE_EXPIRY_403", 10)
|
|
|
|
|
|
|
|
# 429 - too many requests - 10 seconds
|
|
|
|
# recommended to keep this low as to not interfer with the
|
|
|
|
# REST api rate limiting that is already in place which includes
|
|
|
|
# a timer as to when the rate limit will reset - the negative
|
|
|
|
# cache will be on top of that and will obscure the accurate
|
|
|
|
# rate limit reset time
|
|
|
|
set_option("NEGATIVE_CACHE_EXPIRY_429", 10)
|
|
|
|
|
|
|
|
# inactive users and inactive keys - 1 hour
|
|
|
|
set_option("NEGATIVE_CACHE_EXPIRY_INACTIVE_AUTH", 3600)
|
|
|
|
|
|
|
|
# throttled negative cache for repeated 401/403s (X per minute)
|
|
|
|
set_option("NEGATIVE_CACHE_REPEATED_RATE_LIMIT", 10)
|
|
|
|
|
|
|
|
# global on / off switch for negative cache
|
|
|
|
set_option("NEGATIVE_CACHE_ENABLED", True)
|
|
|
|
|
|
|
|
|
2020-04-14 10:45:36 -05:00
|
|
|
# Django config
|
|
|
|
|
|
|
|
ALLOWED_HOSTS = ["*"]
|
|
|
|
SITE_ID = 1
|
|
|
|
|
|
|
|
TIME_ZONE = "UTC"
|
|
|
|
USE_TZ = True
|
|
|
|
|
2021-08-18 08:21:22 -05:00
|
|
|
ADMINS = [
|
2021-08-20 07:32:52 -05:00
|
|
|
("Operations", OPERATIONS_EMAIL),
|
2021-08-18 08:21:22 -05:00
|
|
|
]
|
2020-04-14 10:45:36 -05:00
|
|
|
MANAGERS = ADMINS
|
|
|
|
|
|
|
|
MEDIA_ROOT = os.path.abspath(os.path.join(BASE_DIR, "media"))
|
2020-09-30 01:13:38 +00:00
|
|
|
MEDIA_URL = f"/m/{PEERINGDB_VERSION}/"
|
2020-04-14 10:45:36 -05:00
|
|
|
|
|
|
|
STATIC_ROOT = os.path.abspath(os.path.join(BASE_DIR, "static"))
|
2020-09-30 01:13:38 +00:00
|
|
|
STATIC_URL = f"/s/{PEERINGDB_VERSION}/"
|
2020-04-14 10:45:36 -05:00
|
|
|
|
2023-01-18 18:32:46 +02:00
|
|
|
# limit error emails (2/minute)
|
|
|
|
set_option("ERROR_EMAILS_PERIOD", 60)
|
|
|
|
set_option("ERROR_EMAILS_LIMIT", 2)
|
|
|
|
|
2022-04-28 07:01:07 -05:00
|
|
|
# maximum number of entries in the cache
|
|
|
|
set_option("CACHE_MAX_ENTRIES", 5000)
|
|
|
|
|
|
|
|
# dont allow going below 5000 (#1151)
|
|
|
|
if CACHE_MAX_ENTRIES < 5000:
|
|
|
|
raise ValueError("CACHE_MAX_ENTRIES needs to be >= 5000 (#1151)")
|
|
|
|
|
|
|
|
|
2023-09-13 04:54:04 +03:00
|
|
|
set_option("SESSION_ENGINE", "django.contrib.sessions.backends.db")
|
|
|
|
|
|
|
|
set_option("DEFAULT_CACHE_BACKEND", "DatabaseCache")
|
|
|
|
set_option("ERROR_EMAILS_CACHE_BACKEND", "LocMemCache")
|
|
|
|
set_option("NEGATIVE_CACHE_BACKEND", "RedisCache")
|
|
|
|
|
|
|
|
# only relevant if SESSION_ENGINE = "django.contrib.sessions.backends.cache"
|
|
|
|
set_option("SESSION_CACHE_ALIAS", "session")
|
|
|
|
set_option("SESSION_CACHE_BACKEND", "RedisCache")
|
2020-04-14 10:45:36 -05:00
|
|
|
|
2023-09-13 04:54:04 +03:00
|
|
|
# setup caches
|
|
|
|
cache_names = ["default", "negative", "session", "error_emails"]
|
|
|
|
for cache_name in cache_names:
|
|
|
|
if cache_name not in CACHES:
|
|
|
|
CACHES[cache_name] = get_cache_backend(cache_name)
|
2022-01-11 08:56:47 -06:00
|
|
|
|
|
|
|
# keep database connection open for n seconds
|
|
|
|
# this is defined at the module level so we can expose
|
|
|
|
# it as an environment variable
|
|
|
|
#
|
|
|
|
# it will be set again in the DATABASES configuration
|
|
|
|
# from this global
|
|
|
|
set_option("CONN_MAX_AGE", 3600)
|
|
|
|
|
2020-04-14 10:45:36 -05:00
|
|
|
DATABASES = {
|
|
|
|
"default": {
|
2020-09-30 01:13:38 +00:00
|
|
|
"ENGINE": f"django.db.backends.{DATABASE_ENGINE}",
|
2020-04-14 10:45:36 -05:00
|
|
|
"HOST": DATABASE_HOST,
|
|
|
|
"PORT": DATABASE_PORT,
|
|
|
|
"NAME": DATABASE_NAME,
|
|
|
|
"USER": DATABASE_USER,
|
|
|
|
"PASSWORD": DATABASE_PASSWORD,
|
2022-01-11 08:56:47 -06:00
|
|
|
"CONN_MAX_AGE": CONN_MAX_AGE,
|
2021-01-13 20:35:07 +00:00
|
|
|
# "TEST": { "NAME": f"{DATABASE_NAME}_test" }
|
2020-04-14 10:45:36 -05:00
|
|
|
},
|
|
|
|
}
|
|
|
|
|
2022-04-12 16:39:19 -04:00
|
|
|
# Set file logging path
|
|
|
|
set_option("LOGFILE_PATH", os.path.join(BASE_DIR, "var/log/django.log"))
|
|
|
|
|
|
|
|
if DEBUG:
|
|
|
|
set_option("DJANGO_LOG_LEVEL", "INFO")
|
|
|
|
else:
|
|
|
|
set_option("DJANGO_LOG_LEVEL", "ERROR")
|
|
|
|
|
|
|
|
structlog.configure(
|
|
|
|
processors=[
|
|
|
|
structlog.stdlib.filter_by_level,
|
|
|
|
structlog.processors.TimeStamper(fmt="iso"),
|
|
|
|
structlog.stdlib.add_logger_name,
|
|
|
|
structlog.stdlib.add_log_level,
|
|
|
|
structlog.stdlib.PositionalArgumentsFormatter(),
|
|
|
|
structlog.processors.StackInfoRenderer(),
|
|
|
|
structlog.processors.format_exc_info,
|
|
|
|
structlog.processors.UnicodeDecoder(),
|
|
|
|
structlog.stdlib.ProcessorFormatter.wrap_for_formatter,
|
|
|
|
],
|
|
|
|
context_class=structlog.threadlocal.wrap_dict(dict),
|
|
|
|
logger_factory=structlog.stdlib.LoggerFactory(),
|
|
|
|
wrapper_class=structlog.stdlib.BoundLogger,
|
|
|
|
cache_logger_on_first_use=True,
|
|
|
|
)
|
2020-04-14 10:45:36 -05:00
|
|
|
|
|
|
|
LOGGING = {
|
|
|
|
"version": 1,
|
|
|
|
"disable_existing_loggers": False,
|
2022-04-12 16:39:19 -04:00
|
|
|
"formatters": {
|
|
|
|
"json": {
|
|
|
|
"()": structlog.stdlib.ProcessorFormatter,
|
|
|
|
"processor": structlog.processors.JSONRenderer(),
|
|
|
|
},
|
|
|
|
"color_console": {
|
|
|
|
"()": structlog.stdlib.ProcessorFormatter,
|
|
|
|
"processor": structlog.dev.ConsoleRenderer(),
|
|
|
|
},
|
|
|
|
"key_value": {
|
|
|
|
"()": structlog.stdlib.ProcessorFormatter,
|
|
|
|
"processor": structlog.processors.KeyValueRenderer(
|
|
|
|
key_order=["timestamp", "level", "event", "logger"]
|
|
|
|
),
|
|
|
|
},
|
|
|
|
},
|
2020-04-14 10:45:36 -05:00
|
|
|
"handlers": {
|
|
|
|
# Include the default Django email handler for errors
|
|
|
|
# This is what you'd get without configuring logging at all.
|
|
|
|
"mail_admins": {
|
2023-01-18 18:32:46 +02:00
|
|
|
# "class": "django.utils.log.AdminEmailHandler",
|
|
|
|
"class": "peeringdb_server.log.ThrottledAdminEmailHandler",
|
2022-04-12 16:39:19 -04:00
|
|
|
# only send emails for error logs
|
2020-04-14 10:45:36 -05:00
|
|
|
"level": "ERROR",
|
|
|
|
# But the emails are plain text by default - HTML is nicer
|
|
|
|
"include_html": True,
|
|
|
|
},
|
|
|
|
# Log to a text file that can be rotated by logrotate
|
|
|
|
"logfile": {
|
|
|
|
"class": "logging.handlers.WatchedFileHandler",
|
2022-04-12 16:39:19 -04:00
|
|
|
"filename": LOGFILE_PATH,
|
|
|
|
"formatter": "key_value",
|
2020-04-14 10:45:36 -05:00
|
|
|
},
|
2020-09-29 18:07:56 +00:00
|
|
|
"console": {
|
|
|
|
"class": "logging.StreamHandler",
|
2022-04-12 16:39:19 -04:00
|
|
|
"formatter": "color_console",
|
|
|
|
"stream": sys.stdout,
|
|
|
|
},
|
|
|
|
"console_json": {
|
|
|
|
"class": "logging.StreamHandler",
|
|
|
|
"formatter": "json",
|
|
|
|
"stream": sys.stdout,
|
|
|
|
},
|
|
|
|
"console_debug": {
|
|
|
|
"class": "logging.StreamHandler",
|
|
|
|
"formatter": "color_console",
|
|
|
|
"stream": sys.stdout,
|
|
|
|
"level": "DEBUG",
|
2020-09-29 18:07:56 +00:00
|
|
|
},
|
2020-04-14 10:45:36 -05:00
|
|
|
},
|
|
|
|
"loggers": {
|
2022-04-12 16:39:19 -04:00
|
|
|
# Django log
|
|
|
|
"django": {
|
|
|
|
"handlers": ["mail_admins", "logfile", "console_debug"],
|
|
|
|
"level": DJANGO_LOG_LEVEL,
|
2020-04-14 10:45:36 -05:00
|
|
|
"propagate": True,
|
|
|
|
},
|
2022-04-12 16:39:19 -04:00
|
|
|
# geo normalization / geo-coding
|
|
|
|
"peeringdb_server.geo": {
|
2020-04-14 10:45:36 -05:00
|
|
|
"handlers": ["logfile"],
|
2022-04-12 16:39:19 -04:00
|
|
|
"level": "INFO",
|
2020-04-14 10:45:36 -05:00
|
|
|
"propagate": False,
|
|
|
|
},
|
2022-04-12 16:39:19 -04:00
|
|
|
# django-structlog specific
|
|
|
|
"django_structlog": {
|
2020-04-14 10:45:36 -05:00
|
|
|
"handlers": ["logfile"],
|
2022-04-12 16:39:19 -04:00
|
|
|
"level": "DEBUG",
|
2020-04-14 10:45:36 -05:00
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
2022-04-12 16:39:19 -04:00
|
|
|
|
2020-04-14 10:45:36 -05:00
|
|
|
INSTALLED_APPS = [
|
|
|
|
"django.contrib.auth",
|
|
|
|
"django.contrib.contenttypes",
|
|
|
|
"django.contrib.sessions",
|
|
|
|
"django.contrib.sites",
|
|
|
|
"django.contrib.messages",
|
|
|
|
"django.contrib.staticfiles",
|
2021-07-07 17:57:04 -05:00
|
|
|
"haystack",
|
2020-06-24 12:55:01 -05:00
|
|
|
"django_otp",
|
|
|
|
"django_otp.plugins.otp_static",
|
|
|
|
"django_otp.plugins.otp_totp",
|
|
|
|
"django_otp.plugins.otp_email",
|
|
|
|
"two_factor",
|
2020-04-14 10:45:36 -05:00
|
|
|
"dal",
|
|
|
|
"dal_select2",
|
|
|
|
"grappelli",
|
2022-10-11 15:45:07 +03:00
|
|
|
"import_export",
|
2020-04-14 10:45:36 -05:00
|
|
|
"django.contrib.admin",
|
|
|
|
"allauth",
|
|
|
|
"allauth.account",
|
|
|
|
"allauth.socialaccount",
|
|
|
|
"allauth.socialaccount.providers.google",
|
|
|
|
"allauth.socialaccount.providers.facebook",
|
2022-06-14 12:03:45 -07:00
|
|
|
"django_bootstrap5",
|
2020-04-14 10:45:36 -05:00
|
|
|
"corsheaders",
|
|
|
|
"crispy_forms",
|
|
|
|
"django_countries",
|
|
|
|
"django_inet",
|
2021-01-13 20:35:07 +00:00
|
|
|
"django_grainy",
|
2020-04-14 10:45:36 -05:00
|
|
|
"django_peeringdb",
|
|
|
|
"django_tables2",
|
|
|
|
"oauth2_provider",
|
|
|
|
"peeringdb_server",
|
2022-01-11 08:56:47 -06:00
|
|
|
"django_security_keys",
|
2020-04-14 10:45:36 -05:00
|
|
|
"reversion",
|
|
|
|
"captcha",
|
|
|
|
"django_handleref",
|
|
|
|
]
|
|
|
|
|
2021-10-15 03:25:38 -05:00
|
|
|
# allows us to regenerate the schema graph image for documentation
|
|
|
|
# purposes in a dev environment
|
|
|
|
if RELEASE_ENV == "dev":
|
|
|
|
INSTALLED_APPS.append("django_extensions")
|
|
|
|
|
|
|
|
|
2020-04-14 10:45:36 -05:00
|
|
|
# List of finder classes that know how to find static files in
|
|
|
|
# various locations.
|
|
|
|
STATICFILES_FINDERS = (
|
|
|
|
"django.contrib.staticfiles.finders.AppDirectoriesFinder",
|
|
|
|
"django.contrib.staticfiles.finders.FileSystemFinder",
|
|
|
|
# 'django.contrib.staticfiles.finders.DefaultStorageFinder',
|
|
|
|
)
|
|
|
|
|
|
|
|
# List of callables that know how to import templates from various sources.
|
|
|
|
_TEMPLATE_LOADERS = (
|
|
|
|
"django.template.loaders.filesystem.Loader",
|
|
|
|
"django.template.loaders.app_directories.Loader",
|
|
|
|
# 'django.template.loaders.eggs.Loader',
|
|
|
|
)
|
|
|
|
|
|
|
|
_TEMPLATE_CONTEXT_PROCESSORS = (
|
|
|
|
"django.contrib.auth.context_processors.auth",
|
|
|
|
"django.template.context_processors.debug",
|
|
|
|
"django.template.context_processors.request",
|
|
|
|
"django.template.context_processors.i18n",
|
|
|
|
"django.template.context_processors.media",
|
|
|
|
"django.template.context_processors.static",
|
|
|
|
"django.template.context_processors.tz",
|
|
|
|
"django.contrib.messages.context_processors.messages",
|
|
|
|
)
|
|
|
|
|
|
|
|
_TEMPLATE_DIRS = (os.path.join(BASE_DIR, "peeringdb_server", "templates"),)
|
|
|
|
|
|
|
|
TEMPLATES = [
|
|
|
|
{
|
|
|
|
"BACKEND": "django.template.backends.django.DjangoTemplates",
|
|
|
|
"DIRS": _TEMPLATE_DIRS,
|
|
|
|
"APP_DIRS": True,
|
|
|
|
"OPTIONS": {
|
|
|
|
"context_processors": _TEMPLATE_CONTEXT_PROCESSORS,
|
|
|
|
# "loaders" : _TEMPLATE_LOADERS
|
|
|
|
},
|
|
|
|
}
|
|
|
|
]
|
|
|
|
|
|
|
|
TEST_RUNNER = "django.test.runner.DiscoverRunner"
|
2022-10-11 05:46:49 -07:00
|
|
|
set_option("X_FRAME_OPTIONS", "DENY")
|
|
|
|
set_option("SECURE_BROWSER_XSS_FILTER", True)
|
|
|
|
set_option("SECURE_CONTENT_TYPE_NOSNIFF", True)
|
|
|
|
set_option("SECURE_HSTS_INCLUDE_SUBDOMAINS", True)
|
|
|
|
set_option("SECURE_HSTS_SECONDS", 47304000)
|
|
|
|
set_option("SECURE_REFERRER_POLICY", "strict-origin-when-cross-origin")
|
|
|
|
|
2022-10-26 18:42:04 +03:00
|
|
|
set_option(
|
|
|
|
"CSP_DEFAULT_SRC",
|
|
|
|
[
|
|
|
|
"'self'",
|
|
|
|
],
|
|
|
|
)
|
|
|
|
set_option("CSP_STYLE_SRC", ["'self'", "fonts.googleapis.com", "'unsafe-inline'"])
|
|
|
|
set_option(
|
|
|
|
"CSP_SCRIPT_SRC",
|
2022-11-08 13:42:17 +02:00
|
|
|
[
|
|
|
|
"'self'",
|
|
|
|
"www.google.com",
|
|
|
|
"www.googletagmanager.com",
|
|
|
|
"www.gstatic.com",
|
|
|
|
"cdn.redoc.ly",
|
|
|
|
"'unsafe-inline'",
|
|
|
|
],
|
2022-10-26 18:42:04 +03:00
|
|
|
)
|
|
|
|
set_option("CSP_FRAME_SRC", ["'self'", "www.google.com", "'unsafe-inline'"])
|
|
|
|
set_option("CSP_FONT_SRC", ["'self'", "fonts.gstatic.com"])
|
|
|
|
set_option("CSP_IMG_SRC", ["'self'", "cdn.redoc.ly", "data:"])
|
|
|
|
set_option("CSP_WORKER_SRC", ["'self'", "blob:"])
|
2023-01-18 18:32:46 +02:00
|
|
|
set_option(
|
|
|
|
"CSP_CONNECT_SRC",
|
|
|
|
[
|
|
|
|
"*.google-analytics.com",
|
|
|
|
"'self'",
|
|
|
|
],
|
|
|
|
)
|
2020-04-14 10:45:36 -05:00
|
|
|
|
|
|
|
MIDDLEWARE = (
|
2020-12-03 19:10:02 +00:00
|
|
|
"corsheaders.middleware.CorsMiddleware",
|
2020-04-14 10:45:36 -05:00
|
|
|
"django.middleware.common.CommonMiddleware",
|
2022-10-11 05:46:49 -07:00
|
|
|
"django.middleware.security.SecurityMiddleware",
|
2023-09-13 04:54:04 +03:00
|
|
|
"peeringdb_server.middleware.RedisNegativeCacheMiddleware",
|
2022-10-11 05:46:49 -07:00
|
|
|
"csp.middleware.CSPMiddleware",
|
2022-07-15 21:47:59 +03:00
|
|
|
"peeringdb_server.middleware.PDBSessionMiddleware",
|
2023-01-18 18:32:46 +02:00
|
|
|
"peeringdb_server.middleware.CacheControlMiddleware",
|
2020-04-14 10:45:36 -05:00
|
|
|
"django.middleware.locale.LocaleMiddleware",
|
|
|
|
"django.middleware.csrf.CsrfViewMiddleware",
|
|
|
|
"django.contrib.auth.middleware.AuthenticationMiddleware",
|
2020-06-24 12:55:01 -05:00
|
|
|
"django_otp.middleware.OTPMiddleware",
|
2020-04-14 10:45:36 -05:00
|
|
|
"django.contrib.messages.middleware.MessageMiddleware",
|
|
|
|
"django.middleware.clickjacking.XFrameOptionsMiddleware",
|
2023-09-13 04:54:04 +03:00
|
|
|
"allauth.account.middleware.AccountMiddleware",
|
2020-04-14 10:45:36 -05:00
|
|
|
)
|
|
|
|
|
|
|
|
AUTHENTICATION_BACKENDS = list()
|
|
|
|
|
|
|
|
PASSWORD_HASHERS = (
|
|
|
|
"django.contrib.auth.hashers.PBKDF2PasswordHasher",
|
|
|
|
"django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher",
|
|
|
|
"django.contrib.auth.hashers.BCryptPasswordHasher",
|
|
|
|
"django.contrib.auth.hashers.SHA1PasswordHasher",
|
|
|
|
"django.contrib.auth.hashers.MD5PasswordHasher",
|
|
|
|
"django.contrib.auth.hashers.CryptPasswordHasher",
|
|
|
|
"hashers_passlib.md5_crypt",
|
|
|
|
"hashers_passlib.des_crypt",
|
|
|
|
"hashers_passlib.bsdi_crypt",
|
|
|
|
)
|
|
|
|
|
|
|
|
ROOT_URLCONF = "mainsite.urls"
|
|
|
|
|
2021-08-18 08:21:22 -05:00
|
|
|
DEFAULT_AUTO_FIELD = "django.db.models.AutoField"
|
|
|
|
|
2020-04-14 10:45:36 -05:00
|
|
|
|
|
|
|
# email vars should be already set from the release environment file
|
|
|
|
# override here from env if set
|
|
|
|
set_from_env("EMAIL_HOST")
|
|
|
|
set_from_env("EMAIL_PORT")
|
|
|
|
set_from_env("EMAIL_HOST_USER")
|
|
|
|
set_from_env("EMAIL_HOST_PASSWORD")
|
|
|
|
set_from_env("EMAIL_USE_TLS")
|
|
|
|
|
2022-01-12 12:33:32 -06:00
|
|
|
set_from_env("SESSION_COOKIE_DOMAIN", "localhost")
|
2020-04-14 10:45:36 -05:00
|
|
|
set_from_env("SESSION_COOKIE_SECURE")
|
|
|
|
set_option("SECURE_PROXY_SSL_HEADER", ("HTTP_X_FWD_PROTO", "https"))
|
|
|
|
|
|
|
|
DEFAULT_FROM_EMAIL = SERVER_EMAIL
|
|
|
|
|
2020-06-24 12:55:01 -05:00
|
|
|
OTP_EMAIL_SENDER = SERVER_EMAIL
|
|
|
|
OTP_EMAIL_SUBJECT = "One time password request"
|
|
|
|
|
2020-04-14 10:45:36 -05:00
|
|
|
|
|
|
|
# Python dotted path to the WSGI application used by Django's runserver.
|
|
|
|
WSGI_APPLICATION = "mainsite.wsgi.application"
|
|
|
|
|
|
|
|
|
|
|
|
AUTH_USER_MODEL = "peeringdb_server.User"
|
|
|
|
|
|
|
|
GRAPPELLI_ADMIN_TITLE = "PeeringDB"
|
|
|
|
|
|
|
|
TABLE_PREFIX = "peeringdb_"
|
|
|
|
ABSTRACT_ONLY = True
|
|
|
|
|
2020-06-24 12:55:01 -05:00
|
|
|
LOGIN_URL = "two_factor:login"
|
2020-04-14 10:45:36 -05:00
|
|
|
LOGIN_REDIRECT_URL = "/"
|
|
|
|
|
|
|
|
# App config
|
|
|
|
|
2022-06-14 12:03:45 -07:00
|
|
|
CRISPY_TEMPLATE_PACK = "django_bootstrap5"
|
2020-04-14 10:45:36 -05:00
|
|
|
|
|
|
|
## django-cors-headers
|
|
|
|
|
|
|
|
# No one specific host is allow Allow-Origin at this point]
|
|
|
|
# Origin for API get request is handled via signals (signals.py)
|
|
|
|
CORS_ORIGIN_WHITELIST = []
|
|
|
|
|
|
|
|
# don't allow cookies
|
|
|
|
CORS_ALLOW_CREDENTIALS = False
|
|
|
|
|
|
|
|
# only allow for cross origin requests for GET and OPTIONS
|
|
|
|
CORS_ALLOW_METHODS = ["GET", "OPTIONS"]
|
|
|
|
|
|
|
|
## OAuth2
|
|
|
|
|
|
|
|
# allows PeeringDB to use external OAuth2 sources
|
2021-01-13 20:35:07 +00:00
|
|
|
set_bool("OAUTH_ENABLED", False)
|
2020-04-14 10:45:36 -05:00
|
|
|
|
2023-07-11 16:20:46 +03:00
|
|
|
# https://django-oauth-toolkit.readthedocs.io/en/latest/changelog.html#id12
|
|
|
|
# default changed to True in django-oauth-toolkit v2, set to False for now
|
|
|
|
# to avoid breaking existing clients
|
|
|
|
set_bool("PKCE_REQUIRED", False)
|
|
|
|
|
2022-01-10 14:34:16 +01:00
|
|
|
# enables OpenID Connect support
|
|
|
|
set_bool("OIDC_ENABLED", True)
|
|
|
|
|
|
|
|
# enables JWT signing algorithm RS256
|
|
|
|
set_from_file("OIDC_RSA_PRIVATE_KEY", OIDC_RSA_PRIVATE_KEY_ACTIVE_PATH, "", str)
|
|
|
|
|
|
|
|
|
2020-04-14 10:45:36 -05:00
|
|
|
AUTHENTICATION_BACKENDS += (
|
2022-01-11 08:56:47 -06:00
|
|
|
# for passwordless auth using security-key
|
|
|
|
# this needs to be first so it can do some clean up
|
|
|
|
"django_security_keys.backends.PasswordlessAuthenticationBackend",
|
2020-04-14 10:45:36 -05:00
|
|
|
# for OAuth provider
|
|
|
|
"oauth2_provider.backends.OAuth2Backend",
|
|
|
|
# for OAuth against external sources
|
|
|
|
"allauth.account.auth_backends.AuthenticationBackend",
|
|
|
|
)
|
|
|
|
|
|
|
|
MIDDLEWARE += (
|
|
|
|
"peeringdb_server.maintenance.Middleware",
|
2021-07-07 17:57:04 -05:00
|
|
|
"peeringdb_server.middleware.CurrentRequestContext",
|
2022-03-08 09:27:45 -04:00
|
|
|
"peeringdb_server.middleware.PDBCommonMiddleware",
|
2022-03-17 18:38:50 -04:00
|
|
|
"peeringdb_server.middleware.PDBPermissionMiddleware",
|
2020-04-14 10:45:36 -05:00
|
|
|
"oauth2_provider.middleware.OAuth2TokenMiddleware",
|
2022-04-12 16:39:19 -04:00
|
|
|
"django_structlog.middlewares.RequestMiddleware",
|
2020-04-14 10:45:36 -05:00
|
|
|
)
|
|
|
|
|
|
|
|
OAUTH2_PROVIDER = {
|
2022-01-10 14:34:16 +01:00
|
|
|
"OIDC_ENABLED": OIDC_ENABLED,
|
|
|
|
"OIDC_RSA_PRIVATE_KEY": OIDC_RSA_PRIVATE_KEY,
|
2023-07-11 16:20:46 +03:00
|
|
|
"PKCE_REQUIRED": PKCE_REQUIRED,
|
2022-01-10 14:34:16 +01:00
|
|
|
"OAUTH2_VALIDATOR_CLASS": "mainsite.oauth2.validators.OIDCValidator",
|
2020-04-14 10:45:36 -05:00
|
|
|
"SCOPES": {
|
2022-01-10 14:34:16 +01:00
|
|
|
SupportedScopes.OPENID: "OpenID Connect scope",
|
|
|
|
SupportedScopes.PROFILE: "user profile",
|
|
|
|
SupportedScopes.EMAIL: "email address",
|
|
|
|
SupportedScopes.NETWORKS: "list of user networks and permissions",
|
2020-04-14 10:45:36 -05:00
|
|
|
},
|
|
|
|
"ALLOWED_REDIRECT_URI_SCHEMES": ["https"],
|
|
|
|
"REQUEST_APPROVAL_PROMPT": "auto",
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-05-10 16:56:30 +03:00
|
|
|
# override this to `peeringdb_server.OAuthApplication` once peeringdb_server
|
|
|
|
# migration 0085 has been applied.
|
|
|
|
|
|
|
|
set_option("OAUTH2_PROVIDER_APPLICATION_MODEL", "oauth2_provider.Application")
|
|
|
|
|
2022-10-11 05:47:54 -07:00
|
|
|
# This is setting is for cookie timeout for oauth sessions.
|
|
|
|
# After the timeout, the ongoing oauth session would expire.
|
|
|
|
|
|
|
|
set_option("OAUTH_COOKIE_MAX_AGE", 1800)
|
|
|
|
|
2021-02-05 13:41:37 +00:00
|
|
|
## grainy
|
2020-04-14 10:45:36 -05:00
|
|
|
|
2021-01-13 20:35:07 +00:00
|
|
|
AUTHENTICATION_BACKENDS += ("django_grainy.backends.GrainyBackend",)
|
2020-04-14 10:45:36 -05:00
|
|
|
|
2023-05-16 21:04:05 +03:00
|
|
|
## Django Elasticsearch DSL
|
|
|
|
|
|
|
|
INSTALLED_APPS.append("django_elasticsearch_dsl")
|
|
|
|
|
2023-10-24 20:17:03 +03:00
|
|
|
set_from_env("ELASTICSEARCH_URL", "https://elasticsearch:9200")
|
|
|
|
# same env var as used by ES server docker image
|
|
|
|
set_from_env("ELASTIC_PASSWORD", "")
|
2023-05-16 21:04:05 +03:00
|
|
|
|
|
|
|
ELASTICSEARCH_DSL = {
|
2023-10-24 20:17:03 +03:00
|
|
|
"default": {
|
|
|
|
"hosts": ELASTICSEARCH_URL,
|
|
|
|
"http_auth": ("elastic", ELASTIC_PASSWORD),
|
|
|
|
"verify_certs": False,
|
|
|
|
}
|
2023-05-16 21:04:05 +03:00
|
|
|
}
|
2023-10-24 20:17:03 +03:00
|
|
|
# stop ES from spamming about unsigned certs
|
|
|
|
urllib3.disable_warnings()
|
2023-05-16 21:04:05 +03:00
|
|
|
|
|
|
|
ELASTICSEARCH_DSL_INDEX_SETTINGS = {"number_of_shards": 1}
|
2023-05-23 22:02:15 -05:00
|
|
|
ELASTICSEARCH_DSL_SIGNAL_PROCESSOR = (
|
|
|
|
"peeringdb_server.signals.ESSilentRealTimeSignalProcessor"
|
|
|
|
)
|
2020-04-14 10:45:36 -05:00
|
|
|
|
|
|
|
## Django Rest Framework
|
|
|
|
|
2021-03-09 13:30:30 -06:00
|
|
|
INSTALLED_APPS += ("rest_framework", "rest_framework_swagger", "rest_framework_api_key")
|
2020-04-14 10:45:36 -05:00
|
|
|
|
|
|
|
REST_FRAMEWORK = {
|
|
|
|
"DEFAULT_AUTHENTICATION_CLASSES": (
|
|
|
|
"rest_framework.authentication.BasicAuthentication",
|
|
|
|
"rest_framework.authentication.SessionAuthentication",
|
|
|
|
),
|
|
|
|
# Use hyperlinked styles by default.
|
|
|
|
# Only used if the `serializer_class` attribute is not set on a view.
|
|
|
|
"DEFAULT_MODEL_SERIALIZER_CLASS": "rest_framework.serializers.HyperlinkedModelSerializer",
|
|
|
|
# Use Django's standard `django.contrib.auth` permissions,
|
|
|
|
# or allow read-only access for unauthenticated users.
|
|
|
|
"DEFAULT_PERMISSION_CLASSES": [
|
|
|
|
"rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly",
|
2021-01-13 20:35:07 +00:00
|
|
|
"django_grainy.rest.ModelViewSetPermissions",
|
2020-04-14 10:45:36 -05:00
|
|
|
],
|
|
|
|
"DEFAULT_RENDERER_CLASSES": ("peeringdb_server.renderers.MetaJSONRenderer",),
|
2020-07-15 02:07:01 -05:00
|
|
|
"DEFAULT_SCHEMA_CLASS": "peeringdb_server.api_schema.BaseSchema",
|
2022-04-12 16:39:19 -04:00
|
|
|
"EXCEPTION_HANDLER": "peeringdb_server.exceptions.rest_exception_handler",
|
2020-04-14 10:45:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
if API_THROTTLE_ENABLED:
|
|
|
|
REST_FRAMEWORK.update(
|
|
|
|
{
|
|
|
|
"DEFAULT_THROTTLE_CLASSES": (
|
2022-02-08 13:14:27 -06:00
|
|
|
"peeringdb_server.rest_throttles.APIAnonUserThrottle",
|
|
|
|
"peeringdb_server.rest_throttles.APIUserThrottle",
|
2022-04-12 16:39:19 -04:00
|
|
|
"peeringdb_server.rest_throttles.ResponseSizeThrottle",
|
2021-07-07 17:57:04 -05:00
|
|
|
"peeringdb_server.rest_throttles.FilterDistanceThrottle",
|
2022-04-12 16:39:19 -04:00
|
|
|
"peeringdb_server.rest_throttles.MelissaThrottle",
|
2020-04-14 10:45:36 -05:00
|
|
|
),
|
|
|
|
"DEFAULT_THROTTLE_RATES": {
|
|
|
|
"anon": API_THROTTLE_RATE_ANON,
|
|
|
|
"user": API_THROTTLE_RATE_USER,
|
2021-07-07 17:57:04 -05:00
|
|
|
"filter_distance": API_THROTTLE_RATE_FILTER_DISTANCE,
|
2021-08-18 08:21:22 -05:00
|
|
|
"ixf_import_request": API_THROTTLE_IXF_IMPORT,
|
2022-11-08 19:25:32 +02:00
|
|
|
"response_size_ip": API_THROTTLE_REPEATED_REQUEST_RATE_IP,
|
|
|
|
"response_size_cidr": API_THROTTLE_REPEATED_REQUEST_RATE_CIDR,
|
|
|
|
"response_size_user": API_THROTTLE_REPEATED_REQUEST_RATE_USER,
|
|
|
|
"response_size_org": API_THROTTLE_REPEATED_REQUEST_RATE_ORG,
|
2022-04-12 16:39:19 -04:00
|
|
|
"melissa_user": API_THROTTLE_MELISSA_RATE_USER,
|
|
|
|
"melissa_org": API_THROTTLE_MELISSA_RATE_ORG,
|
|
|
|
"melissa_ip": API_THROTTLE_MELISSA_RATE_IP,
|
2022-06-15 15:23:26 +03:00
|
|
|
"melissa_admin": API_THROTTLE_MELISSA_RATE_ADMIN,
|
2020-04-14 10:45:36 -05:00
|
|
|
},
|
|
|
|
}
|
|
|
|
)
|
|
|
|
|
2021-01-13 20:35:07 +00:00
|
|
|
## RDAP
|
|
|
|
|
|
|
|
set_bool("RDAP_SELF_BOOTSTRAP", True)
|
|
|
|
# put it under the main cache dir
|
|
|
|
set_option("RDAP_BOOTSTRAP_DIR", os.path.join(BASE_DIR, "api-cache", "rdap-bootstrap"))
|
|
|
|
set_bool("RDAP_IGNORE_RECURSE_ERRORS", True)
|
2020-04-14 10:45:36 -05:00
|
|
|
|
|
|
|
## PeeringDB
|
|
|
|
|
|
|
|
# TODO for tests
|
|
|
|
|
|
|
|
# from address for sponsorship emails
|
|
|
|
set_option("SPONSORSHIPS_EMAIL", SERVER_EMAIL)
|
|
|
|
|
|
|
|
|
2023-01-18 10:12:23 -06:00
|
|
|
set_option("API_URL", "https://www.peeringdb.com/api")
|
2021-01-13 20:35:07 +00:00
|
|
|
set_option("API_DEPTH_ROW_LIMIT", 250)
|
2020-04-14 10:45:36 -05:00
|
|
|
|
2021-07-07 17:57:04 -05:00
|
|
|
# limit results for the standard search
|
|
|
|
# (hitting enter on the main search bar)
|
|
|
|
set_option("SEARCH_RESULTS_LIMIT", 1000)
|
|
|
|
|
|
|
|
# limit results for the quick search
|
|
|
|
# (autocomplete on the main search bar)
|
|
|
|
set_option("SEARCH_RESULTS_AUTOCOMPLETE_LIMIT", 40)
|
|
|
|
|
2021-07-08 21:00:23 -05:00
|
|
|
# boost org,net,fac,ix matches over secondary entites (1.0 == no boost)
|
|
|
|
set_option("SEARCH_MAIN_ENTITY_BOOST", 1.5)
|
|
|
|
|
2021-07-07 17:57:04 -05:00
|
|
|
|
2020-04-14 10:45:36 -05:00
|
|
|
set_option("BASE_URL", "http://localhost")
|
|
|
|
set_option("PASSWORD_RESET_URL", os.path.join(BASE_URL, "reset-password"))
|
|
|
|
|
|
|
|
ACCOUNT_EMAIL_CONFIRMATION_ANONYMOUS_REDIRECT_URL = "/login"
|
|
|
|
ACCOUNT_EMAIL_CONFIRMATION_AUTHENTICATED_REDIRECT_URL = "/verify"
|
|
|
|
ACCOUNT_EMAIL_REQUIRED = True
|
|
|
|
|
2022-01-11 08:56:47 -06:00
|
|
|
# Webauthn (U2F) settings
|
|
|
|
|
|
|
|
# unique id for the relying party
|
2022-01-12 12:33:32 -06:00
|
|
|
set_option("WEBAUTHN_RP_ID", SESSION_COOKIE_DOMAIN)
|
2022-01-11 08:56:47 -06:00
|
|
|
|
|
|
|
# name of the relying party (displayed to the user)
|
|
|
|
set_option("WEBAUTHN_RP_NAME", "PeeringDB")
|
|
|
|
|
|
|
|
# webauthn origin validation
|
2022-02-15 16:50:13 +02:00
|
|
|
if RELEASE_ENV == "prod":
|
|
|
|
set_option(
|
|
|
|
"WEBAUTHN_ORIGIN",
|
|
|
|
[
|
|
|
|
"https://peeringdb.com",
|
|
|
|
"https://www.peeringdb.com",
|
|
|
|
"https://auth.peeringdb.com",
|
|
|
|
],
|
|
|
|
)
|
|
|
|
else:
|
|
|
|
set_option("WEBAUTHN_ORIGIN", [BASE_URL.rstrip("/")])
|
|
|
|
|
2022-01-11 08:56:47 -06:00
|
|
|
|
|
|
|
# collect webauthn device attestation
|
|
|
|
set_option("WEBAUTHN_ATTESTATION", "none")
|
|
|
|
|
2023-06-20 03:26:06 +03:00
|
|
|
|
2021-07-07 17:57:04 -05:00
|
|
|
# haystack
|
|
|
|
|
2022-01-12 12:33:32 -06:00
|
|
|
set_option("WHOOSH_INDEX_PATH", os.path.join(API_CACHE_ROOT, "whoosh-index"))
|
2021-07-07 17:57:04 -05:00
|
|
|
set_option("WHOOSH_STORAGE", "file")
|
|
|
|
HAYSTACK_CONNECTIONS = {
|
|
|
|
"default": {
|
|
|
|
"ENGINE": "haystack.backends.whoosh_backend.WhooshEngine",
|
|
|
|
"PATH": WHOOSH_INDEX_PATH,
|
|
|
|
"STORAGE": WHOOSH_STORAGE,
|
|
|
|
"BATCH_SIZE": 40000,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
2023-06-20 03:26:06 +03:00
|
|
|
|
2021-07-07 17:57:04 -05:00
|
|
|
set_option("HAYSTACK_ITERATOR_LOAD_PER_QUERY", 20000)
|
|
|
|
set_option("HAYSTACK_LIMIT_TO_REGISTERED_MODELS", False)
|
2020-04-14 10:45:36 -05:00
|
|
|
|
|
|
|
# add user defined iso code for Kosovo
|
|
|
|
COUNTRIES_OVERRIDE = {
|
|
|
|
"XK": _("Kosovo"),
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# Which client config versions we support
|
|
|
|
set_option(
|
|
|
|
"CLIENT_COMPAT",
|
|
|
|
{
|
2020-09-29 18:07:56 +00:00
|
|
|
"client": {
|
|
|
|
"min": (0, 6),
|
|
|
|
"max": (255, 0),
|
|
|
|
},
|
|
|
|
"backends": {
|
|
|
|
"django_peeringdb": {
|
2020-11-04 00:26:15 +00:00
|
|
|
"min": (2, 3, 0, 1),
|
2020-09-29 18:07:56 +00:00
|
|
|
"max": (255, 0),
|
|
|
|
},
|
|
|
|
},
|
2020-04-14 10:45:36 -05:00
|
|
|
},
|
|
|
|
)
|
|
|
|
|
|
|
|
set_option("IXF_POSTMORTEM_LIMIT", 250)
|
|
|
|
|
2020-07-15 02:07:01 -05:00
|
|
|
# when encountering problems where an exchange's ix-f feed
|
|
|
|
# becomes unavilable / unparsable this setting controls
|
|
|
|
# the interval in which we communicate the issue to them (hours)
|
2020-11-19 13:11:11 -08:00
|
|
|
set_option("IXF_PARSE_ERROR_NOTIFICATION_PERIOD", 360)
|
2020-07-15 02:07:01 -05:00
|
|
|
|
|
|
|
# toggle the creation of DeskPRO tickets from ix-f importer
|
|
|
|
# conflicts
|
|
|
|
set_option("IXF_TICKET_ON_CONFLICT", True)
|
|
|
|
|
2020-07-26 23:36:27 -05:00
|
|
|
# send the ix-f importer generated tickets to deskpro
|
|
|
|
set_option("IXF_SEND_TICKETS", False)
|
|
|
|
|
2020-07-15 02:07:01 -05:00
|
|
|
# toggle the notification of exchanges via email
|
|
|
|
# for ix-f importer conflicts
|
|
|
|
set_option("IXF_NOTIFY_IX_ON_CONFLICT", False)
|
|
|
|
|
|
|
|
# toggle the notification of networks via email
|
|
|
|
# for ix-f importer conflicts
|
|
|
|
set_option("IXF_NOTIFY_NET_ON_CONFLICT", False)
|
|
|
|
|
2020-07-26 23:36:27 -05:00
|
|
|
# number of days of a conflict being unresolved before
|
|
|
|
# deskpro ticket is created
|
|
|
|
set_option("IXF_IMPORTER_DAYS_UNTIL_TICKET", 6)
|
|
|
|
|
2023-03-13 20:22:22 +02:00
|
|
|
# number of days until bad NetworkIXLan data is deleted
|
|
|
|
# regardless of ixf-automation status on the network (#1271)
|
|
|
|
set_option("IXF_REMOVE_STALE_NETIXLAN_PERIOD", 90)
|
|
|
|
|
2023-03-20 14:34:56 +02:00
|
|
|
# number of notifications required to the network before
|
|
|
|
# stale removal period is started (#1271)
|
|
|
|
set_option("IXF_REMOVE_STALE_NETIXLAN_NOTIFY_COUNT", 3)
|
|
|
|
|
|
|
|
# number of days between repeated notification of stale
|
|
|
|
# #netixlan data (#1271)
|
|
|
|
set_option("IXF_REMOVE_STALE_NETIXLAN_NOTIFY_PERIOD", 30)
|
|
|
|
|
|
|
|
# on / off toggle for automatic stale netixlan removal
|
|
|
|
# through ix-f (#1271)
|
2023-08-15 21:40:18 +03:00
|
|
|
#
|
|
|
|
# default was changed to False as part of #1360
|
|
|
|
set_option("IXF_REMOVE_STALE_NETIXLAN", False)
|
2023-03-20 14:34:56 +02:00
|
|
|
|
2022-05-10 16:56:30 +03:00
|
|
|
# clean up data change notification queue by discarding
|
|
|
|
# entries older than this (7 days)
|
|
|
|
set_option("DATA_CHANGE_NOTIFY_MAX_AGE", 86400 * 7)
|
|
|
|
|
|
|
|
# data change emails will only be sent if this True
|
|
|
|
set_option("DATA_CHANGE_SEND_EMAILS", False)
|
|
|
|
|
2020-07-15 02:07:01 -05:00
|
|
|
|
|
|
|
# when a user tries to delete a protected object, a deskpro
|
|
|
|
# ticket is dispatched. This setting throttles repeat
|
|
|
|
# updates for the same object (hours)
|
|
|
|
#
|
|
|
|
# deskpro will sort messages with the same subject into
|
|
|
|
# the same ticket, so this is mostly to avoid ticket spam
|
|
|
|
# from users repeat-clicking the delete button
|
|
|
|
set_option("PROTECTED_OBJECT_NOTIFICATION_PERIOD", 1)
|
|
|
|
|
2020-04-14 10:45:36 -05:00
|
|
|
set_option("MAINTENANCE_MODE_LOCKFILE", "maintenance.lock")
|
|
|
|
|
|
|
|
# django_peeringdb settings
|
|
|
|
PEERINGDB_ABSTRACT_ONLY = True
|
|
|
|
|
|
|
|
# In a beta environment that gets sync'd from production this
|
|
|
|
# flag allows you to enable / disable showing of next sync date in
|
|
|
|
# the beta notification banner
|
|
|
|
set_option("SHOW_AUTO_PROD_SYNC_WARNING", False)
|
|
|
|
|
|
|
|
# all suggested entities will be created under this org
|
|
|
|
set_option("SUGGEST_ENTITY_ORG", 20525)
|
2023-03-13 19:58:49 -05:00
|
|
|
set_option("DEFAULT_SELF_ORG", 25554)
|
|
|
|
set_option("DEFAULT_SELF_NET", 666)
|
|
|
|
set_option("DEFAULT_SELF_IX", 4095)
|
|
|
|
set_option("DEFAULT_SELF_FAC", 13346)
|
|
|
|
set_option("DEFAULT_SELF_CARRIER", 66)
|
|
|
|
set_option("DEFAULT_SELF_CAMPUS", 25)
|
2023-02-15 09:55:01 +02:00
|
|
|
set_option("CAMPUS_MAX_DISTANCE", 50)
|
2020-04-14 10:45:36 -05:00
|
|
|
|
|
|
|
set_option("TUTORIAL_MODE", False)
|
|
|
|
|
|
|
|
#'guest' user group
|
|
|
|
GUEST_GROUP_ID = 1
|
2021-01-13 20:35:07 +00:00
|
|
|
set_option("GRAINY_ANONYMOUS_GROUP", "Guest")
|
2020-04-14 10:45:36 -05:00
|
|
|
|
|
|
|
#'user' user group
|
|
|
|
USER_GROUP_ID = 2
|
|
|
|
|
|
|
|
CSRF_FAILURE_VIEW = "peeringdb_server.views.view_http_error_csrf"
|
|
|
|
|
|
|
|
RECAPTCHA_VERIFY_URL = "https://www.google.com/recaptcha/api/siteverify"
|
|
|
|
|
2021-10-12 11:05:25 -05:00
|
|
|
# Organization logo limitations for public users
|
|
|
|
# These limits dont necessarily apply for logos submitted through
|
|
|
|
# /cp (django-admin)
|
|
|
|
|
|
|
|
set_option("ORG_LOGO_ALLOWED_FILE_TYPE", ".jpg,.jpeg,.png")
|
|
|
|
|
|
|
|
# max file size for public organization logo uploads (bytes)
|
|
|
|
set_option("ORG_LOGO_MAX_SIZE", 50 * 1024)
|
|
|
|
|
|
|
|
# max rendering height for the organization logo in net / org / fac / ix views
|
|
|
|
# does NOT affect sponsorship logo rendering (pixels)
|
|
|
|
set_option("ORG_LOGO_MAX_VIEW_HEIGHT", 75)
|
2020-04-14 10:45:36 -05:00
|
|
|
|
2020-09-29 18:07:56 +00:00
|
|
|
# Set countries that don't use zipcodes
|
|
|
|
set_option("NON_ZIPCODE_COUNTRIES", non_zipcode_countries())
|
|
|
|
|
2020-04-14 10:45:36 -05:00
|
|
|
## Locale
|
|
|
|
|
|
|
|
LANGUAGE_CODE = "en-us"
|
2023-03-13 14:22:08 -04:00
|
|
|
LANGUAGE_COOKIE_AGE = 31557600 # one year
|
2020-04-14 10:45:36 -05:00
|
|
|
USE_I18N = True
|
|
|
|
USE_L10N = True
|
|
|
|
|
|
|
|
LOCALE_PATHS = (os.path.join(BASE_DIR, "locale"),)
|
|
|
|
|
|
|
|
LANGUAGES = [
|
|
|
|
# ("ar", _("Arabic")),
|
|
|
|
("cs-cz", _("Czech")),
|
|
|
|
("de-de", _("German")),
|
|
|
|
("el-gr", _("Greek")),
|
|
|
|
("en", _("English")),
|
|
|
|
("es-es", _("Spanish")),
|
|
|
|
("fr-fr", _("French")),
|
|
|
|
("it", _("Italian")),
|
|
|
|
("ja-jp", _("Japanese")),
|
|
|
|
# ("ko", _("Korean")),
|
2020-05-29 09:11:02 -07:00
|
|
|
("oc", _("Occitan")),
|
2020-04-14 10:45:36 -05:00
|
|
|
("pt", _("Portuguese")),
|
|
|
|
("ro-ro", _("Romanian")),
|
|
|
|
("ru-ru", _("Russian")),
|
|
|
|
("zh-cn", _("Chinese (Simplified)")),
|
|
|
|
("zh-tw", _("Chinese (Traditional)")),
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
|
# enable all languages available in the locale directory
|
|
|
|
set_option("ENABLE_ALL_LANGUAGES", False)
|
|
|
|
|
|
|
|
if ENABLE_ALL_LANGUAGES:
|
|
|
|
language_dict = dict(LANGUAGES)
|
|
|
|
for locale_path in LOCALE_PATHS:
|
|
|
|
for name in os.listdir(locale_path):
|
|
|
|
path = os.path.join(locale_path, name)
|
|
|
|
if not os.path.isdir(os.path.join(path, "LC_MESSAGES")):
|
|
|
|
continue
|
|
|
|
code = name.replace("_", "-").lower()
|
|
|
|
if code not in language_dict:
|
|
|
|
name = _(get_locale_name(code))
|
|
|
|
language_dict[code] = name
|
|
|
|
|
|
|
|
LANGUAGES = sorted(language_dict.items())
|
|
|
|
|
2022-09-12 09:34:19 -04:00
|
|
|
EXTRA_LANG_INFO = {
|
|
|
|
"oc": {
|
|
|
|
"bidi": False,
|
|
|
|
"code": "oc",
|
|
|
|
"name": "Occitan",
|
|
|
|
"name_local": "occitan",
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
# Add custom languages not provided by Django
|
|
|
|
LANG_INFO = dict(django.conf.locale.LANG_INFO, **EXTRA_LANG_INFO)
|
|
|
|
django.conf.locale.LANG_INFO = LANG_INFO
|
|
|
|
|
2021-10-12 11:05:25 -05:00
|
|
|
|
2020-04-14 10:45:36 -05:00
|
|
|
# dynamic config starts here
|
|
|
|
|
2020-04-14 21:16:05 +00:00
|
|
|
API_DOC_INCLUDES = {}
|
|
|
|
API_DOC_PATH = os.path.join(BASE_DIR, "docs", "api")
|
|
|
|
for _, _, files in os.walk(API_DOC_PATH):
|
2020-09-29 18:07:56 +00:00
|
|
|
for file in files:
|
|
|
|
base, ext = os.path.splitext(file)
|
|
|
|
if ext == ".md":
|
|
|
|
API_DOC_INCLUDES[base] = os.path.join(API_DOC_PATH, file)
|
2020-04-14 10:45:36 -05:00
|
|
|
|
|
|
|
|
2020-12-03 19:10:02 +00:00
|
|
|
set_option("MAIL_DEBUG", DEBUG)
|
2020-09-29 18:07:56 +00:00
|
|
|
|
|
|
|
# Setting for automated resending of failed ixf import emails
|
2020-09-30 01:13:38 +00:00
|
|
|
set_option("IXF_RESEND_FAILED_EMAILS", False)
|
2020-09-29 18:07:56 +00:00
|
|
|
|
2021-11-09 09:47:38 -06:00
|
|
|
# Set value for IX-F fetch timeout
|
|
|
|
set_option("IXF_FETCH_TIMEOUT", 30)
|
|
|
|
|
|
|
|
# Setting for number of days before deleting childless Organizations
|
2022-01-11 08:56:47 -06:00
|
|
|
set_option("ORG_CHILDLESS_DELETE_DURATION", 90)
|
2021-11-09 09:47:38 -06:00
|
|
|
|
|
|
|
# Grace period before an organization is processed for childless cleanup
|
|
|
|
# n days after creation
|
|
|
|
set_option("ORG_CHILDLESS_GRACE_DURATION", 1)
|
|
|
|
|
2022-09-12 16:29:28 +03:00
|
|
|
# Delete orphaned user accounts after n days
|
|
|
|
set_option("DELETE_ORPHANED_USER_DAYS", 90)
|
|
|
|
|
|
|
|
# Notify orphaned users n days before deletion
|
|
|
|
set_option("NOTIFY_ORPHANED_USER_DAYS", 30)
|
|
|
|
|
2023-07-11 16:20:46 +03:00
|
|
|
# Grace period before a newly created user can be flagged for deletion
|
2022-09-12 16:29:28 +03:00
|
|
|
# This is so users have some time to affiliate naturally. (days)
|
|
|
|
set_option("MIN_AGE_ORPHANED_USER_DAYS", 14)
|
|
|
|
|
2023-07-11 16:20:46 +03:00
|
|
|
# Notification period to notify organizations of users missing 2FA (days)
|
|
|
|
set_option("NOTIFY_MISSING_2FA_DAYS", 30)
|
|
|
|
|
2022-02-08 13:14:27 -06:00
|
|
|
# pdb_validate_data cache timeout default
|
|
|
|
set_option("PDB_VALIDATE_DATA_CACHE_TIMEOUT", 3600)
|
|
|
|
|
2022-11-08 19:25:32 +02:00
|
|
|
# cache global stats (footer statistics) for N seconds
|
|
|
|
set_option("GLOBAL_STATS_CACHE_DURATION", 900)
|
|
|
|
|
2023-01-18 18:32:46 +02:00
|
|
|
# cache settings for optimal CDN use
|
|
|
|
|
|
|
|
# static Pages - pages that only update through release deployment (seconds)
|
|
|
|
set_option("CACHE_CONTROL_STATIC_PAGE", 15 * 60)
|
|
|
|
|
|
|
|
# dynamic pages - entity views
|
|
|
|
set_option("CACHE_CONTROL_DYNAMIC_PAGE", 10)
|
|
|
|
|
|
|
|
# api cache responses (seconds)
|
|
|
|
set_option("CACHE_CONTROL_API_CACHE", 15 * 60)
|
|
|
|
|
|
|
|
# api responses (seconds)
|
|
|
|
set_option("CACHE_CONTROL_API", 10)
|
|
|
|
|
2022-03-08 09:27:45 -04:00
|
|
|
if RELEASE_ENV == "prod":
|
|
|
|
set_option("PDB_PREPEND_WWW", True)
|
|
|
|
else:
|
|
|
|
set_option("PDB_PREPEND_WWW", False)
|
|
|
|
|
2020-04-14 10:45:36 -05:00
|
|
|
TEMPLATES[0]["OPTIONS"]["debug"] = DEBUG
|
|
|
|
|
2022-04-12 16:39:19 -04:00
|
|
|
# set custom throttling message
|
|
|
|
set_option(
|
|
|
|
"API_THROTTLE_RATE_ANON_MSG", "Request was throttled. Expected available in {time}."
|
|
|
|
)
|
|
|
|
set_option(
|
|
|
|
"API_THROTTLE_RATE_USER_MSG", "Request was throttled. Expected available in {time}."
|
|
|
|
)
|
2021-11-09 09:47:38 -06:00
|
|
|
|
2022-07-15 21:47:59 +03:00
|
|
|
set_from_env(
|
|
|
|
"RIR_ALLOCATION_DATA_PATH", os.path.join(API_CACHE_ROOT, "rdap-rir-status")
|
|
|
|
)
|
|
|
|
|
|
|
|
set_option("RIR_ALLOCATION_DATA_CACHE_DAYS", 1)
|
|
|
|
|
2020-04-14 10:45:36 -05:00
|
|
|
|
|
|
|
if TUTORIAL_MODE:
|
|
|
|
EMAIL_SUBJECT_PREFIX = "[PDB TUTORIAL] "
|
|
|
|
DISABLE_VERIFICATION_QUEUE_EMAILS = True
|
|
|
|
DISABLE_VERIFICATION_QUEUE = True
|
|
|
|
AUTO_APPROVE_AFFILIATION = True
|
|
|
|
AUTO_VERIFY_USERS = True
|
|
|
|
else:
|
2020-09-30 01:13:38 +00:00
|
|
|
EMAIL_SUBJECT_PREFIX = f"[{RELEASE_ENV}] "
|
2020-04-14 10:45:36 -05:00
|
|
|
|
2022-06-15 05:23:01 -07:00
|
|
|
CSRF_USE_SESSIONS = True
|
|
|
|
|
2023-06-20 03:26:06 +03:00
|
|
|
set_option("CSRF_TRUSTED_ORIGINS", WEBAUTHN_ORIGIN)
|
|
|
|
|
2022-09-12 16:29:28 +03:00
|
|
|
# A toggle for the periodic re-authentication process propagated
|
|
|
|
# by organizations (#736)
|
|
|
|
set_option("PERIODIC_REAUTH_ENABLED", True)
|
|
|
|
|
|
|
|
# Maximum amount of email addresses allowed per user
|
|
|
|
set_option("USER_MAX_EMAIL_ADDRESSES", 5)
|
|
|
|
|
2023-04-12 00:04:36 +03:00
|
|
|
# Authentication settings to use when syncing via pdb_load
|
|
|
|
set_option("PEERINGDB_SYNC_USERNAME", "")
|
|
|
|
set_option("PEERINGDB_SYNC_PASSWORD", "")
|
|
|
|
|
|
|
|
# If the api key is specified it will be used over the username and password
|
|
|
|
set_option("PEERINGDB_SYNC_API_KEY", "")
|
|
|
|
|
2023-07-11 16:20:46 +03:00
|
|
|
# peeringdb sync cache
|
|
|
|
set_option("PEERINGDB_SYNC_CACHE_URL", "https://cache.peeringdb.com")
|
|
|
|
set_option("PEERINGDB_SYNC_CACHE_DIR", os.path.join(BASE_DIR, "sync-cache"))
|
|
|
|
|
2020-09-30 01:13:38 +00:00
|
|
|
print_debug(f"loaded settings for PeeringDB {PEERINGDB_VERSION} (DEBUG: {DEBUG})")
|