Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -526,6 +526,14 @@ WEBDAV_SERVER_NAMES="172.17.0.1,webdav"
# DEFAULT: 5433
HOST_POSTGRES_PORT=5433

# Comma-separated list of origins allowed to make cross-origin requests to the API.
# Do NOT include trailing slashes. Example: https://app.example.com,http://localhost:5173
CORS_ALLOWED_ORIGINS=https://docs.qfield.org

# Allow credentials (cookies, authorization headers) in cross-origin requests.
# Set to 1 if your clients send authentication tokens or session cookies.
CORS_ALLOW_CREDENTIALS=1
Comment on lines +529 to +535
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
# Comma-separated list of origins allowed to make cross-origin requests to the API.
# Do NOT include trailing slashes. Example: https://app.example.com,http://localhost:5173
CORS_ALLOWED_ORIGINS=https://docs.qfield.org
# Allow credentials (cookies, authorization headers) in cross-origin requests.
# Set to 1 if your clients send authentication tokens or session cookies.
CORS_ALLOW_CREDENTIALS=1
# Comma-separated list of origins allowed to make cross-origin requests to the API.
# Example "https://app.example.com,http://localhost:5173"
# NOTE: Do NOT include trailing slashes.
# DEFAULT: "https://docs.qfield.org"
CORS_ALLOWED_ORIGINS=https://docs.qfield.org
# Allow credentials (cookies, authorization headers) in cross-origin requests.
# VALUES: 0 - do not allow credentials; 1 - allow clients to send authentication tokens or session cookies.
# DEFAULT: 1
CORS_ALLOW_CREDENTIALS=1

See the docs example here: https://github.com/csgis/QFieldCloud/blob/b1f73e9074a3dc55fc359d8e0fa8c8607d1cf256/.env.example#L6



##################
# Debug settings - development only
Expand Down
30 changes: 30 additions & 0 deletions docker-app/qfieldcloud/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,12 +137,14 @@
"django_extensions",
"bootstrap4",
"sri",
"corsheaders",
# To ensure that exceptions inside other apps' signal handlers do not affect the integrity of file deletions within transactions, `django_cleanup` should be placed last in `INSTALLED_APPS`. See https://github.com/un1t/django-cleanup#configuration
"django_cleanup.apps.CleanupConfig",
]

MIDDLEWARE = [
"debug_toolbar.middleware.DebugToolbarMiddleware",
"corsheaders.middleware.CorsMiddleware",
"django.middleware.security.SecurityMiddleware",
"django.contrib.sessions.middleware.SessionMiddleware",
"django.middleware.locale.LocaleMiddleware",
Expand Down Expand Up @@ -586,6 +588,7 @@ def before_send(event, hint):
},
}

###########################
# Django axes configuration
# https://django-axes.readthedocs.io/en/latest/4_configuration.html
###########################
Expand Down Expand Up @@ -970,3 +973,30 @@ def before_send(event, hint):
# "logo_alt": "Your logo description",
# "favicon": "path/to/favicon.ico",
# }


###########################
# CORS settings
# Managed via django-cors-headers.
# Origins and credentials are configured through environment variables,
# so no nginx changes are needed when adding new clients.
# https://github.com/adamchainz/django-cors-headers
###########################

# Comma-separated list of origins that are allowed to make cross-origin
# requests. Do not include trailing slashes.
# Example: CORS_ALLOWED_ORIGINS=https://app.example.com,http://localhost:5173
CORS_ALLOWED_ORIGINS = [
origin.strip()
for origin in os.environ.get("CORS_ALLOWED_ORIGINS", "").split(",")
if origin.strip()
]
Comment on lines +989 to +993
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
CORS_ALLOWED_ORIGINS = [
origin.strip()
for origin in os.environ.get("CORS_ALLOWED_ORIGINS", "").split(",")
if origin.strip()
]
CORS_ALLOWED_ORIGINS = parse_string_to_list(os.environ.get("CORS_ALLOWED_ORIGINS", ""))

Can you add a new helper function parse_string_to_list(input_str: str) -> list[str] to settings_utils instead of inlining the Python in this file?


# Only allow CORS on API endpoints – static files and pages are unaffected.
CORS_URLS_REGEX = r"^/api/.*$"

