Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

♻️ Clean up simcore webserver environment ⚠️ DEVOPS #4491

Merged
merged 32 commits into from
Jul 31, 2023
Merged
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
e005101
Clean up simcore webserver environment
YuryHrytsuk Jul 12, 2023
1643fbe
Add WEBSERVER_ACTIVITY
YuryHrytsuk Jul 14, 2023
4ce375b
Fix project variables
YuryHrytsuk Jul 14, 2023
b9aa157
Merge branch 'master' into clean-up-webserver-env
YuryHrytsuk Jul 14, 2023
b436532
Fixing tests
YuryHrytsuk Jul 14, 2023
0e6e483
Merge branch 'master' into clean-up-webserver-env
YuryHrytsuk Jul 14, 2023
81e1f70
Stop using json env variables
YuryHrytsuk Jul 17, 2023
a25e602
Fix mock environment
YuryHrytsuk Jul 17, 2023
463e946
Fix login setup
YuryHrytsuk Jul 18, 2023
1693065
Fix garbage collector unit tests
YuryHrytsuk Jul 18, 2023
0ffb179
Propagate new env names
YuryHrytsuk Jul 18, 2023
fe63d28
Fix garbage collector tests
YuryHrytsuk Jul 18, 2023
162b44a
Fix exporter variable
YuryHrytsuk Jul 18, 2023
26f4f40
Add missing WEBSERVER_LOGLEVEL
YuryHrytsuk Jul 18, 2023
215b682
Fix variable `STUDIES_ACCESS_ANONYMOUS_ALLOWED`
YuryHrytsuk Jul 18, 2023
bce288f
Return to one-liner volumes
YuryHrytsuk Jul 19, 2023
51387c2
Remove `dask-scheduler` env validation
YuryHrytsuk Jul 19, 2023
c1fcd84
Add LOGIN_2FA_CODE_EXPIRATION_SEC env
YuryHrytsuk Jul 19, 2023
38b881c
Update webserver related services env
YuryHrytsuk Jul 20, 2023
88af0b1
Merge branch 'master' into clean-up-webserver-env
YuryHrytsuk Jul 20, 2023
840ab12
Merge branch 'master' into clean-up-webserver-env
YuryHrytsuk Jul 20, 2023
25e3491
Update webserver garbage collector and event db listener env
YuryHrytsuk Jul 21, 2023
338f109
Merge branch 'master' into clean-up-webserver-env
YuryHrytsuk Jul 24, 2023
332c5b3
Merge branch 'master' into clean-up-webserver-env
YuryHrytsuk Jul 26, 2023
817bff8
Add missing envs
YuryHrytsuk Jul 28, 2023
ccebdc1
Update .env-devel
YuryHrytsuk Jul 28, 2023
8aaada7
Add missing envs to .env-devel
YuryHrytsuk Jul 28, 2023
d6600c3
Merge branch 'master' into clean-up-webserver-env
YuryHrytsuk Jul 28, 2023
c5367d4
Add missing env
YuryHrytsuk Jul 28, 2023
8c6bace
Merge branch 'master' into clean-up-webserver-env
YuryHrytsuk Jul 28, 2023
7fca09b
Merge branch 'master' into clean-up-webserver-env
YuryHrytsuk Jul 31, 2023
d89e2b3
Merge branch 'master' into clean-up-webserver-env
YuryHrytsuk Jul 31, 2023
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
73 changes: 66 additions & 7 deletions .env-devel
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,6 @@ S3_ENDPOINT=172.17.0.1:9001
S3_SECRET_KEY=12345678
S3_SECURE=0



SCICRUNCH_API_BASE_URL=https://scicrunch.org/api/1
SCICRUNCH_API_KEY=REPLACE_ME_with_valid_api_key

Expand All @@ -105,19 +103,80 @@ TRACING_THRIFT_COMPACT_ENDPOINT=http://jaeger:5775
TRAEFIK_SIMCORE_ZONE=internal_simcore_stack

# NOTE: WEBSERVER_SESSION_SECRET_KEY = $(python3 -c "from cryptography.fernet import Fernet; print(Fernet.generate_key())")

