We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Update structlog configuration to fix structlog.threadlocal deprecation warning
## Description
The new version of structlog deprecates structlog.threadlocal and generates this warning

```
terraso_backend/config/settings.py:183
  /app/terraso_backend/config/settings.py:183: DeprecationWarning: `structlog.threadlocal` is deprecated, please use `structlog.contextvars` instead.
    context_class=structlog.threadlocal.wrap_dict(dict),
```

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `terraso_backend/config/settings.py`
Content:
```
1 import os
2 
3 import django
4 import structlog
5 from dj_database_url import parse as parse_db_url
6 from django.utils.encoding import force_str
7 from prettyconf import config
8 
9 # Monkey patching force_text function to make the application work with Django
10 # 4.0. This is necessary until graphene-django fully supports the new Django
11 # version. This will probably be necessary until the following PR be merged.
12 # https://github.com/graphql-python/graphene-django/pull/1275
13 django.utils.encoding.force_text = force_str
14 
15 # Build paths inside the project like this: os.path.join(BASE_DIR, ...)
16 BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
17 PROJECT_DIR = os.path.dirname(os.path.abspath(BASE_DIR))
18 
19 DEBUG = config("DEBUG", default=False, cast=config.boolean)
20 
21 ALLOWED_HOSTS = config("ALLOWED_HOSTS", default="*", cast=config.list)
22 CSRF_TRUSTED_ORIGINS = config(
23     "CSRF_TRUSTED_ORIGINS", default="https://*.terraso.org", cast=config.list
24 )
25 
26 SECRET_KEY = config("SECRET_KEY")
27 
28 SILENCED_SYSTEM_CHECKS = ["auth.W004"]
29 
30 INSTALLED_APPS = [
31     "django.contrib.admin",
32     "django.contrib.auth",
33     "django.contrib.contenttypes",
34     "django.contrib.sessions",
35     "django.contrib.messages",
36     "django.contrib.staticfiles",
37     "oauth2_provider",
38     "corsheaders",
39     "graphene_django",
40     "rules",
41     "storages",
42     "safedelete",
43     "apps.core",
44     "apps.graphql",
45     "apps.auth",
46     "apps.shared_data",
47 ]
48 
49 MIDDLEWARE = [
50     "django.middleware.security.SecurityMiddleware",
51     "django.contrib.sessions.middleware.SessionMiddleware",
52     "corsheaders.middleware.CorsMiddleware",
53     "django.middleware.common.CommonMiddleware",
54     "django.middleware.csrf.CsrfViewMiddleware",
55     "django.contrib.auth.middleware.AuthenticationMiddleware",
56     "django.contrib.messages.middleware.MessageMiddleware",
57     "django.middleware.clickjacking.XFrameOptionsMiddleware",
58     "apps.auth.middleware.JWTAuthenticationMiddleware",
59     "django_structlog.middlewares.RequestMiddleware",
60 ]
61 
62 ROOT_URLCONF = "config.urls"
63 
64 TEMPLATES = [
65     {
66         "BACKEND": "django.template.backends.django.DjangoTemplates",
67         "APP_DIRS": True,
68         "DIRS": [os.path.join(BASE_DIR, "custom_templates")],
69         "OPTIONS": {
70             "context_processors": [
71                 "django.template.context_processors.debug",
72                 "django.template.context_processors.request",
73                 "django.contrib.auth.context_processors.auth",
74                 "django.contrib.messages.context_processors.messages",
75                 "apps.core.context_processors.restore_allowed",
76             ],
77         },
78     },
79 ]
80 
81 WSGI_APPLICATION = "config.wsgi.application"
82 
83 default_dburl = "sqlite:///" + os.path.join(BASE_DIR, "db.sqlite3")
84 DATABASES = {
85     "default": config("DATABASE_URL", default=default_dburl, cast=parse_db_url),
86 }
87 
88 AUTHENTICATION_BACKENDS = (
89     "rules.permissions.ObjectPermissionBackend",
90     "django.contrib.auth.backends.ModelBackend",
91 )
92 
93 SAFE_DELETE_FIELD_NAME = "deleted_at"
94 
95 AUTH_USER_MODEL = "core.User"
96 
97 AUTH_PASSWORD_VALIDATORS = [
98     {
99         "NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator",
100     },
101     {
102         "NAME": "django.contrib.auth.password_validation.MinimumLengthValidator",
103     },
104     {
105         "NAME": "django.contrib.auth.password_validation.CommonPasswordValidator",
106     },
107     {
108         "NAME": "django.contrib.auth.password_validation.NumericPasswordValidator",
109     },
110 ]
111 
112 OAUTH2_PROVIDER = {
113     "OIDC_ENABLED": True,
114     "SCOPES": {
115         "email": "User's email scope",
116         "openid": "OpenID Connect scope",
117         "profile": "User's information scope",
118     },
119     "OAUTH2_VALIDATOR_CLASS": "apps.auth.provider.oauth_validator.TerrasoOAuth2Validator",
120     "OIDC_RSA_PRIVATE_KEY": config("OAUTH_OIDC_KEY", default="").replace("\\n", "\n"),
121     "PKCE_REQUIRED": False,
122 }
123 
124 LANGUAGE_CODE = "en-us"
125 TIME_ZONE = "UTC"
126 USE_I18N = True
127 USE_TZ = True
128 
129 MEDIA_URL = "/media/"
130 STATIC_URL = "/static/"
131 
132 # don't allow "new" as a name, as the view route conflicts with the create route
133 DISALLOWED_NAMES_LIST = ["new"]
134 
135 if not DEBUG:
136     CDN_STATIC_DOMAIN = config("CDN_STATIC_DOMAIN")
137     AWS_S3_CUSTOM_DOMAIN = CDN_STATIC_DOMAIN
138     AWS_STORAGE_BUCKET_NAME = CDN_STATIC_DOMAIN
139     STATIC_URL = f"{CDN_STATIC_DOMAIN}/"
140     STATICFILES_STORAGE = "storages.backends.s3boto3.S3StaticStorage"
141 
142 LOGGING = {
143     "version": 1,
144     "disable_existing_loggers": False,
145     "formatters": {
146         "json_formatter": {
147             "()": structlog.stdlib.ProcessorFormatter,
148             "processor": structlog.processors.JSONRenderer(),
149         },
150         "plain_console": {
151             "()": structlog.stdlib.ProcessorFormatter,
152             "processor": structlog.dev.ConsoleRenderer(),
153         },
154     },
155     "handlers": {
156         "console": {
157             "class": "logging.StreamHandler",
158             "formatter": "json_formatter",
159         },
160     },
161     "loggers": {
162         "": {
163             "handlers": ["console"],
164             "level": "INFO",
165         },
166         "django": {
167             "handlers": ["console"],
168             "level": "ERROR",
169         },
170     },
171 }
172 
173 structlog.configure(
174     processors=[
175         structlog.stdlib.filter_by_level,
176         structlog.processors.TimeStamper(fmt="iso"),
177         structlog.stdlib.add_logger_name,
178         structlog.stdlib.add_log_level,
179         structlog.stdlib.PositionalArgumentsFormatter(),
180         structlog.processors.StackInfoRenderer(),
181         structlog.processors.format_exc_info,
182         structlog.processors.UnicodeDecoder(),
183         structlog.stdlib.ProcessorFormatter.wrap_for_formatter,
184     ],
185     context_class=structlog.threadlocal.wrap_dict(dict),
186     logger_factory=structlog.stdlib.LoggerFactory(),
187     wrapper_class=structlog.stdlib.BoundLogger,
188     cache_logger_on_first_use=True,
189 )
190 
191 GRAPHENE = {
192     "SCHEMA": "apps.graphql.schema.schema",
193 }
194 
195 WEB_CLIENT_URL = config("WEB_CLIENT_ENDPOINT", default="")
196 LOGIN_URL = f"{WEB_CLIENT_URL}/account"
197 AUTH_COOKIE_DOMAIN = config("AUTH_COOKIE_DOMAIN", default="")
198 CORS_ORIGIN_WHITELIST = config("CORS_ORIGIN_WHITELIST", default=[], cast=config.list)
199 
200 AIRTABLE_API_KEY = config("AIRTABLE_API_KEY", default="")
201 
202 GOOGLE_CLIENT_ID = config("GOOGLE_CLIENT_ID", default="")
203 GOOGLE_CLIENT_SECRET = config("GOOGLE_CLIENT_SECRET", default="")
204 GOOGLE_AUTH_REDIRECT_URI = config("GOOGLE_AUTH_REDIRECT_URI", default="")
205 
206 APPLE_KEY_ID = config("APPLE_KEY_ID", default="")
207 APPLE_TEAM_ID = config("APPLE_TEAM_ID", default="")
208 APPLE_PRIVATE_KEY = config("APPLE_PRIVATE_KEY", default="").replace("\\n", "\n")
209 APPLE_CLIENT_ID = config("APPLE_CLIENT_ID", default="")
210 APPLE_AUTH_REDIRECT_URI = config("APPLE_AUTH_REDIRECT_URI", default="")
211 
212 JWT_SECRET = config("JWT_SECRET")
213 JWT_ALGORITHM = config("JWT_ALGORITHM", default="HS512")
214 JWT_ACCESS_EXP_DELTA_SECONDS = config(
215     "JWT_ACCESS_EXP_DELTA_SECONDS", default="360", cast=config.eval
216 )
217 JWT_REFRESH_EXP_DELTA_SECONDS = config(
218     "JWT_REFRESH_EXP_DELTA_SECONDS", default="3600", cast=config.eval
219 )
220 JWT_ISS = config("JWT_ISS", default="https://terraso.org")
221 
222 PROFILE_IMAGES_S3_BUCKET = config("PROFILE_IMAGES_S3_BUCKET", default="")
223 PROFILE_IMAGES_BASE_URL = f"https://{PROFILE_IMAGES_S3_BUCKET}"
224 
225 DATA_ENTRY_FILE_S3_BUCKET = config("DATA_ENTRY_FILE_S3_BUCKET", default="")
226 DATA_ENTRY_FILE_BASE_URL = f"https://{DATA_ENTRY_FILE_S3_BUCKET}"
227 
228 DB_BACKUP_S3_BUCKET = config("DB_BACKUP_S3_BUCKET", default="")
229 ALLOW_RESTORE_FROM_BACKUP = config("ALLOW_RESTORE_FROM_BACKUP", default="false").lower() == "true"
230 DB_RESTORE_CONFIG_FILE = config("DB_RESTORE_CONFIG_FILE", default="")
231 
232 AWS_ACCESS_KEY_ID = config("AWS_ACCESS_KEY_ID", default="")
233 AWS_SECRET_ACCESS_KEY = config("AWS_SECRET_ACCESS_KEY", default="")
234 AWS_S3_REGION_NAME = config("AWS_S3_REGION_NAME", default="us-east-2")
235 
236 PLAUSIBLE_URL = config("PLAUSIBLE_URL", default="https://plausible.io/api/event")
237 RENDER_API_URL = config("RENDER_API_URL", default="https://api.render.com/v1/")
238 RENDER_API_TOKEN = config("RENDER_API_TOKEN", default="")
239
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/terraso_backend/config/settings.py b/terraso_backend/config/settings.py
--- a/terraso_backend/config/settings.py
+++ b/terraso_backend/config/settings.py
@@ -182,7 +182,6 @@
         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,

{"golden_diff": "diff --git a/terraso_backend/config/settings.py b/terraso_backend/config/settings.py\n--- a/terraso_backend/config/settings.py\n+++ b/terraso_backend/config/settings.py\n@@ -182,7 +182,6 @@\n         structlog.processors.UnicodeDecoder(),\n         structlog.stdlib.ProcessorFormatter.wrap_for_formatter,\n     ],\n-    context_class=structlog.threadlocal.wrap_dict(dict),\n     logger_factory=structlog.stdlib.LoggerFactory(),\n     wrapper_class=structlog.stdlib.BoundLogger,\n     cache_logger_on_first_use=True,\n", "issue": "Update structlog configuration to fix structlog.threadlocal deprecation warning\n## Description\r\nThe new version of structlog deprecates structlog.threadlocal and generates this warning\r\n\r\n```\r\nterraso_backend/config/settings.py:183\r\n  /app/terraso_backend/config/settings.py:183: DeprecationWarning: `structlog.threadlocal` is deprecated, please use `structlog.contextvars` instead.\r\n    context_class=structlog.threadlocal.wrap_dict(dict),\r\n```\n", "before_files": [{"content": "import os\n\nimport django\nimport structlog\nfrom dj_database_url import parse as parse_db_url\nfrom django.utils.encoding import force_str\nfrom prettyconf import config\n\n# Monkey patching force_text function to make the application work with Django\n# 4.0. This is necessary until graphene-django fully supports the new Django\n# version. This will probably be necessary until the following PR be merged.\n# https://github.com/graphql-python/graphene-django/pull/1275\ndjango.utils.encoding.force_text = force_str\n\n# Build paths inside the project like this: os.path.join(BASE_DIR, ...)\nBASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))\nPROJECT_DIR = os.path.dirname(os.path.abspath(BASE_DIR))\n\nDEBUG = config(\"DEBUG\", default=False, cast=config.boolean)\n\nALLOWED_HOSTS = config(\"ALLOWED_HOSTS\", default=\"*\", cast=config.list)\nCSRF_TRUSTED_ORIGINS = config(\n    \"CSRF_TRUSTED_ORIGINS\", default=\"https://*.terraso.org\", cast=config.list\n)\n\nSECRET_KEY = config(\"SECRET_KEY\")\n\nSILENCED_SYSTEM_CHECKS = [\"auth.W004\"]\n\nINSTALLED_APPS = [\n    \"django.contrib.admin\",\n    \"django.contrib.auth\",\n    \"django.contrib.contenttypes\",\n    \"django.contrib.sessions\",\n    \"django.contrib.messages\",\n    \"django.contrib.staticfiles\",\n    \"oauth2_provider\",\n    \"corsheaders\",\n    \"graphene_django\",\n    \"rules\",\n    \"storages\",\n    \"safedelete\",\n    \"apps.core\",\n    \"apps.graphql\",\n    \"apps.auth\",\n    \"apps.shared_data\",\n]\n\nMIDDLEWARE = [\n    \"django.middleware.security.SecurityMiddleware\",\n    \"django.contrib.sessions.middleware.SessionMiddleware\",\n    \"corsheaders.middleware.CorsMiddleware\",\n    \"django.middleware.common.CommonMiddleware\",\n    \"django.middleware.csrf.CsrfViewMiddleware\",\n    \"django.contrib.auth.middleware.AuthenticationMiddleware\",\n    \"django.contrib.messages.middleware.MessageMiddleware\",\n    \"django.middleware.clickjacking.XFrameOptionsMiddleware\",\n    \"apps.auth.middleware.JWTAuthenticationMiddleware\",\n    \"django_structlog.middlewares.RequestMiddleware\",\n]\n\nROOT_URLCONF = \"config.urls\"\n\nTEMPLATES = [\n    {\n        \"BACKEND\": \"django.template.backends.django.DjangoTemplates\",\n        \"APP_DIRS\": True,\n        \"DIRS\": [os.path.join(BASE_DIR, \"custom_templates\")],\n        \"OPTIONS\": {\n            \"context_processors\": [\n                \"django.template.context_processors.debug\",\n                \"django.template.context_processors.request\",\n                \"django.contrib.auth.context_processors.auth\",\n                \"django.contrib.messages.context_processors.messages\",\n                \"apps.core.context_processors.restore_allowed\",\n            ],\n        },\n    },\n]\n\nWSGI_APPLICATION = \"config.wsgi.application\"\n\ndefault_dburl = \"sqlite:///\" + os.path.join(BASE_DIR, \"db.sqlite3\")\nDATABASES = {\n    \"default\": config(\"DATABASE_URL\", default=default_dburl, cast=parse_db_url),\n}\n\nAUTHENTICATION_BACKENDS = (\n    \"rules.permissions.ObjectPermissionBackend\",\n    \"django.contrib.auth.backends.ModelBackend\",\n)\n\nSAFE_DELETE_FIELD_NAME = \"deleted_at\"\n\nAUTH_USER_MODEL = \"core.User\"\n\nAUTH_PASSWORD_VALIDATORS = [\n    {\n        \"NAME\": \"django.contrib.auth.password_validation.UserAttributeSimilarityValidator\",\n    },\n    {\n        \"NAME\": \"django.contrib.auth.password_validation.MinimumLengthValidator\",\n    },\n    {\n        \"NAME\": \"django.contrib.auth.password_validation.CommonPasswordValidator\",\n    },\n    {\n        \"NAME\": \"django.contrib.auth.password_validation.NumericPasswordValidator\",\n    },\n]\n\nOAUTH2_PROVIDER = {\n    \"OIDC_ENABLED\": True,\n    \"SCOPES\": {\n        \"email\": \"User's email scope\",\n        \"openid\": \"OpenID Connect scope\",\n        \"profile\": \"User's information scope\",\n    },\n    \"OAUTH2_VALIDATOR_CLASS\": \"apps.auth.provider.oauth_validator.TerrasoOAuth2Validator\",\n    \"OIDC_RSA_PRIVATE_KEY\": config(\"OAUTH_OIDC_KEY\", default=\"\").replace(\"\\\\n\", \"\\n\"),\n    \"PKCE_REQUIRED\": False,\n}\n\nLANGUAGE_CODE = \"en-us\"\nTIME_ZONE = \"UTC\"\nUSE_I18N = True\nUSE_TZ = True\n\nMEDIA_URL = \"/media/\"\nSTATIC_URL = \"/static/\"\n\n# don't allow \"new\" as a name, as the view route conflicts with the create route\nDISALLOWED_NAMES_LIST = [\"new\"]\n\nif not DEBUG:\n    CDN_STATIC_DOMAIN = config(\"CDN_STATIC_DOMAIN\")\n    AWS_S3_CUSTOM_DOMAIN = CDN_STATIC_DOMAIN\n    AWS_STORAGE_BUCKET_NAME = CDN_STATIC_DOMAIN\n    STATIC_URL = f\"{CDN_STATIC_DOMAIN}/\"\n    STATICFILES_STORAGE = \"storages.backends.s3boto3.S3StaticStorage\"\n\nLOGGING = {\n    \"version\": 1,\n    \"disable_existing_loggers\": False,\n    \"formatters\": {\n        \"json_formatter\": {\n            \"()\": structlog.stdlib.ProcessorFormatter,\n            \"processor\": structlog.processors.JSONRenderer(),\n        },\n        \"plain_console\": {\n            \"()\": structlog.stdlib.ProcessorFormatter,\n            \"processor\": structlog.dev.ConsoleRenderer(),\n        },\n    },\n    \"handlers\": {\n        \"console\": {\n            \"class\": \"logging.StreamHandler\",\n            \"formatter\": \"json_formatter\",\n        },\n    },\n    \"loggers\": {\n        \"\": {\n            \"handlers\": [\"console\"],\n            \"level\": \"INFO\",\n        },\n        \"django\": {\n            \"handlers\": [\"console\"],\n            \"level\": \"ERROR\",\n        },\n    },\n}\n\nstructlog.configure(\n    processors=[\n        structlog.stdlib.filter_by_level,\n        structlog.processors.TimeStamper(fmt=\"iso\"),\n        structlog.stdlib.add_logger_name,\n        structlog.stdlib.add_log_level,\n        structlog.stdlib.PositionalArgumentsFormatter(),\n        structlog.processors.StackInfoRenderer(),\n        structlog.processors.format_exc_info,\n        structlog.processors.UnicodeDecoder(),\n        structlog.stdlib.ProcessorFormatter.wrap_for_formatter,\n    ],\n    context_class=structlog.threadlocal.wrap_dict(dict),\n    logger_factory=structlog.stdlib.LoggerFactory(),\n    wrapper_class=structlog.stdlib.BoundLogger,\n    cache_logger_on_first_use=True,\n)\n\nGRAPHENE = {\n    \"SCHEMA\": \"apps.graphql.schema.schema\",\n}\n\nWEB_CLIENT_URL = config(\"WEB_CLIENT_ENDPOINT\", default=\"\")\nLOGIN_URL = f\"{WEB_CLIENT_URL}/account\"\nAUTH_COOKIE_DOMAIN = config(\"AUTH_COOKIE_DOMAIN\", default=\"\")\nCORS_ORIGIN_WHITELIST = config(\"CORS_ORIGIN_WHITELIST\", default=[], cast=config.list)\n\nAIRTABLE_API_KEY = config(\"AIRTABLE_API_KEY\", default=\"\")\n\nGOOGLE_CLIENT_ID = config(\"GOOGLE_CLIENT_ID\", default=\"\")\nGOOGLE_CLIENT_SECRET = config(\"GOOGLE_CLIENT_SECRET\", default=\"\")\nGOOGLE_AUTH_REDIRECT_URI = config(\"GOOGLE_AUTH_REDIRECT_URI\", default=\"\")\n\nAPPLE_KEY_ID = config(\"APPLE_KEY_ID\", default=\"\")\nAPPLE_TEAM_ID = config(\"APPLE_TEAM_ID\", default=\"\")\nAPPLE_PRIVATE_KEY = config(\"APPLE_PRIVATE_KEY\", default=\"\").replace(\"\\\\n\", \"\\n\")\nAPPLE_CLIENT_ID = config(\"APPLE_CLIENT_ID\", default=\"\")\nAPPLE_AUTH_REDIRECT_URI = config(\"APPLE_AUTH_REDIRECT_URI\", default=\"\")\n\nJWT_SECRET = config(\"JWT_SECRET\")\nJWT_ALGORITHM = config(\"JWT_ALGORITHM\", default=\"HS512\")\nJWT_ACCESS_EXP_DELTA_SECONDS = config(\n    \"JWT_ACCESS_EXP_DELTA_SECONDS\", default=\"360\", cast=config.eval\n)\nJWT_REFRESH_EXP_DELTA_SECONDS = config(\n    \"JWT_REFRESH_EXP_DELTA_SECONDS\", default=\"3600\", cast=config.eval\n)\nJWT_ISS = config(\"JWT_ISS\", default=\"https://terraso.org\")\n\nPROFILE_IMAGES_S3_BUCKET = config(\"PROFILE_IMAGES_S3_BUCKET\", default=\"\")\nPROFILE_IMAGES_BASE_URL = f\"https://{PROFILE_IMAGES_S3_BUCKET}\"\n\nDATA_ENTRY_FILE_S3_BUCKET = config(\"DATA_ENTRY_FILE_S3_BUCKET\", default=\"\")\nDATA_ENTRY_FILE_BASE_URL = f\"https://{DATA_ENTRY_FILE_S3_BUCKET}\"\n\nDB_BACKUP_S3_BUCKET = config(\"DB_BACKUP_S3_BUCKET\", default=\"\")\nALLOW_RESTORE_FROM_BACKUP = config(\"ALLOW_RESTORE_FROM_BACKUP\", default=\"false\").lower() == \"true\"\nDB_RESTORE_CONFIG_FILE = config(\"DB_RESTORE_CONFIG_FILE\", default=\"\")\n\nAWS_ACCESS_KEY_ID = config(\"AWS_ACCESS_KEY_ID\", default=\"\")\nAWS_SECRET_ACCESS_KEY = config(\"AWS_SECRET_ACCESS_KEY\", default=\"\")\nAWS_S3_REGION_NAME = config(\"AWS_S3_REGION_NAME\", default=\"us-east-2\")\n\nPLAUSIBLE_URL = config(\"PLAUSIBLE_URL\", default=\"https://plausible.io/api/event\")\nRENDER_API_URL = config(\"RENDER_API_URL\", default=\"https://api.render.com/v1/\")\nRENDER_API_TOKEN = config(\"RENDER_API_TOKEN\", default=\"\")\n", "path": "terraso_backend/config/settings.py"}], "after_files": [{"content": "import os\n\nimport django\nimport structlog\nfrom dj_database_url import parse as parse_db_url\nfrom django.utils.encoding import force_str\nfrom prettyconf import config\n\n# Monkey patching force_text function to make the application work with Django\n# 4.0. This is necessary until graphene-django fully supports the new Django\n# version. This will probably be necessary until the following PR be merged.\n# https://github.com/graphql-python/graphene-django/pull/1275\ndjango.utils.encoding.force_text = force_str\n\n# Build paths inside the project like this: os.path.join(BASE_DIR, ...)\nBASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))\nPROJECT_DIR = os.path.dirname(os.path.abspath(BASE_DIR))\n\nDEBUG = config(\"DEBUG\", default=False, cast=config.boolean)\n\nALLOWED_HOSTS = config(\"ALLOWED_HOSTS\", default=\"*\", cast=config.list)\nCSRF_TRUSTED_ORIGINS = config(\n    \"CSRF_TRUSTED_ORIGINS\", default=\"https://*.terraso.org\", cast=config.list\n)\n\nSECRET_KEY = config(\"SECRET_KEY\")\n\nSILENCED_SYSTEM_CHECKS = [\"auth.W004\"]\n\nINSTALLED_APPS = [\n    \"django.contrib.admin\",\n    \"django.contrib.auth\",\n    \"django.contrib.contenttypes\",\n    \"django.contrib.sessions\",\n    \"django.contrib.messages\",\n    \"django.contrib.staticfiles\",\n    \"oauth2_provider\",\n    \"corsheaders\",\n    \"graphene_django\",\n    \"rules\",\n    \"storages\",\n    \"safedelete\",\n    \"apps.core\",\n    \"apps.graphql\",\n    \"apps.auth\",\n    \"apps.shared_data\",\n]\n\nMIDDLEWARE = [\n    \"django.middleware.security.SecurityMiddleware\",\n    \"django.contrib.sessions.middleware.SessionMiddleware\",\n    \"corsheaders.middleware.CorsMiddleware\",\n    \"django.middleware.common.CommonMiddleware\",\n    \"django.middleware.csrf.CsrfViewMiddleware\",\n    \"django.contrib.auth.middleware.AuthenticationMiddleware\",\n    \"django.contrib.messages.middleware.MessageMiddleware\",\n    \"django.middleware.clickjacking.XFrameOptionsMiddleware\",\n    \"apps.auth.middleware.JWTAuthenticationMiddleware\",\n    \"django_structlog.middlewares.RequestMiddleware\",\n]\n\nROOT_URLCONF = \"config.urls\"\n\nTEMPLATES = [\n    {\n        \"BACKEND\": \"django.template.backends.django.DjangoTemplates\",\n        \"APP_DIRS\": True,\n        \"DIRS\": [os.path.join(BASE_DIR, \"custom_templates\")],\n        \"OPTIONS\": {\n            \"context_processors\": [\n                \"django.template.context_processors.debug\",\n                \"django.template.context_processors.request\",\n                \"django.contrib.auth.context_processors.auth\",\n                \"django.contrib.messages.context_processors.messages\",\n                \"apps.core.context_processors.restore_allowed\",\n            ],\n        },\n    },\n]\n\nWSGI_APPLICATION = \"config.wsgi.application\"\n\ndefault_dburl = \"sqlite:///\" + os.path.join(BASE_DIR, \"db.sqlite3\")\nDATABASES = {\n    \"default\": config(\"DATABASE_URL\", default=default_dburl, cast=parse_db_url),\n}\n\nAUTHENTICATION_BACKENDS = (\n    \"rules.permissions.ObjectPermissionBackend\",\n    \"django.contrib.auth.backends.ModelBackend\",\n)\n\nSAFE_DELETE_FIELD_NAME = \"deleted_at\"\n\nAUTH_USER_MODEL = \"core.User\"\n\nAUTH_PASSWORD_VALIDATORS = [\n    {\n        \"NAME\": \"django.contrib.auth.password_validation.UserAttributeSimilarityValidator\",\n    },\n    {\n        \"NAME\": \"django.contrib.auth.password_validation.MinimumLengthValidator\",\n    },\n    {\n        \"NAME\": \"django.contrib.auth.password_validation.CommonPasswordValidator\",\n    },\n    {\n        \"NAME\": \"django.contrib.auth.password_validation.NumericPasswordValidator\",\n    },\n]\n\nOAUTH2_PROVIDER = {\n    \"OIDC_ENABLED\": True,\n    \"SCOPES\": {\n        \"email\": \"User's email scope\",\n        \"openid\": \"OpenID Connect scope\",\n        \"profile\": \"User's information scope\",\n    },\n    \"OAUTH2_VALIDATOR_CLASS\": \"apps.auth.provider.oauth_validator.TerrasoOAuth2Validator\",\n    \"OIDC_RSA_PRIVATE_KEY\": config(\"OAUTH_OIDC_KEY\", default=\"\").replace(\"\\\\n\", \"\\n\"),\n    \"PKCE_REQUIRED\": False,\n}\n\nLANGUAGE_CODE = \"en-us\"\nTIME_ZONE = \"UTC\"\nUSE_I18N = True\nUSE_TZ = True\n\nMEDIA_URL = \"/media/\"\nSTATIC_URL = \"/static/\"\n\n# don't allow \"new\" as a name, as the view route conflicts with the create route\nDISALLOWED_NAMES_LIST = [\"new\"]\n\nif not DEBUG:\n    CDN_STATIC_DOMAIN = config(\"CDN_STATIC_DOMAIN\")\n    AWS_S3_CUSTOM_DOMAIN = CDN_STATIC_DOMAIN\n    AWS_STORAGE_BUCKET_NAME = CDN_STATIC_DOMAIN\n    STATIC_URL = f\"{CDN_STATIC_DOMAIN}/\"\n    STATICFILES_STORAGE = \"storages.backends.s3boto3.S3StaticStorage\"\n\nLOGGING = {\n    \"version\": 1,\n    \"disable_existing_loggers\": False,\n    \"formatters\": {\n        \"json_formatter\": {\n            \"()\": structlog.stdlib.ProcessorFormatter,\n            \"processor\": structlog.processors.JSONRenderer(),\n        },\n        \"plain_console\": {\n            \"()\": structlog.stdlib.ProcessorFormatter,\n            \"processor\": structlog.dev.ConsoleRenderer(),\n        },\n    },\n    \"handlers\": {\n        \"console\": {\n            \"class\": \"logging.StreamHandler\",\n            \"formatter\": \"json_formatter\",\n        },\n    },\n    \"loggers\": {\n        \"\": {\n            \"handlers\": [\"console\"],\n            \"level\": \"INFO\",\n        },\n        \"django\": {\n            \"handlers\": [\"console\"],\n            \"level\": \"ERROR\",\n        },\n    },\n}\n\nstructlog.configure(\n    processors=[\n        structlog.stdlib.filter_by_level,\n        structlog.processors.TimeStamper(fmt=\"iso\"),\n        structlog.stdlib.add_logger_name,\n        structlog.stdlib.add_log_level,\n        structlog.stdlib.PositionalArgumentsFormatter(),\n        structlog.processors.StackInfoRenderer(),\n        structlog.processors.format_exc_info,\n        structlog.processors.UnicodeDecoder(),\n        structlog.stdlib.ProcessorFormatter.wrap_for_formatter,\n    ],\n    logger_factory=structlog.stdlib.LoggerFactory(),\n    wrapper_class=structlog.stdlib.BoundLogger,\n    cache_logger_on_first_use=True,\n)\n\nGRAPHENE = {\n    \"SCHEMA\": \"apps.graphql.schema.schema\",\n}\n\nWEB_CLIENT_URL = config(\"WEB_CLIENT_ENDPOINT\", default=\"\")\nLOGIN_URL = f\"{WEB_CLIENT_URL}/account\"\nAUTH_COOKIE_DOMAIN = config(\"AUTH_COOKIE_DOMAIN\", default=\"\")\nCORS_ORIGIN_WHITELIST = config(\"CORS_ORIGIN_WHITELIST\", default=[], cast=config.list)\n\nAIRTABLE_API_KEY = config(\"AIRTABLE_API_KEY\", default=\"\")\n\nGOOGLE_CLIENT_ID = config(\"GOOGLE_CLIENT_ID\", default=\"\")\nGOOGLE_CLIENT_SECRET = config(\"GOOGLE_CLIENT_SECRET\", default=\"\")\nGOOGLE_AUTH_REDIRECT_URI = config(\"GOOGLE_AUTH_REDIRECT_URI\", default=\"\")\n\nAPPLE_KEY_ID = config(\"APPLE_KEY_ID\", default=\"\")\nAPPLE_TEAM_ID = config(\"APPLE_TEAM_ID\", default=\"\")\nAPPLE_PRIVATE_KEY = config(\"APPLE_PRIVATE_KEY\", default=\"\").replace(\"\\\\n\", \"\\n\")\nAPPLE_CLIENT_ID = config(\"APPLE_CLIENT_ID\", default=\"\")\nAPPLE_AUTH_REDIRECT_URI = config(\"APPLE_AUTH_REDIRECT_URI\", default=\"\")\n\nJWT_SECRET = config(\"JWT_SECRET\")\nJWT_ALGORITHM = config(\"JWT_ALGORITHM\", default=\"HS512\")\nJWT_ACCESS_EXP_DELTA_SECONDS = config(\n    \"JWT_ACCESS_EXP_DELTA_SECONDS\", default=\"360\", cast=config.eval\n)\nJWT_REFRESH_EXP_DELTA_SECONDS = config(\n    \"JWT_REFRESH_EXP_DELTA_SECONDS\", default=\"3600\", cast=config.eval\n)\nJWT_ISS = config(\"JWT_ISS\", default=\"https://terraso.org\")\n\nPROFILE_IMAGES_S3_BUCKET = config(\"PROFILE_IMAGES_S3_BUCKET\", default=\"\")\nPROFILE_IMAGES_BASE_URL = f\"https://{PROFILE_IMAGES_S3_BUCKET}\"\n\nDATA_ENTRY_FILE_S3_BUCKET = config(\"DATA_ENTRY_FILE_S3_BUCKET\", default=\"\")\nDATA_ENTRY_FILE_BASE_URL = f\"https://{DATA_ENTRY_FILE_S3_BUCKET}\"\n\nDB_BACKUP_S3_BUCKET = config(\"DB_BACKUP_S3_BUCKET\", default=\"\")\nALLOW_RESTORE_FROM_BACKUP = config(\"ALLOW_RESTORE_FROM_BACKUP\", default=\"false\").lower() == \"true\"\nDB_RESTORE_CONFIG_FILE = config(\"DB_RESTORE_CONFIG_FILE\", default=\"\")\n\nAWS_ACCESS_KEY_ID = config(\"AWS_ACCESS_KEY_ID\", default=\"\")\nAWS_SECRET_ACCESS_KEY = config(\"AWS_SECRET_ACCESS_KEY\", default=\"\")\nAWS_S3_REGION_NAME = config(\"AWS_S3_REGION_NAME\", default=\"us-east-2\")\n\nPLAUSIBLE_URL = config(\"PLAUSIBLE_URL\", default=\"https://plausible.io/api/event\")\nRENDER_API_URL = config(\"RENDER_API_URL\", default=\"https://api.render.com/v1/\")\nRENDER_API_TOKEN = config(\"RENDER_API_TOKEN\", default=\"\")\n", "path": "terraso_backend/config/settings.py"}]}