# Whether to include credentials (cookies, authorization headers) in
# cross-origin requests. Required when clients send auth tokens.
CORS_ALLOW_CREDENTIALS = bool(
int(os.environ.get("CORS_ALLOW_CREDENTIALS", 0))
)
1 change: 1 addition & 0 deletions docker-app/requirements/requirements.in
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ django-axes==8.0.0
django-bootstrap4==25.2
django-classy-tags==4.1.0
django-cleanup==9.0.0
django-cors-headers==4.9.0
django-common-helpers==0.9.2
django-constance==4.3.2
django-countries==8.2.0
Expand Down
99 changes: 50 additions & 49 deletions docker-app/requirements/requirements.txt
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file has way too many diff lines. Please minimize to the actual subset of changes that matters. Also it seems you ran the script with Python 3.11 somehow. Make sure you use the pip-compile that is part of the app container.

Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
#
# This file is autogenerated by pip-compile with Python 3.10
# This file is autogenerated by pip-compile with Python 3.11
# by the following command:
#
# pip-compile --no-strip-extras --output-file=/requirements/requirements.txt /requirements/requirements.in
# pip-compile requirements/requirements.in
#
asgiref==3.9.1
# via
# django
# django-allauth
# django-axes
# django-cors-headers
# django-countries
attrs==25.3.0
# via
Expand All @@ -17,9 +18,9 @@ attrs==25.3.0
beautifulsoup4==4.13.5
# via django-bootstrap4
boto3==1.35.90
# via -r /requirements/requirements.in
# via -r requirements/requirements.in
boto3-stubs==1.35.90
# via -r /requirements/requirements.in
# via -r requirements/requirements.in
botocore==1.35.99
# via
# boto3
Expand All @@ -39,16 +40,17 @@ cryptography==45.0.6
# django-fernet-encrypted-fields
# pyjwt
deprecated==1.3.1
# via -r /requirements/requirements.in
# via -r requirements/requirements.in
django==4.2.28
# via
# -r /requirements/requirements.in
# -r requirements/requirements.in
# django-allauth
# django-auditlog
# django-axes
# django-bootstrap4
# django-classy-tags
# django-common-helpers
# django-cors-headers
# django-cron
# django-currentuser
# django-debug-toolbar
Expand All @@ -72,77 +74,79 @@ django==4.2.28
# drf-spectacular
# jsonfield
django-allauth[socialaccount]==65.13.1
# via -r /requirements/requirements.in
# via -r requirements/requirements.in
django-auditlog==3.4.0
# via -r /requirements/requirements.in
# via -r requirements/requirements.in
django-axes==8.0.0
# via -r /requirements/requirements.in
# via -r requirements/requirements.in
django-bootstrap4==25.2
# via -r /requirements/requirements.in
# via -r requirements/requirements.in
django-classy-tags==4.1.0
# via -r /requirements/requirements.in
# via -r requirements/requirements.in
django-cleanup==9.0.0
# via -r /requirements/requirements.in
# via -r requirements/requirements.in
django-common-helpers==0.9.2
# via -r /requirements/requirements.in
# via -r requirements/requirements.in
django-constance==4.3.2
# via -r /requirements/requirements.in
# via -r requirements/requirements.in
django-cors-headers==4.9.0
# via -r requirements/requirements.in
django-countries==8.2.0
# via -r /requirements/requirements.in
# via -r requirements/requirements.in
django-cron==0.6.0
# via -r /requirements/requirements.in
# via -r requirements/requirements.in
django-currentuser==0.9.0
# via -r /requirements/requirements.in
# via -r requirements/requirements.in
django-debug-toolbar==6.0.0
# via -r /requirements/requirements.in
# via -r requirements/requirements.in
django-extensions==4.1
# via -r /requirements/requirements.in
# via -r requirements/requirements.in
django-fernet-encrypted-fields==0.3.0
# via -r /requirements/requirements.in
# via -r requirements/requirements.in
django-filter==25.1
# via -r /requirements/requirements.in
# via -r requirements/requirements.in
django-invitations==2.1.0
# via -r /requirements/requirements.in
# via -r requirements/requirements.in
django-jazzmin==3.0.1
# via -r /requirements/requirements.in
# via -r requirements/requirements.in
django-log-request-id==2.1.0
# via -r /requirements/requirements.in
# via -r requirements/requirements.in
django-migrate-sql-3==3.0.2
# via -r /requirements/requirements.in
# via -r requirements/requirements.in
django-model-utils==5.0.0
# via
# -r /requirements/requirements.in
# -r requirements/requirements.in
# django-notifications-hq
django-nonrelated-inlines==0.2
# via -r /requirements/requirements.in
# via -r requirements/requirements.in
django-notifications-hq==1.8.3
# via -r /requirements/requirements.in
# via -r requirements/requirements.in
django-phonenumber-field==8.3.0
# via -r /requirements/requirements.in
# via -r requirements/requirements.in
django-sri==0.8.0
# via -r /requirements/requirements.in
# via -r requirements/requirements.in
django-storages==1.14.6
# via -r /requirements/requirements.in
# via -r requirements/requirements.in
django-stubs==5.2.7
# via
# -r /requirements/requirements.in
# -r requirements/requirements.in
# djangorestframework-stubs
django-stubs-ext==5.2.7
# via
# -r /requirements/requirements.in
# -r requirements/requirements.in
# django-stubs
django-tables2==2.8.0
# via -r /requirements/requirements.in
# via -r requirements/requirements.in
django-timezone-field==7.1
# via -r /requirements/requirements.in
# via -r requirements/requirements.in
djangorestframework==3.16.1
# via
# -r /requirements/requirements.in
# -r requirements/requirements.in
# drf-spectacular
djangorestframework-stubs==3.16.4
# via -r /requirements/requirements.in
# via -r requirements/requirements.in
drf-spectacular==0.29.0
# via -r /requirements/requirements.in
# via -r requirements/requirements.in
idna==3.10
# via requests
inflection==0.5.1
Expand All @@ -152,29 +156,29 @@ jmespath==1.0.1
# boto3
# botocore
json-log-formatter==1.1.1
# via -r /requirements/requirements.in
# via -r requirements/requirements.in
jsonfield==3.2.0
# via django-notifications-hq
jsonschema==4.25.1
# via drf-spectacular
jsonschema-specifications==2025.4.1
# via jsonschema
mypy-boto3-s3==1.35.81
# via -r /requirements/requirements.in
# via -r requirements/requirements.in
oauthlib==3.3.1
# via django-allauth
phonenumbers==9.0.15
# via -r /requirements/requirements.in
# via -r requirements/requirements.in
pillow==11.3.0
# via -r /requirements/requirements.in
# via -r requirements/requirements.in
psycopg2==2.9.11
# via -r /requirements/requirements.in
# via -r requirements/requirements.in
pycparser==2.22
# via cffi
pyjwt[crypto]==2.10.1
# via django-allauth
pymemcache==4.0.0
# via -r /requirements/requirements.in
# via -r requirements/requirements.in
python-dateutil==2.9.0.post0
# via
# botocore
Expand All @@ -199,7 +203,7 @@ rpds-py==0.27.0
s3transfer==0.10.4
# via boto3
sentry-sdk==2.47.0
# via -r /requirements/requirements.in
# via -r requirements/requirements.in
six==1.17.0
# via python-dateutil
soupsieve==2.7
Expand All @@ -209,11 +213,9 @@ sqlparse==0.5.3
# django
# django-debug-toolbar
stripe==4.2.0
# via -r /requirements/requirements.in
# via -r requirements/requirements.in
swapper==1.4.0
# via django-notifications-hq
tomli==2.2.1
# via django-stubs
types-awscrt==0.27.6
# via botocore-stubs
types-pyyaml==6.0.12.20250822
Expand All @@ -226,7 +228,6 @@ types-s3transfer==0.13.0
# via boto3-stubs
typing-extensions==4.14.1
# via
# asgiref
# beautifulsoup4
# boto3-stubs
# django-countries
Expand Down
2 changes: 2 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ services:
EMAIL_HOST_USER: ${EMAIL_HOST_USER}
EMAIL_HOST_PASSWORD: ${EMAIL_HOST_PASSWORD}
DEFAULT_FROM_EMAIL: ${DEFAULT_FROM_EMAIL}
CORS_ALLOWED_ORIGINS: ${CORS_ALLOWED_ORIGINS}
CORS_ALLOW_CREDENTIALS: ${CORS_ALLOW_CREDENTIALS}
# Settings below are specific to worker_wrapper
# TODO : move this to the worker_wrapper service and keep things DRY (yaml syntax expert needed)
TMP_DIRECTORY: ${TMP_DIRECTORY}
Expand Down
1 change: 0 additions & 1 deletion docker-nginx/templates/default.conf.template
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,6 @@ server {
}

location /swagger.yaml {
add_header Access-Control-Allow-Origin https://docs.qfield.org;
proxy_pass http://django;
}

Expand Down