| 
									
										
										
										
											2020-04-14 10:45:36 -05:00
										 |  |  | # Django settings | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import os | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import django.conf.global_settings | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | _DEFAULT_ARG = object() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def print_debug(*args, **kwargs): | 
					
						
							|  |  |  |     if DEBUG: | 
					
						
							|  |  |  |         print(*args, **kwargs) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def get_locale_name(code): | 
					
						
							|  |  |  |     """ Gets the readble name for a locale code. """ | 
					
						
							|  |  |  |     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) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def set_default(name, value): | 
					
						
							|  |  |  |     """ Sets the default value for the option if it's not already set. """ | 
					
						
							|  |  |  |     if name not in globals(): | 
					
						
							|  |  |  |         globals()[name] = value | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def set_from_env(name, default=_DEFAULT_ARG): | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     Sets a global variable from a environment variable of the same name. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     This is useful to leave the option unset and use Django's default (which may change). | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     if default is _DEFAULT_ARG and name not in os.environ: | 
					
						
							|  |  |  |         return | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     globals()[name] = os.environ.get(name, default) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def set_option(name, value): | 
					
						
							| 
									
										
										
										
											2020-04-14 21:29:02 +00:00
										 |  |  |     """ Sets an 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: | 
					
						
							|  |  |  |         globals()[name] = os.environ.get(name) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if name not in globals(): | 
					
						
							|  |  |  |         globals()[name] = value | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def set_bool(name, value): | 
					
						
							|  |  |  |     """ Sets and option, first checking for env vars, then checking for value already set, then going to the default value if passed. """ | 
					
						
							|  |  |  |     if name in os.environ: | 
					
						
							|  |  |  |         envval = os.environ.get(name).lower() | 
					
						
							|  |  |  |         if envval in ["1", "true", "y", "yes"]: | 
					
						
							|  |  |  |             globals()[name] = True | 
					
						
							|  |  |  |         elif envval in ["0", "false", "n", "no"]: | 
					
						
							|  |  |  |             globals()[name] = False | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             raise ValueError( | 
					
						
							|  |  |  |                 "{} is a boolean, cannot match '{}'".format(name, os.environ[name]) | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if name not in globals(): | 
					
						
							|  |  |  |         globals()[name] = value | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def try_include(filename): | 
					
						
							|  |  |  |     """ Tries to include another file from the settings directory. """ | 
					
						
							|  |  |  |     print_debug("including {} {}".format(filename, RELEASE_ENV)) | 
					
						
							|  |  |  |     try: | 
					
						
							|  |  |  |         with open(filename) as f: | 
					
						
							|  |  |  |             exec(compile(f.read(), filename, "exec"), globals()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         print_debug("loaded additional settings file '{}'".format(filename)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     except FileNotFoundError: | 
					
						
							|  |  |  |         print_debug( | 
					
						
							|  |  |  |             "additional settings file '{}' was not found, skipping".format(filename) | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |         pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def read_file(name): | 
					
						
							|  |  |  |     with open(name) as fh: | 
					
						
							|  |  |  |         return fh.read() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | _ = lambda s: s | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | BASE_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..")) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # 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 | 
					
						
							|  |  |  | env_file = os.path.join(os.path.dirname(__file__), "{}.py".format(RELEASE_ENV)) | 
					
						
							|  |  |  | try_include(env_file) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | print_debug("Release env is '{}'".format(RELEASE_ENV)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # set version, default from /srv/www.peeringdb.com/etc/VERSION | 
					
						
							|  |  |  | set_option( | 
					
						
							|  |  |  |     "PEERINGDB_VERSION", read_file(os.path.join(BASE_DIR, "etc/VERSION")).strip() | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # Contact email, from address, support email | 
					
						
							|  |  |  | set_from_env("SERVER_EMAIL") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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", "") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # Keys | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # Limits | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | API_THROTTLE_ENABLED = True | 
					
						
							|  |  |  | API_THROTTLE_RATE_ANON = "100/second" | 
					
						
							|  |  |  | API_THROTTLE_RATE_USER = "100/second" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # maximum value to allow in network.info_prefixes4 | 
					
						
							| 
									
										
										
										
											2020-04-19 11:40:34 -05:00
										 |  |  | set_option("DATA_QUALITY_MAX_PREFIX_V4_LIMIT", 1000000) | 
					
						
							| 
									
										
										
										
											2020-04-14 10:45:36 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | # maximum value to allow in network.info_prefixes6 | 
					
						
							| 
									
										
										
										
											2020-04-19 11:40:34 -05:00
										 |  |  | set_option("DATA_QUALITY_MAX_PREFIX_V6_LIMIT", 100000) | 
					
						
							| 
									
										
										
										
											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-04-14 10:45:36 -05:00
										 |  |  | 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", | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-01 11:08:12 +00:00
										 |  |  | # maximum number of affiliation requests a user can have pending | 
					
						
							|  |  |  | MAX_USER_AFFILIATION_REQUESTS = 5 | 
					
						
							| 
									
										
										
										
											2020-04-14 10:45:36 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | # Django config | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ALLOWED_HOSTS = ["*"] | 
					
						
							|  |  |  | SITE_ID = 1 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | TIME_ZONE = "UTC" | 
					
						
							|  |  |  | USE_TZ = True | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ADMINS = ("Support", SERVER_EMAIL) | 
					
						
							|  |  |  | MANAGERS = ADMINS | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | MEDIA_ROOT = os.path.abspath(os.path.join(BASE_DIR, "media")) | 
					
						
							|  |  |  | MEDIA_URL = "/m/{}/".format(PEERINGDB_VERSION) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | STATIC_ROOT = os.path.abspath(os.path.join(BASE_DIR, "static")) | 
					
						
							|  |  |  | STATIC_URL = "/s/{}/".format(PEERINGDB_VERSION) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | CACHES = { | 
					
						
							|  |  |  |     "default": { | 
					
						
							|  |  |  |         "BACKEND": "django.core.cache.backends.db.DatabaseCache", | 
					
						
							|  |  |  |         "LOCATION": "django_cache", | 
					
						
							|  |  |  |         "OPTIONS": { | 
					
						
							|  |  |  |             # maximum number of entries in the cache | 
					
						
							|  |  |  |             "MAX_ENTRIES": 5000, | 
					
						
							|  |  |  |             # once max entries are reach delete 500 of the oldest entries | 
					
						
							|  |  |  |             "CULL_FREQUENCY": 10, | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | DATABASES = { | 
					
						
							|  |  |  |     "default": { | 
					
						
							|  |  |  |         "ENGINE": "django.db.backends.{}".format(DATABASE_ENGINE), | 
					
						
							|  |  |  |         "HOST": DATABASE_HOST, | 
					
						
							|  |  |  |         "PORT": DATABASE_PORT, | 
					
						
							|  |  |  |         "NAME": DATABASE_NAME, | 
					
						
							|  |  |  |         "USER": DATABASE_USER, | 
					
						
							|  |  |  |         "PASSWORD": DATABASE_PASSWORD, | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | LOGGING = { | 
					
						
							|  |  |  |     "version": 1, | 
					
						
							|  |  |  |     "disable_existing_loggers": False, | 
					
						
							|  |  |  |     "handlers": { | 
					
						
							|  |  |  |         # Include the default Django email handler for errors | 
					
						
							|  |  |  |         # This is what you'd get without configuring logging at all. | 
					
						
							|  |  |  |         "mail_admins": { | 
					
						
							|  |  |  |             "class": "django.utils.log.AdminEmailHandler", | 
					
						
							|  |  |  |             "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", | 
					
						
							|  |  |  |             "filename": os.path.join(BASE_DIR, "var/log/django.log"), | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |         "console": {"level": "DEBUG", "class": "logging.StreamHandler",}, | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  |     "loggers": { | 
					
						
							|  |  |  |         # Again, default Django configuration to email unhandled exceptions | 
					
						
							|  |  |  |         "django.request": { | 
					
						
							|  |  |  |             "handlers": ["mail_admins"], | 
					
						
							|  |  |  |             "level": "ERROR", | 
					
						
							|  |  |  |             "propagate": True, | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |         # Might as well log any errors anywhere else in Django | 
					
						
							|  |  |  |         "django": { | 
					
						
							|  |  |  |             #            'handlers': ['console', 'logfile'], | 
					
						
							|  |  |  |             #            'level': 'DEBUG', | 
					
						
							|  |  |  |             "handlers": ["logfile"], | 
					
						
							|  |  |  |             "level": "ERROR", | 
					
						
							|  |  |  |             "propagate": False, | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |         # Your own app - this assumes all your logger names start with "myapp." | 
					
						
							|  |  |  |         "": { | 
					
						
							|  |  |  |             "handlers": ["logfile"], | 
					
						
							|  |  |  |             "level": "WARNING",  # Or maybe INFO or DEBUG | 
					
						
							|  |  |  |             "propagate": False, | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | INSTALLED_APPS = [ | 
					
						
							|  |  |  |     "django.contrib.auth", | 
					
						
							|  |  |  |     "django.contrib.contenttypes", | 
					
						
							|  |  |  |     "django.contrib.sessions", | 
					
						
							|  |  |  |     "django.contrib.sites", | 
					
						
							|  |  |  |     "django.contrib.messages", | 
					
						
							|  |  |  |     "django.contrib.staticfiles", | 
					
						
							|  |  |  |     "dal", | 
					
						
							|  |  |  |     "dal_select2", | 
					
						
							|  |  |  |     "grappelli", | 
					
						
							|  |  |  |     "django.contrib.admin", | 
					
						
							|  |  |  |     "allauth", | 
					
						
							|  |  |  |     "allauth.account", | 
					
						
							|  |  |  |     "allauth.socialaccount", | 
					
						
							|  |  |  |     "allauth.socialaccount.providers.google", | 
					
						
							|  |  |  |     "allauth.socialaccount.providers.facebook", | 
					
						
							|  |  |  |     "bootstrap3", | 
					
						
							|  |  |  |     "corsheaders", | 
					
						
							|  |  |  |     "crispy_forms", | 
					
						
							|  |  |  |     "django_countries", | 
					
						
							|  |  |  |     "django_inet", | 
					
						
							|  |  |  |     "django_namespace_perms", | 
					
						
							|  |  |  |     "django_peeringdb", | 
					
						
							|  |  |  |     "django_tables2", | 
					
						
							|  |  |  |     "oauth2_provider", | 
					
						
							|  |  |  |     "peeringdb_server", | 
					
						
							|  |  |  |     "reversion", | 
					
						
							|  |  |  |     "captcha", | 
					
						
							|  |  |  |     "django_handleref", | 
					
						
							|  |  |  | ] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # 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" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | MIDDLEWARE = ( | 
					
						
							|  |  |  |     "django.middleware.common.CommonMiddleware", | 
					
						
							|  |  |  |     "django.contrib.sessions.middleware.SessionMiddleware", | 
					
						
							|  |  |  |     "django.middleware.locale.LocaleMiddleware", | 
					
						
							|  |  |  |     "django.middleware.csrf.CsrfViewMiddleware", | 
					
						
							|  |  |  |     "django.contrib.auth.middleware.AuthenticationMiddleware", | 
					
						
							|  |  |  |     "django.contrib.messages.middleware.MessageMiddleware", | 
					
						
							|  |  |  |     "django.middleware.clickjacking.XFrameOptionsMiddleware", | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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" | 
					
						
							|  |  |  | CONN_MAX_AGE = 3600 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # 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") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | set_from_env("SESSION_COOKIE_DOMAIN") | 
					
						
							|  |  |  | set_from_env("SESSION_COOKIE_SECURE") | 
					
						
							|  |  |  | set_option("SECURE_PROXY_SSL_HEADER", ("HTTP_X_FWD_PROTO", "https")) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | DEFAULT_FROM_EMAIL = SERVER_EMAIL | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # 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 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | LOGIN_URL = "/login" | 
					
						
							|  |  |  | LOGIN_REDIRECT_URL = "/" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # App config | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | CRISPY_TEMPLATE_PACK = "bootstrap3" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ## 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 | 
					
						
							|  |  |  | set_option("OAUTH_ENABLED", False) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | AUTHENTICATION_BACKENDS += ( | 
					
						
							|  |  |  |     # for OAuth provider | 
					
						
							|  |  |  |     "oauth2_provider.backends.OAuth2Backend", | 
					
						
							|  |  |  |     # for OAuth against external sources | 
					
						
							|  |  |  |     "allauth.account.auth_backends.AuthenticationBackend", | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | MIDDLEWARE += ( | 
					
						
							|  |  |  |     "peeringdb_server.maintenance.Middleware", | 
					
						
							|  |  |  |     "oauth2_provider.middleware.OAuth2TokenMiddleware", | 
					
						
							|  |  |  |     "corsheaders.middleware.CorsMiddleware", | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | OAUTH2_PROVIDER = { | 
					
						
							|  |  |  |     "SCOPES": { | 
					
						
							|  |  |  |         "profile": "user profile", | 
					
						
							|  |  |  |         "email": "email address", | 
					
						
							|  |  |  |         "networks": "list of user networks and permissions", | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  |     "ALLOWED_REDIRECT_URI_SCHEMES": ["https"], | 
					
						
							|  |  |  |     "REQUEST_APPROVAL_PROMPT": "auto", | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ## NSP | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | NSP_MODE = "crud" | 
					
						
							|  |  |  | AUTHENTICATION_BACKENDS += ("django_namespace_perms.auth.backends.NSPBackend",) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ## Django Rest Framework | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | INSTALLED_APPS += ("rest_framework", "rest_framework_swagger") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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. | 
					
						
							|  |  |  |     # Handle rest of permissioning via django-namespace-perms | 
					
						
							|  |  |  |     "DEFAULT_PERMISSION_CLASSES": [ | 
					
						
							|  |  |  |         "rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly", | 
					
						
							|  |  |  |         "django_namespace_perms.rest.BasePermission", | 
					
						
							|  |  |  |     ], | 
					
						
							|  |  |  |     "DEFAULT_RENDERER_CLASSES": ("peeringdb_server.renderers.MetaJSONRenderer",), | 
					
						
							|  |  |  |     "DEFAULT_SCHEMA_CLASS": "rest_framework.schemas.coreapi.AutoSchema", | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | if API_THROTTLE_ENABLED: | 
					
						
							|  |  |  |     REST_FRAMEWORK.update( | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             "DEFAULT_THROTTLE_CLASSES": ( | 
					
						
							|  |  |  |                 "rest_framework.throttling.AnonRateThrottle", | 
					
						
							|  |  |  |                 "rest_framework.throttling.UserRateThrottle", | 
					
						
							|  |  |  |             ), | 
					
						
							|  |  |  |             "DEFAULT_THROTTLE_RATES": { | 
					
						
							|  |  |  |                 "anon": API_THROTTLE_RATE_ANON, | 
					
						
							|  |  |  |                 "user": API_THROTTLE_RATE_USER, | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ## PeeringDB | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # TODO for tests | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # from address for sponsorship emails | 
					
						
							|  |  |  | set_option("SPONSORSHIPS_EMAIL", SERVER_EMAIL) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | set_option("API_URL", "https://peeringdb.com/api") | 
					
						
							|  |  |  | API_DEPTH_ROW_LIMIT = 250 | 
					
						
							|  |  |  | API_CACHE_ENABLED = True | 
					
						
							|  |  |  | API_CACHE_ROOT = os.path.join(BASE_DIR, "api-cache") | 
					
						
							|  |  |  | API_CACHE_LOG = os.path.join(BASE_DIR, "var/log/api-cache.log") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # add user defined iso code for Kosovo | 
					
						
							|  |  |  | COUNTRIES_OVERRIDE = { | 
					
						
							|  |  |  |     "XK": _("Kosovo"), | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # Which client config versions we support | 
					
						
							|  |  |  | set_option( | 
					
						
							|  |  |  |     "CLIENT_COMPAT", | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         "client": {"min": "0,6", "max": "255,0",}, | 
					
						
							|  |  |  |         "backends": {"django_peeringdb": {"min": "0,6", "max": "255,0",},}, | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | set_option("IXF_POSTMORTEM_LIMIT", 250) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # TODO -- let's make this 1 | 
					
						
							|  |  |  | # TODO -- why are the ids different for prod, beta, tutor, etc? | 
					
						
							|  |  |  | # all suggested entities will be created under this org | 
					
						
							|  |  |  | set_option("SUGGEST_ENTITY_ORG", 20525) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | set_option("TUTORIAL_MODE", False) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #'guest' user group | 
					
						
							|  |  |  | GUEST_GROUP_ID = 1 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #'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" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ## Locale | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | LANGUAGE_CODE = "en-us" | 
					
						
							|  |  |  | 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")), | 
					
						
							|  |  |  |     ("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()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # 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): | 
					
						
							|  |  |  |   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
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | MAIL_DEBUG = DEBUG | 
					
						
							|  |  |  | TEMPLATES[0]["OPTIONS"]["debug"] = DEBUG | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | if DEBUG: | 
					
						
							|  |  |  |     # make all loggers use the console. | 
					
						
							|  |  |  |     for logger in LOGGING["loggers"]: | 
					
						
							|  |  |  |         LOGGING["loggers"][logger]["handlers"] = ["console"] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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: | 
					
						
							|  |  |  |     EMAIL_SUBJECT_PREFIX = "[{}] ".format(RELEASE_ENV) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | print_debug( | 
					
						
							|  |  |  |     "loaded settings for PeeringDB {} (DEBUG: {})".format(PEERINGDB_VERSION, DEBUG) | 
					
						
							|  |  |  | ) |