WEBSERVER_LOGLEVEL=INFO

WEBSERVER_PROJECTS={}
PROJECTS_MAX_COPY_SIZE_BYTES=30Gib
PROJECTS_MAX_NUM_RUNNING_DYNAMIC_NODES=5

WEBSERVER_ANNOUNCEMENTS=1

WEBSERVER_DEV_FEATURES_ENABLED=0

WEBSERVER_HOST=webserver
WEBSERVER_LOGIN_REGISTRATION_CONFIRMATION_REQUIRED=0
WEBSERVER_LOGIN_REGISTRATION_INVITATION_REQUIRED=0

WEBSERVER_CATALOG={}
CATALOG_HOST=catalog
CATALOG_PORT=8000

WEBSERVER_SCICRUNCH={}

WEBSERVER_SESSION_SECRET_KEY='REPLACE_ME_with_result__Fernet_generate_key='

WEBSERVER_STATICWEB={}

WEBSERVER_STUDIES_DISPATCHER={}
STUDIES_ACCESS_ANONYMOUS_ALLOWED=0
STUDIES_DEFAULT_SERVICE_THUMBNAIL=https://via.placeholder.com/170x120.png

WEBSERVER_TRACING={}

WEBSERVER_GUNICORN_CMD_ARGS=--timeout=180

WEBSERVER_EXPORTER={}

WEBSERVER_EMAIL={}

DIRECTOR_HOST=director
DIRECTOR_PORT=8080

DIRECTOR_V2_HOST=director-v2
DIRECTOR_V2_PORT=8000

WEBSERVER_DIAGNOSTICS={}
DIAGNOSTICS_MAX_AVG_LATENCY=10
DIAGNOSTICS_MAX_TASK_DELAY=30

WEBSERVER_GARBAGE_COLLECTOR=null

WEBSERVER_DB_LISTENER=0

WEBSERVER_LOGIN={}
LOGIN_REGISTRATION_CONFIRMATION_REQUIRED=0
LOGIN_REGISTRATION_INVITATION_REQUIRED=0
LOGIN_2FA_REQUIRED=0
LOGIN_2FA_CODE_EXPIRATION_SEC=60

WEBSERVER_FRONTEND={}

WEBSERVER_ACTIVITY=null # disable Prometheus
WEBSERVER_PROMETHEUS_API_VERSION=v1
WEBSERVER_PROMETHEUS_URL=http://prometheus:9090
WEBSERVER_RESOURCES_DELETION_TIMEOUT_SECONDS=900
WEBSERVER_SESSION_SECRET_KEY='REPLACE_ME_with_result__Fernet_generate_key='
WEBSERVER_STUDIES_ACCESS_ENABLED=0

RESOURCE_MANAGER_RESOURCE_TTL_S=900

WEBSERVER_NOTIFICATIONS=1

WEBSERVER_CLUSTERS=0
WEBSERVER_GROUPS=1
WEBSERVER_META_MODELING=1
WEBSERVER_PRODUCTS=1
WEBSERVER_PUBLICATIONS=1
WEBSERVER_SOCKETIO=1
WEBSERVER_TAGS=1
WEBSERVER_USERS=1
WEBSERVER_VERSION_CONTROL=1

# For development ONLY ---------------
#
Expand Down
3 changes: 2 additions & 1 deletion services/docker-compose.devel.yml
Original file line number Diff line number Diff line change
Expand Up @@ -95,14 +95,15 @@ services:
volumes: *webserver-volumes-dev
environment:
<<: *webserver-environment-dev
WEBSERVER_RESOURCES_DELETION_TIMEOUT_SECONDS: 15
RESOURCE_MANAGER_RESOURCE_TTL_S: 15

dask-sidecar:
volumes:
&dev-dask-sidecar-volumes
- ./dask-sidecar:/devel/services/dask-sidecar
- ../packages:/devel/packages
- ${ETC_HOSTNAME:-/etc/hostname}:/home/scu/hostname:ro

