mirror of https://github.com/interlegis/sapl.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
394 lines
12 KiB
394 lines
12 KiB
"""
|
|
Django settings for sapl project.
|
|
|
|
Generated by 'django-admin startproject' using Django 1.8.2.
|
|
|
|
For more information on this file, see
|
|
https://docs.djangoproject.com/en/1.8/topics/settings/
|
|
|
|
For the full list of settings and their values, see
|
|
https://docs.djangoproject.com/en/1.8/ref/settings/
|
|
|
|
Quick-start development settings - unsuitable for production
|
|
See https://docs.djangoproject.com/en/1.8/howto/deployment/checklist/
|
|
|
|
"""
|
|
import logging
|
|
import socket
|
|
|
|
from decouple import config
|
|
from dj_database_url import parse as db_url
|
|
from easy_thumbnails.conf import Settings as thumbnail_settings
|
|
from unipath import Path
|
|
|
|
logging.captureWarnings(True)
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
host = socket.gethostbyname_ex(socket.gethostname())[0]
|
|
|
|
BASE_DIR = Path(__file__).ancestor(1)
|
|
PROJECT_DIR = Path(__file__).ancestor(2)
|
|
|
|
DEFAULT_AUTO_FIELD = "django.db.models.AutoField"
|
|
|
|
# SECURITY WARNING: keep the secret key used in production secret!
|
|
SECRET_KEY = config("SECRET_KEY", default="32jk1h412l3kjh421lkj4hlkj234")
|
|
# SECURITY WARNING: don't run with debug turned on in production!
|
|
DEBUG = config("DEBUG", default=False, cast=bool)
|
|
|
|
MESSAGE_STORAGE = "django.contrib.messages.storage.session.SessionStorage"
|
|
|
|
ALLOWED_HOSTS = ["*"]
|
|
|
|
LOGIN_REDIRECT_URL = "/"
|
|
LOGIN_URL = "/login/?next="
|
|
|
|
SAPL_VERSION = "3.1.164-RC1"
|
|
|
|
if DEBUG:
|
|
EMAIL_BACKEND = "django.core.mail.backends.console.EmailBackend"
|
|
else:
|
|
EMAIL_BACKEND = "django.core.mail.backends.smtp.EmailBackend"
|
|
|
|
# SAPL business apps in dependency order
|
|
SAPL_APPS = (
|
|
"sapl.audiencia",
|
|
"sapl.base",
|
|
"sapl.crud",
|
|
"sapl.parlamentares",
|
|
"sapl.comissoes",
|
|
"sapl.materia",
|
|
"sapl.norma",
|
|
"sapl.sessao",
|
|
"sapl.lexml",
|
|
"sapl.painel",
|
|
"sapl.protocoloadm",
|
|
"sapl.redireciona_urls",
|
|
"sapl.compilacao",
|
|
"sapl.api",
|
|
"sapl.rules",
|
|
)
|
|
|
|
INSTALLED_APPS = (
|
|
"django_admin_bootstrapped", # must come before django.contrib.admin
|
|
"django.contrib.admin",
|
|
"django.contrib.auth",
|
|
"django.contrib.contenttypes",
|
|
"django.contrib.sessions",
|
|
"django.contrib.messages",
|
|
"django.contrib.staticfiles",
|
|
"django.forms",
|
|
"django_extensions",
|
|
"crispy_forms",
|
|
"crispy_bootstrap4",
|
|
"waffle",
|
|
"drf_spectacular",
|
|
"rest_framework",
|
|
"rest_framework.authtoken",
|
|
"django_filters",
|
|
"easy_thumbnails",
|
|
"image_cropping",
|
|
"haystack",
|
|
"django.contrib.postgres",
|
|
"webpack_loader",
|
|
"django_prometheus",
|
|
) + SAPL_APPS
|
|
|
|
# FTS = Full Text Search
|
|
# Desabilita a indexação textual até encontramos uma solução para a issue
|
|
# https://github.com/interlegis/sapl/issues/2055
|
|
HAYSTACK_SIGNAL_PROCESSOR = "haystack.signals.BaseSignalProcessor" # Disable auto index
|
|
SEARCH_BACKEND = ""
|
|
SEARCH_URL = ["", ""]
|
|
|
|
# SOLR
|
|
USE_SOLR = config("USE_SOLR", cast=bool, default=False)
|
|
SOLR_URL = config("SOLR_URL", cast=str, default="http://localhost:8983")
|
|
SOLR_COLLECTION = config("SOLR_COLLECTION", cast=str, default="sapl")
|
|
|
|
# FOR HAYSTACK 3.3.1 (Django >= 3)
|
|
# SOLR_USER = config('SOLR_USER', cast=str)
|
|
# SOLR_PASSWORD = config('SOLR_PASSWORD', cast=str)
|
|
|
|
if USE_SOLR:
|
|
HAYSTACK_SIGNAL_PROCESSOR = (
|
|
"haystack.signals.RealtimeSignalProcessor" # enable auto-index
|
|
)
|
|
SEARCH_BACKEND = "haystack.backends.solr_backend.SolrEngine"
|
|
SEARCH_URL = ("URL", "{}/solr/{}".format(SOLR_URL, SOLR_COLLECTION))
|
|
|
|
# BATCH_SIZE: default is 1000 if omitted, avoid Too Large Entity Body errors
|
|
HAYSTACK_CONNECTIONS = {
|
|
"default": {
|
|
"ENGINE": SEARCH_BACKEND,
|
|
SEARCH_URL[0]: SEARCH_URL[1],
|
|
"BATCH_SIZE": 1000,
|
|
"TIMEOUT": 20,
|
|
# 'KWARGS': {
|
|
# 'timeout': 60,
|
|
# 'auth': (SOLR_USER, SOLR_PASSWORD), # <-- for basic auth
|
|
# },
|
|
},
|
|
}
|
|
|
|
MIDDLEWARE = [
|
|
"django_prometheus.middleware.PrometheusBeforeMiddleware",
|
|
"django.contrib.sessions.middleware.SessionMiddleware",
|
|
"django.middleware.locale.LocaleMiddleware",
|
|
"django.middleware.common.CommonMiddleware",
|
|
"sapl.endpoint_restriction_middleware.EndpointRestrictionMiddleware",
|
|
"django.middleware.csrf.CsrfViewMiddleware",
|
|
"django.contrib.auth.middleware.AuthenticationMiddleware",
|
|
"django.contrib.messages.middleware.MessageMiddleware",
|
|
"django.middleware.clickjacking.XFrameOptionsMiddleware",
|
|
"django.middleware.security.SecurityMiddleware",
|
|
"whitenoise.middleware.WhiteNoiseMiddleware",
|
|
"django_prometheus.middleware.PrometheusAfterMiddleware",
|
|
"waffle.middleware.WaffleMiddleware",
|
|
"sapl.middleware.CheckWeakPasswordMiddleware",
|
|
]
|
|
if DEBUG:
|
|
INSTALLED_APPS += ("debug_toolbar",)
|
|
MIDDLEWARE += [
|
|
"debug_toolbar.middleware.DebugToolbarMiddleware",
|
|
]
|
|
INTERNAL_IPS = "127.0.0.1"
|
|
|
|
SITE_URL = config("SITE_URL", cast=str, default="")
|
|
|
|
REST_FRAMEWORK = {
|
|
"UNICODE_JSON": False,
|
|
"DEFAULT_PARSER_CLASSES": (
|
|
"rest_framework.parsers.JSONParser",
|
|
"rest_framework.parsers.MultiPartParser",
|
|
),
|
|
"DEFAULT_RENDERER_CLASSES": ("rest_framework.renderers.JSONRenderer",),
|
|
"DEFAULT_PERMISSION_CLASSES": ("sapl.api.permissions.SaplModelPermissions",),
|
|
"DEFAULT_AUTHENTICATION_CLASSES": (
|
|
"rest_framework.authentication.TokenAuthentication",
|
|
"rest_framework.authentication.SessionAuthentication",
|
|
),
|
|
"DEFAULT_SCHEMA_CLASS": "sapl.api.schema.Schema",
|
|
"DEFAULT_PAGINATION_CLASS": "sapl.api.pagination.StandardPagination",
|
|
"DEFAULT_FILTER_BACKENDS": (
|
|
"rest_framework.filters.SearchFilter",
|
|
"django_filters.rest_framework.DjangoFilterBackend",
|
|
),
|
|
}
|
|
|
|
DRFAUTOAPI = {
|
|
"DEFAULT_SERIALIZER_MODULE": "sapl.api.serializers",
|
|
"DEFAULT_FILTER_MODULE": "sapl.api.forms",
|
|
"GLOBAL_SERIALIZER_MIXIN": "sapl.api.serializers.SaplSerializerMixin",
|
|
"GLOBAL_FILTERSET_MIXIN": "sapl.api.forms.SaplFilterSetMixin",
|
|
}
|
|
|
|
SPECTACULAR_SETTINGS = {
|
|
"TITLE": "Sapl API - docs",
|
|
"DESCRIPTION": "Sapl API - Docs",
|
|
"VERSION": "1.0.0",
|
|
}
|
|
|
|
CACHES = {
|
|
"default": {
|
|
"BACKEND": "django.core.cache.backends.filebased.FileBasedCache",
|
|
"LOCATION": "/var/tmp/django_cache",
|
|
"OPTIONS": {"MAX_ENTRIES": 10000},
|
|
}
|
|
}
|
|
|
|
ROOT_URLCONF = "sapl.urls"
|
|
|
|
FORM_RENDERER = "django.forms.renderers.TemplatesSetting"
|
|
|
|
TEMPLATES = [
|
|
{
|
|
"BACKEND": "django.template.backends.django.DjangoTemplates",
|
|
"DIRS": ["sapl/templates"],
|
|
"APP_DIRS": True,
|
|
"OPTIONS": {
|
|
"context_processors": [
|
|
"django.template.context_processors.debug",
|
|
"django.template.context_processors.request",
|
|
"django.contrib.auth.context_processors.auth",
|
|
"django.template.context_processors.media",
|
|
"django.template.context_processors.static",
|
|
"django.contrib.messages.context_processors.messages",
|
|
"sapl.context_processors.parliament_info",
|
|
"sapl.context_processors.mail_service_configured",
|
|
"sapl.context_processors.google_recaptcha_configured",
|
|
"sapl.context_processors.enable_sapn",
|
|
],
|
|
"debug": DEBUG,
|
|
},
|
|
},
|
|
]
|
|
|
|
WSGI_APPLICATION = "sapl.wsgi.application"
|
|
|
|
# Database
|
|
# https://docs.djangoproject.com/en/1.8/ref/settings/#databases
|
|
|
|
# Parse DATABASE_URL
|
|
# dj-database-url==0.5.0 is the latest compatible with Django 2.2, later versions required Django >= 4
|
|
# but it doesn't support OPTIONS tag, so we need setup_db_tz
|
|
# This should be removed once we are able to upgrade to Django >= 4
|
|
DATABASES = {"default": config("DATABASE_URL", cast=db_url)}
|
|
|
|
|
|
def setup_db_tz():
|
|
### TODO: dj-database-url now supports CONN_MAX_AGE and OPTIONS
|
|
db = DATABASES["default"]
|
|
# Normalize legacy engine alias returned by old dj-database-url
|
|
if db.get("ENGINE") == "django.db.backends.postgresql_psycopg2":
|
|
db["ENGINE"] = "django.db.backends.postgresql"
|
|
|
|
# Force UTC per connection for Postgres (fixes Django’s utc_tzinfo_factory assertion)
|
|
if db.get("ENGINE") == "django.db.backends.postgresql":
|
|
opts = db.setdefault("OPTIONS", {})
|
|
existing = (opts.get("options") or "").strip()
|
|
force_utc = "-c timezone=UTC"
|
|
opts["options"] = f"{existing} {force_utc}".strip() if existing else force_utc
|
|
|
|
# ensure default TCP port if you use HOST; leave sockets alone if HOST is empty
|
|
if db.get("HOST") and not db.get("PORT"):
|
|
db["PORT"] = "5432"
|
|
|
|
# Add connection lifetime
|
|
# in recent dj-database-url versions, replace by config("DATABASE_URL", conn_max_age=300)
|
|
db["CONN_MAX_AGE"] = 300 # keep connections for 5 minutes
|
|
|
|
# Log if DEBUG mode
|
|
if config("DEBUG", default=False, cast=bool):
|
|
logger.debug("DB config: %r", db)
|
|
|
|
|
|
setup_db_tz()
|
|
|
|
IMAGE_CROPPING_JQUERY_URL = None
|
|
THUMBNAIL_PROCESSORS = (
|
|
"image_cropping.thumbnail_processors.crop_corners",
|
|
) + thumbnail_settings.THUMBNAIL_PROCESSORS
|
|
|
|
THUMBNAIL_SOURCE_GENERATORS = ("sapl.utils.pil_image",)
|
|
|
|
# troque no caso de reimplementação da classe User conforme
|
|
# https://docs.djangoproject.com/en/1.9/topics/auth/customizing/#substituting-a-custom-user-model
|
|
AUTH_USER_MODEL = "auth.User"
|
|
|
|
X_FRAME_OPTIONS = "ALLOWALL"
|
|
|
|
EMAIL_HOST = config("EMAIL_HOST", default="localhost")
|
|
EMAIL_PORT = config("EMAIL_PORT", cast=int, default=587)
|
|
EMAIL_HOST_USER = config("EMAIL_HOST_USER", default="")
|
|
EMAIL_HOST_PASSWORD = config("EMAIL_HOST_PASSWORD", default="")
|
|
EMAIL_USE_TLS = config("EMAIL_USE_TLS", cast=bool, default=True)
|
|
EMAIL_SEND_USER = config("EMAIL_SEND_USER", cast=str, default="")
|
|
DEFAULT_FROM_EMAIL = config("DEFAULT_FROM_EMAIL", cast=str, default="")
|
|
SERVER_EMAIL = config("SERVER_EMAIL", cast=str, default="")
|
|
EMAIL_RUNNING = None
|
|
|
|
# Feature Flag
|
|
WAFFLE_FLAG_DEFAULT = False
|
|
WAFFLE_SWITCH_DEFAULT = False
|
|
WAFFLE_CREATE_MISSING_FLAGS = True
|
|
WAFFLE_LOG_MISSING_FLAGS = True
|
|
WAFFLE_CREATE_MISSING_SWITCHES = True
|
|
WAFFLE_LOG_MISSING_SWITCHES = True
|
|
WAFFLE_ENABLE_ADMIN_PAGES = True
|
|
|
|
MAX_DOC_UPLOAD_SIZE = 150 * 1024 * 1024 # 150MB
|
|
MAX_IMAGE_UPLOAD_SIZE = 2 * 1024 * 1024 # 2MB
|
|
DATA_UPLOAD_MAX_MEMORY_SIZE = 10 * 1024 * 1024 # 10MB
|
|
|
|
# Internationalization
|
|
# https://docs.djangoproject.com/en/1.8/topics/i18n/
|
|
LANGUAGE_CODE = "pt-br"
|
|
LANGUAGES = (("pt-br", "Português"),)
|
|
|
|
TIME_ZONE = config("TZ", default="America/Sao_Paulo")
|
|
if not TIME_ZONE:
|
|
raise ValueError(
|
|
"TIMEZONE env variable undefined in .env settings file! Leaving..."
|
|
)
|
|
|
|
USE_I18N = True
|
|
USE_TZ = True
|
|
|
|
# DATE_FORMAT = 'N j, Y'
|
|
DATE_FORMAT = "d/m/Y"
|
|
SHORT_DATE_FORMAT = "d/m/Y"
|
|
DATETIME_FORMAT = "d/m/Y H:i:s"
|
|
SHORT_DATETIME_FORMAT = "d/m/Y H:i"
|
|
DATE_INPUT_FORMATS = ("%d/%m/%Y", "%m-%d-%Y", "%Y-%m-%d")
|
|
|
|
LOCALE_PATHS = ("locale",)
|
|
|
|
WEBPACK_LOADER = {
|
|
"DEFAULT": {
|
|
"CACHE": not DEBUG,
|
|
"BUNDLE_DIR_NAME": "sapl/static/sapl/frontend",
|
|
"STATS_FILE": PROJECT_DIR.child("frontend").child(
|
|
f'{"dev-" if DEBUG else ""}webpack-stats.json'
|
|
),
|
|
"POLL_INTERVAL": 0.1,
|
|
"TIMEOUT": None,
|
|
"IGNORE": [r".+\.hot-update.js", r".+\.map"],
|
|
}
|
|
}
|
|
if DEBUG and not WEBPACK_LOADER["DEFAULT"]["STATS_FILE"].exists():
|
|
WEBPACK_LOADER["DEFAULT"]["STATS_FILE"] = PROJECT_DIR.child("frontend").child(
|
|
f"webpack-stats.json"
|
|
)
|
|
|
|
STATIC_URL = "/static/"
|
|
STATIC_ROOT = PROJECT_DIR.child("collected_static")
|
|
|
|
STATICFILES_DIRS = (BASE_DIR.child("static"),)
|
|
|
|
STATICFILES_FINDERS = (
|
|
"django.contrib.staticfiles.finders.FileSystemFinder",
|
|
"django.contrib.staticfiles.finders.AppDirectoriesFinder",
|
|
)
|
|
|
|
MEDIA_ROOT = PROJECT_DIR.child("media")
|
|
MEDIA_URL = "/media/"
|
|
|
|
FILE_UPLOAD_PERMISSIONS = 0o644
|
|
|
|
DAB_FIELD_RENDERER = "django_admin_bootstrapped.renderers.BootstrapFieldRenderer"
|
|
CRISPY_TEMPLATE_PACK = "bootstrap4"
|
|
CRISPY_ALLOWED_TEMPLATE_PACKS = "bootstrap4"
|
|
CRISPY_FAIL_SILENTLY = False
|
|
|
|
# suprime texto de ajuda default do django-filter
|
|
FILTERS_HELP_TEXT_FILTER = False
|
|
|
|
LOGGING_CONSOLE_VERBOSE = config("LOGGING_CONSOLE_VERBOSE", cast=bool, default=False)
|
|
|
|
LOGGING = {
|
|
"version": 1,
|
|
"disable_existing_loggers": False,
|
|
"handlers": {
|
|
"console": {"class": "logging.StreamHandler"},
|
|
},
|
|
"root": { # everything falls back here
|
|
"handlers": ["console"],
|
|
"level": "DEBUG",
|
|
},
|
|
"loggers": {
|
|
"django.request": { # 500s go here
|
|
"handlers": ["console"],
|
|
"level": "ERROR",
|
|
"propagate": False,
|
|
},
|
|
},
|
|
}
|
|
|
|
PASSWORD_HASHERS = [
|
|
"django.contrib.auth.hashers.PBKDF2PasswordHasher", # default
|
|
"sapl.hashers.ZopeSHA1PasswordHasher",
|
|
]
|
|
|
|
LOGOUT_REDIRECT_URL = "/login"
|
|
|