Coverage for config.py: 97%
71 statements
« prev ^ index » next coverage.py v7.9.1, created at 2025-06-14 23:13 +0000
« prev ^ index » next coverage.py v7.9.1, created at 2025-06-14 23:13 +0000
1# -*- coding: utf-8 -*-
2"""
3Configuration overrides for settings.py
4"""
6import os
7import sys
8from django.urls import reverse_lazy
9from django.utils.translation import gettext_lazy as _
10from django.contrib.messages import constants as message_constants
11from ivatar.settings import BASE_DIR
13from ivatar.settings import MIDDLEWARE
14from ivatar.settings import INSTALLED_APPS
15from ivatar.settings import TEMPLATES
17ADMIN_USERS = []
18ALLOWED_HOSTS = ["*"]
20INSTALLED_APPS.extend(
21 [
22 "django_extensions",
23 "django_openid_auth",
24 "bootstrap4",
25 "anymail",
26 "ivatar",
27 "ivatar.ivataraccount",
28 "ivatar.tools",
29 ]
30)
32MIDDLEWARE.extend(
33 [
34 "django.middleware.locale.LocaleMiddleware",
35 ]
36)
37MIDDLEWARE.insert(
38 0,
39 "ivatar.middleware.MultipleProxyMiddleware",
40)
42AUTHENTICATION_BACKENDS = (
43 # Enable this to allow LDAP authentication.
44 # See INSTALL for more information.
45 # 'django_auth_ldap.backend.LDAPBackend',
46 "django_openid_auth.auth.OpenIDBackend",
47 "ivatar.ivataraccount.auth.FedoraOpenIdConnect",
48 "django.contrib.auth.backends.ModelBackend",
49)
51TEMPLATES[0]["DIRS"].extend(
52 [
53 os.path.join(BASE_DIR, "templates"),
54 ]
55)
56TEMPLATES[0]["OPTIONS"]["context_processors"].append(
57 "ivatar.context_processors.basepage",
58)
60OPENID_CREATE_USERS = True
61OPENID_UPDATE_DETAILS_FROM_SREG = True
62SOCIAL_AUTH_JSONFIELD_ENABLED = True
63# Fedora authentication (OIDC). You need to set these two values to use it.
64SOCIAL_AUTH_FEDORA_KEY = None # Also known as client_id
65SOCIAL_AUTH_FEDORA_SECRET = None # Also known as client_secret
67SITE_NAME = os.environ.get("SITE_NAME", "libravatar")
68IVATAR_VERSION = "1.8.0"
70SCHEMAROOT = "https://www.libravatar.org/schemas/export/0.2"
72SECURE_BASE_URL = os.environ.get(
73 "SECURE_BASE_URL", "https://avatars.linux-kernel.at/avatar/"
74)
75BASE_URL = os.environ.get("BASE_URL", "http://avatars.linux-kernel.at/avatar/")
77LOGIN_REDIRECT_URL = reverse_lazy("profile")
78MAX_LENGTH_EMAIL = 254 # http://stackoverflow.com/questions/386294
80MAX_NUM_PHOTOS = 5
81MAX_NUM_UNCONFIRMED_EMAILS = 5
82MAX_PHOTO_SIZE = 10485760 # in bytes
83MAX_PIXELS = 7000
84AVATAR_MAX_SIZE = 512
85JPEG_QUALITY = 85
87# I'm not 100% sure if single character domains are possible
88# under any tld... so MIN_LENGTH_EMAIL/_URL, might be +1
89MIN_LENGTH_URL = 11 # eg. http://a.io
90MAX_LENGTH_URL = 255 # MySQL can't handle more than that (LP: 1018682)
91MIN_LENGTH_EMAIL = 6 # eg. x@x.xx
92MAX_LENGTH_EMAIL = 254 # http://stackoverflow.com/questions/386294
94BOOTSTRAP4 = {
95 "include_jquery": False,
96 "javascript_in_head": False,
97 "css_url": {
98 "href": "/static/css/bootstrap.min.css",
99 "integrity": "sha384-WskhaSGFgHYWDcbwN70/dfYBj47jz9qbsMId/iRN3ewGhXQFZCSftd1LZCfmhktB",
100 "crossorigin": "anonymous",
101 },
102 "javascript_url": {
103 "url": "/static/js/bootstrap.min.js",
104 "integrity": "",
105 "crossorigin": "anonymous",
106 },
107 "popper_url": {
108 "url": "/static/js/popper.min.js",
109 "integrity": "sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49",
110 "crossorigin": "anonymous",
111 },
112}
114if "EMAIL_BACKEND" in os.environ:
115 EMAIL_BACKEND = os.environ["EMAIL_BACKEND"] # pragma: no cover
116else:
117 if "test" in sys.argv or "collectstatic" in sys.argv:
118 EMAIL_BACKEND = "django.core.mail.backends.locmem.EmailBackend"
119 else:
120 try:
121 ANYMAIL = { # pragma: no cover
122 "MAILGUN_API_KEY": os.environ["IVATAR_MAILGUN_API_KEY"],
123 "MAILGUN_SENDER_DOMAIN": os.environ["IVATAR_MAILGUN_SENDER_DOMAIN"],
124 }
125 EMAIL_BACKEND = "anymail.backends.mailgun.EmailBackend" # pragma: no cover
126 except Exception: # pragma: nocover # pylint: disable=broad-except
127 EMAIL_BACKEND = "django.core.mail.backends.smtp.EmailBackend"
129SERVER_EMAIL = os.environ.get("SERVER_EMAIL", "ivatar@mg.linux-kernel.at")
130DEFAULT_FROM_EMAIL = os.environ.get("DEFAULT_FROM_EMAIL", "ivatar@mg.linux-kernel.at")
132try:
133 from ivatar.settings import DATABASES
134except ImportError: # pragma: no cover
135 DATABASES = [] # pragma: no cover
137if "default" not in DATABASES:
138 DATABASES["default"] = { # pragma: no cover
139 "ENGINE": "django.db.backends.sqlite3",
140 "NAME": os.path.join(BASE_DIR, "db.sqlite3"),
141 }
143if "MYSQL_DATABASE" in os.environ:
144 DATABASES["default"] = { # pragma: no cover
145 "ENGINE": "django.db.backends.mysql",
146 "NAME": os.environ["MYSQL_DATABASE"],
147 "USER": os.environ["MYSQL_USER"],
148 "PASSWORD": os.environ["MYSQL_PASSWORD"],
149 "HOST": "mysql",
150 }
152if "POSTGRESQL_DATABASE" in os.environ:
153 DATABASES["default"] = { # pragma: no cover
154 "ENGINE": "django.db.backends.postgresql",
155 "NAME": os.environ["POSTGRESQL_DATABASE"],
156 "USER": os.environ["POSTGRESQL_USER"],
157 "PASSWORD": os.environ["POSTGRESQL_PASSWORD"],
158 "HOST": "postgresql",
159 }
161# CI/CD config has different naming
162if "POSTGRES_DB" in os.environ:
163 DATABASES["default"] = { # pragma: no cover
164 "ENGINE": "django.db.backends.postgresql",
165 "NAME": os.environ["POSTGRES_DB"],
166 "USER": os.environ["POSTGRES_USER"],
167 "PASSWORD": os.environ["POSTGRES_PASSWORD"],
168 "HOST": os.environ["POSTGRES_HOST"],
169 "TEST": {
170 "NAME": os.environ["POSTGRES_DB"],
171 },
172 }
174SESSION_SERIALIZER = "django.contrib.sessions.serializers.JSONSerializer"
176USE_X_FORWARDED_HOST = True
177ALLOWED_EXTERNAL_OPENID_REDIRECT_DOMAINS = [
178 "avatars.linux-kernel.at",
179 "localhost",
180]
182DEFAULT_AVATAR_SIZE = 80
184LANGUAGES = (
185 ("de", _("Deutsch")),
186 ("en", _("English")),
187 ("ca", _("Català")),
188 ("cs", _("Česky")),
189 ("es", _("Español")),
190 ("eu", _("Basque")),
191 ("fr", _("Français")),
192 ("it", _("Italiano")),
193 ("ja", _("日本語")),
194 ("nl", _("Nederlands")),
195 ("pt", _("Português")),
196 ("ru", _("Русский")),
197 ("sq", _("Shqip")),
198 ("tr", _("Türkçe")),
199 ("uk", _("Українська")),
200)
202MESSAGE_TAGS = {
203 message_constants.DEBUG: "debug",
204 message_constants.INFO: "info",
205 message_constants.SUCCESS: "success",
206 message_constants.WARNING: "warning",
207 message_constants.ERROR: "danger",
208}
210CACHES = {
211 "default": {
212 "BACKEND": "django.core.cache.backends.memcached.PyMemcacheCache",
213 "LOCATION": [
214 "127.0.0.1:11211",
215 ],
216 },
217 "filesystem": {
218 "BACKEND": "django.core.cache.backends.filebased.FileBasedCache",
219 "LOCATION": "/var/tmp/ivatar_cache",
220 "TIMEOUT": 900, # 15 minutes
221 },
222}
224# This is 5 minutes caching for generated/resized images,
225# so the sites don't hit ivatar so much - it's what's set in the HTTP header
226CACHE_IMAGES_MAX_AGE = 5 * 60
228CACHE_RESPONSE = True
230# Trusted URLs for default redirection
231TRUSTED_DEFAULT_URLS = [
232 {"schemes": ["https"], "host_equals": "ui-avatars.com", "path_prefix": "/api/"},
233 {
234 "schemes": ["http", "https"],
235 "host_equals": "gravatar.com",
236 "path_prefix": "/avatar/",
237 },
238 {
239 "schemes": ["http", "https"],
240 "host_suffix": ".gravatar.com",
241 "path_prefix": "/avatar/",
242 },
243 {
244 "schemes": ["http", "https"],
245 "host_equals": "www.gravatar.org",
246 "path_prefix": "/avatar/",
247 },
248 {
249 "schemes": ["https"],
250 "host_equals": "avatars.dicebear.com",
251 "path_prefix": "/api/",
252 },
253 {
254 "schemes": ["https"],
255 "host_equals": "api.dicebear.com",
256 "path_prefix": "/",
257 },
258 {
259 "schemes": ["https"],
260 "host_equals": "badges.fedoraproject.org",
261 "path_prefix": "/static/img/",
262 },
263 {
264 "schemes": ["http"],
265 "host_equals": "www.planet-libre.org",
266 "path_prefix": "/themes/planetlibre/images/",
267 },
268 {"schemes": ["https"], "host_equals": "www.azuracast.com", "path_prefix": "/img/"},
269 {
270 "schemes": ["https"],
271 "host_equals": "reps.mozilla.org",
272 "path_prefix": "/static/base/img/remo/",
273 },
274]
276URL_TIMEOUT = 10
279def map_legacy_config(trusted_url):
280 """
281 For backward compability with the legacy configuration
282 for trusting URLs. Adapts them to fit the new config.
283 """
284 if isinstance(trusted_url, str):
285 return {"url_prefix": trusted_url}
287 return trusted_url
290# Backward compability for legacy behavior
291TRUSTED_DEFAULT_URLS = list(map(map_legacy_config, TRUSTED_DEFAULT_URLS))
293# Bluesky settings
294BLUESKY_IDENTIFIER = os.environ.get("BLUESKY_IDENTIFIER", None)
295BLUESKY_APP_PASSWORD = os.environ.get("BLUESKY_APP_PASSWORD", None)
297# This MUST BE THE LAST!
298if os.path.isfile(os.path.join(BASE_DIR, "config_local.py")):
299 from config_local import * # noqa # flake8: noqa # NOQA # pragma: no cover