environment:
SC_BOOT_MODE: debug-ptvsd
SIDECAR_LOGLEVEL: DEBUG
Expand Down
181 changes: 160 additions & 21 deletions services/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -262,26 +262,143 @@ services:
hostname: "{{.Node.Hostname}}-{{.Service.Name}}-{{.Task.Slot}}"
environment:
&webserver-environment
YuryHrytsuk marked this conversation as resolved.
Show resolved Hide resolved
CATALOG_HOST: ${CATALOG_HOST:-catalog}
CATALOG_PORT: ${CATALOG_PORT:-8000}
DIAGNOSTICS_MAX_AVG_LATENCY: 10
DIAGNOSTICS_MAX_TASK_DELAY: 30
DIRECTOR_HOST: ${DIRECTOR_HOST:-director}
DIRECTOR_PORT: ${DIRECTOR_PORT:-8080}
DIRECTOR_V2_HOST: ${DIRECTOR_V2_HOST:-director-v2}
DIRECTOR_V2_PORT: ${DIRECTOR_V2_PORT:-8000}

SWARM_STACK_NAME: ${SWARM_STACK_NAME}

WEBSERVER_DEV_FEATURES_ENABLED: ${WEBSERVER_DEV_FEATURES_ENABLED}

WEBSERVER_LOGLEVEL: ${WEBSERVER_LOGLEVEL}

WEBSERVER_LOG_FORMAT_LOCAL_DEV_ENABLED: ${LOG_FORMAT_LOCAL_DEV_ENABLED}

# WEBSERVER_SERVER_HOST

WEBSERVER_HOST: ${WEBSERVER_HOST}

# WEBSERVER_SERVER_PORT

WEBSERVER_FRONTEND: ${WEBSERVER_FRONTEND}

# WEBSERVER_ACTIVITY
WEBSERVER_ACTIVITY: ${WEBSERVER_ACTIVITY}
PROMETHEUS_API_VERSION: ${WEBSERVER_PROMETHEUS_API_VERSION} # seems to be not used
PROMETHEUS_URL: ${WEBSERVER_PROMETHEUS_URL}

WEBSERVER_CATALOG: ${WEBSERVER_CATALOG}
CATALOG_HOST: ${CATALOG_HOST}
CATALOG_PORT: ${CATALOG_PORT}

# WEBSERVER_DB
POSTGRES_DB: ${POSTGRES_DB}
POSTGRES_ENDPOINT: ${POSTGRES_ENDPOINT}
POSTGRES_HOST: ${POSTGRES_HOST}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_PORT: ${POSTGRES_PORT}
POSTGRES_USER: ${POSTGRES_USER}

# WEBSERVER_DIAGNOSTICS
WEBSERVER_DIAGNOSTICS: ${WEBSERVER_DIAGNOSTICS}
DIAGNOSTICS_MAX_AVG_LATENCY: ${DIAGNOSTICS_MAX_AVG_LATENCY}
DIAGNOSTICS_MAX_TASK_DELAY: ${DIAGNOSTICS_MAX_TASK_DELAY}

# WEBSERVER_DIRECTOR_V2
DIRECTOR_V2_HOST: ${DIRECTOR_V2_HOST}
DIRECTOR_V2_PORT: ${DIRECTOR_V2_PORT}

# WEBSERVER_DIRECTOR
DIRECTOR_HOST: ${DIRECTOR_HOST}
DIRECTOR_PORT: ${DIRECTOR_PORT}

# WEBSERVER_EMAIL
WEBSERVER_EMAIL: ${WEBSERVER_EMAIL}
SMTP_HOST: ${SMTP_HOST}
SMTP_PORT: ${SMTP_PORT}

WEBSERVER_EXPORTER: ${WEBSERVER_EXPORTER}

# WEBSERVER_GARBAGE_COLLECTOR
WEBSERVER_GARBAGE_COLLECTOR: ${WEBSERVER_GARBAGE_COLLECTOR}

# WEBSERVER_INVITATIONS
INVITATIONS_HOST: ${INVITATIONS_HOST}
INVITATIONS_LOGLEVEL: ${INVITATIONS_LOGLEVEL}
INVITATIONS_OSPARC_URL: ${INVITATIONS_OSPARC_URL}
INVITATIONS_PASSWORD: ${INVITATIONS_PASSWORD}
INVITATIONS_PORT: ${INVITATIONS_PORT}
INVITATIONS_SECRET_KEY: ${INVITATIONS_SECRET_KEY}
INVITATIONS_USERNAME: ${INVITATIONS_USERNAME}

WEBSERVER_LOGIN: ${WEBSERVER_LOGIN}
LOGIN_REGISTRATION_CONFIRMATION_REQUIRED: ${LOGIN_REGISTRATION_CONFIRMATION_REQUIRED}
LOGIN_REGISTRATION_INVITATION_REQUIRED: ${LOGIN_REGISTRATION_INVITATION_REQUIRED}
LOGIN_2FA_REQUIRED: ${LOGIN_2FA_REQUIRED}
LOGIN_2FA_CODE_EXPIRATION_SEC: ${LOGIN_2FA_CODE_EXPIRATION_SEC}

# WEBSERVER_REDIS
REDIS_HOST: ${REDIS_HOST}
REDIS_PORT: ${REDIS_PORT}

# WEBSERVER_REST

# WEBSERVER_RESOURCE_MANAGER
RESOURCE_MANAGER_RESOURCE_TTL_S: ${RESOURCE_MANAGER_RESOURCE_TTL_S}

# WEBSERVER_RESOURCE_USAGE_TRACKER

# WEBSERVER_SCICRUNCH
WEBSERVER_SCICRUNCH: ${WEBSERVER_SCICRUNCH}
SCICRUNCH_API_BASE_URL: ${SCICRUNCH_API_BASE_URL}
SCICRUNCH_API_KEY: ${SCICRUNCH_API_KEY}

# WEBSERVER_SESSION
SESSION_SECRET_KEY: ${WEBSERVER_SESSION_SECRET_KEY}

WEBSERVER_STATICWEB: ${WEBSERVER_STATICWEB}

# WEBSERVER_STORAGE
STORAGE_ENDPOINT: ${STORAGE_ENDPOINT}
STORAGE_HOST: ${STORAGE_HOST}
STORAGE_PORT: ${STORAGE_PORT}

# WEBSERVER_STUDIES_DISPATCHER
WEBSERVER_STUDIES_DISPATCHER: ${WEBSERVER_STUDIES_DISPATCHER}
STUDIES_ACCESS_ANONYMOUS_ALLOWED: ${STUDIES_ACCESS_ANONYMOUS_ALLOWED}
STUDIES_DEFAULT_SERVICE_THUMBNAIL: ${STUDIES_DEFAULT_SERVICE_THUMBNAIL}

WEBSERVER_TRACING: ${WEBSERVER_TRACING}
TRACING_ENABLED: ${TRACING_ENABLED}
TRACING_ZIPKIN_ENDPOINT: ${TRACING_ZIPKIN_ENDPOINT}
TRACING_THRIFT_COMPACT_ENDPOINT: ${TRACING_THRIFT_COMPACT_ENDPOINT}

# WEBSERVER_PROJECTS
WEBSERVER_PROJECTS: ${WEBSERVER_PROJECTS}
PROJECTS_MAX_COPY_SIZE_BYTES: ${PROJECTS_MAX_COPY_SIZE_BYTES}
PROJECTS_MAX_NUM_RUNNING_DYNAMIC_NODES: ${PROJECTS_MAX_NUM_RUNNING_DYNAMIC_NODES}

# WEBSERVER_RABBITMQ
RABBIT_HOST: ${RABBIT_HOST}
RABBIT_PASSWORD: ${RABBIT_PASSWORD}
RABBIT_PORT: ${RABBIT_PORT}
RABBIT_USER: ${RABBIT_USER}

# ARBITRARY ENV VARS

# see [https://docs.gunicorn.org/en/stable/settings.html#timeout],
# since we have the docker healthcheck already, this should be ok
GUNICORN_CMD_ARGS: --timeout=180
LOG_FORMAT_LOCAL_DEV_ENABLED: ${LOG_FORMAT_LOCAL_DEV_ENABLED}
STORAGE_HOST: ${STORAGE_HOST:-storage}
STORAGE_PORT: ${STORAGE_PORT:-8080}
SWARM_STACK_NAME: ${SWARM_STACK_NAME:-simcore}
WEBSERVER_DB_LISTENER: 0
WEBSERVER_GARBAGE_COLLECTOR: "null"
WEBSERVER_LOGLEVEL: ${LOG_LEVEL:-WARNING}
env_file:
- ../.env
GUNICORN_CMD_ARGS: ${WEBSERVER_GUNICORN_CMD_ARGS}
WEBSERVER_DB_LISTENER: ${WEBSERVER_DB_LISTENER}
WEBSERVER_ANNOUNCEMENTS: ${WEBSERVER_ANNOUNCEMENTS}
WEBSERVER_NOTIFICATIONS: ${WEBSERVER_NOTIFICATIONS}
WEBSERVER_CLUSTERS: ${WEBSERVER_CLUSTERS}
WEBSERVER_GROUPS: ${WEBSERVER_GROUPS}
WEBSERVER_META_MODELING: ${WEBSERVER_META_MODELING}
WEBSERVER_PRODUCTS: ${WEBSERVER_PRODUCTS}
WEBSERVER_PUBLICATIONS: ${WEBSERVER_PUBLICATIONS}
WEBSERVER_SOCKETIO: ${WEBSERVER_SOCKETIO}
WEBSERVER_TAGS: ${WEBSERVER_TAGS}
WEBSERVER_USERS: ${WEBSERVER_USERS}
WEBSERVER_VERSION_CONTROL: ${WEBSERVER_VERSION_CONTROL}

deploy:
placement:
constraints:
Expand Down Expand Up @@ -312,12 +429,22 @@ services:
networks:
- default
- interactive_services_subnet

wb-db-event-listener:
YuryHrytsuk marked this conversation as resolved.
Show resolved Hide resolved
image: ${DOCKER_REGISTRY:-itisfoundation}/webserver:${DOCKER_IMAGE_TAG:-latest}
init: true
hostname: "{{.Node.Hostname}}-{{.Service.Name}}-{{.Task.Slot}}"
environment:
<<: *webserver-environment
DIRECTOR_HOST: ${DIRECTOR_HOST}
DIRECTOR_PORT: ${DIRECTOR_PORT}
DIRECTOR_V2_HOST: ${DIRECTOR_V2_HOST}
DIRECTOR_V2_PORT: ${DIRECTOR_V2_PORT}
# see [https://docs.gunicorn.org/en/stable/settings.html#timeout],
# since we have the docker healthcheck already, this should be ok
GUNICORN_CMD_ARGS: ${WEBSERVER_GUNICORN_CMD_ARGS}
LOG_FORMAT_LOCAL_DEV_ENABLED: ${LOG_FORMAT_LOCAL_DEV_ENABLED}
SWARM_STACK_NAME: ${SWARM_STACK_NAME}
WEBSERVER_LOGLEVEL: ${LOG_LEVEL}
WEBSERVER_DB_LISTENER: 1
WEBSERVER_SOCKETIO: 1
env_file:
Expand All @@ -339,9 +466,21 @@ services:
init: true
hostname: "{{.Node.Hostname}}-{{.Service.Name}}-{{.Task.Slot}}"
environment:
<<: *webserver-environment
DIRECTOR_HOST: ${DIRECTOR_HOST}
DIRECTOR_PORT: ${DIRECTOR_PORT}
DIRECTOR_V2_HOST: ${DIRECTOR_V2_HOST}
DIRECTOR_V2_PORT: ${DIRECTOR_V2_PORT}
# see [https://docs.gunicorn.org/en/stable/settings.html#timeout],
# since we have the docker healthcheck already, this should be ok
GUNICORN_CMD_ARGS: ${WEBSERVER_GUNICORN_CMD_ARGS}
LOG_FORMAT_LOCAL_DEV_ENABLED: ${LOG_FORMAT_LOCAL_DEV_ENABLED}
STORAGE_HOST: ${STORAGE_HOST}
STORAGE_PORT: ${STORAGE_PORT}
SWARM_STACK_NAME: ${SWARM_STACK_NAME}
WEBSERVER_DB_LISTENER: 0
WEBSERVER_LOGLEVEL: ${LOG_LEVEL}
WEBSERVER_GARBAGE_COLLECTOR: '{"GARBAGE_COLLECTOR_INTERVAL_S": 30}'
WEBSERVER_RESOURCES_DELETION_TIMEOUT_SECONDS: 60
RESOURCE_MANAGER_RESOURCE_TTL_S: 60
env_file:
- ../.env
- ../.env-wb-garbage-collector
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -206,9 +206,7 @@ class ApplicationSettings(BaseCustomSettings, MixinLoggingSettings):
WEBSERVER_ANNOUNCEMENTS: bool = False
WEBSERVER_CLUSTERS: bool = False
WEBSERVER_DB_LISTENER: bool = True
WEBSERVER_NOTIFICATIONS: bool = Field(
default=True, env=["WEBSERVER_NOTIFICATIONS", "WEBSERVER_COMPUTATION"]
)
WEBSERVER_NOTIFICATIONS: bool = Field(default=True)
WEBSERVER_GROUPS: bool = True
WEBSERVER_META_MODELING: bool = True
WEBSERVER_PRODUCTS: bool = True
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -215,10 +215,10 @@ def _set_if_disabled(field_name, section):
if section := cfg.get("resource_manager"):
_set_if_disabled("WEBSERVER_RESOURCE_MANAGER", section)

envs["WEBSERVER_RESOURCES_DELETION_TIMEOUT_SECONDS"] = section.get(
envs["RESOURCE_MANAGER_RESOURCE_TTL_S"] = section.get(
"resource_deletion_timeout_seconds"
)
envs["WEBSERVER_GARBAGE_COLLECTION_INTERVAL_SECONDS"] = section.get(
envs["GARBAGE_COLLECTOR_INTERVAL_S"] = section.get(
"garbage_collection_interval_seconds"
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,6 @@ class GarbageCollectorSettings(BaseCustomSettings):
GARBAGE_COLLECTOR_INTERVAL_S: PositiveInt = Field(
30 * _SEC,
description="Waiting time between consecutive runs of the garbage-colector",
# legacy
YuryHrytsuk marked this conversation as resolved.
Show resolved Hide resolved
env=[
"GARBAGE_COLLECTOR_INTERVAL_S",
"WEBSERVER_GARBAGE_COLLECTION_INTERVAL_SECONDS", # legacy
],
)

GARBAGE_COLLECTOR_EXPIRED_USERS_CHECK_INTERVAL_S: PositiveInt = Field(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,18 +23,10 @@
class LoginSettings(BaseCustomSettings):
LOGIN_REGISTRATION_CONFIRMATION_REQUIRED: bool = Field(
True,
env=[
"LOGIN_REGISTRATION_CONFIRMATION_REQUIRED",
"WEBSERVER_LOGIN_REGISTRATION_CONFIRMATION_REQUIRED",
],
)

LOGIN_REGISTRATION_INVITATION_REQUIRED: bool = Field(
...,
env=[
"LOGIN_REGISTRATION_INVITATION_REQUIRED",
"WEBSERVER_LOGIN_REGISTRATION_INVITATION_REQUIRED",
],
)

LOGIN_TWILIO: TwilioSettings | None = Field(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,6 @@ class ResourceManagerSettings(BaseCustomSettings):
RESOURCE_MANAGER_RESOURCE_TTL_S: PositiveInt = Field(
900,
description="Expiration time (or Time to live (TTL) in redis jargon) for a registered resource",
# legacy!
env=[
"RESOURCE_MANAGER_RESOURCE_TTL_S",
"WEBSERVER_RESOURCES_DELETION_TIMEOUT_SECONDS", # legacy
],
)


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ class StudiesDispatcherSettings(BaseCustomSettings):
STUDIES_ACCESS_ANONYMOUS_ALLOWED: bool = Field(
False,
description="If enabled, the study links are accessible to anonymous users",
env=["STUDIES_ACCESS_ANONYMOUS_ALLOWED", "WEBSERVER_STUDIES_ACCESS_ENABLED"],
)

STUDIES_GUEST_ACCOUNT_LIFETIME: timedelta = Field(
Expand Down
Loading