fractal-server 2.16.6__py3-none-any.whl → 2.17.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (142) hide show
  1. fractal_server/__init__.py +1 -1
  2. fractal_server/__main__.py +178 -52
  3. fractal_server/app/db/__init__.py +9 -11
  4. fractal_server/app/models/security.py +30 -22
  5. fractal_server/app/models/user_settings.py +5 -4
  6. fractal_server/app/models/v2/__init__.py +4 -0
  7. fractal_server/app/models/v2/profile.py +16 -0
  8. fractal_server/app/models/v2/project.py +5 -0
  9. fractal_server/app/models/v2/resource.py +130 -0
  10. fractal_server/app/models/v2/task_group.py +4 -0
  11. fractal_server/app/routes/admin/v2/__init__.py +4 -0
  12. fractal_server/app/routes/admin/v2/_aux_functions.py +55 -0
  13. fractal_server/app/routes/admin/v2/accounting.py +3 -3
  14. fractal_server/app/routes/admin/v2/impersonate.py +2 -2
  15. fractal_server/app/routes/admin/v2/job.py +51 -15
  16. fractal_server/app/routes/admin/v2/profile.py +100 -0
  17. fractal_server/app/routes/admin/v2/project.py +2 -2
  18. fractal_server/app/routes/admin/v2/resource.py +222 -0
  19. fractal_server/app/routes/admin/v2/task.py +59 -32
  20. fractal_server/app/routes/admin/v2/task_group.py +17 -12
  21. fractal_server/app/routes/admin/v2/task_group_lifecycle.py +52 -86
  22. fractal_server/app/routes/api/__init__.py +45 -8
  23. fractal_server/app/routes/api/v2/_aux_functions.py +17 -1
  24. fractal_server/app/routes/api/v2/_aux_functions_history.py +2 -2
  25. fractal_server/app/routes/api/v2/_aux_functions_task_lifecycle.py +3 -3
  26. fractal_server/app/routes/api/v2/_aux_functions_tasks.py +55 -19
  27. fractal_server/app/routes/api/v2/_aux_task_group_disambiguation.py +21 -17
  28. fractal_server/app/routes/api/v2/dataset.py +10 -19
  29. fractal_server/app/routes/api/v2/history.py +8 -8
  30. fractal_server/app/routes/api/v2/images.py +5 -5
  31. fractal_server/app/routes/api/v2/job.py +8 -8
  32. fractal_server/app/routes/api/v2/pre_submission_checks.py +3 -3
  33. fractal_server/app/routes/api/v2/project.py +15 -7
  34. fractal_server/app/routes/api/v2/status_legacy.py +2 -2
  35. fractal_server/app/routes/api/v2/submit.py +49 -42
  36. fractal_server/app/routes/api/v2/task.py +26 -8
  37. fractal_server/app/routes/api/v2/task_collection.py +39 -50
  38. fractal_server/app/routes/api/v2/task_collection_custom.py +10 -6
  39. fractal_server/app/routes/api/v2/task_collection_pixi.py +34 -42
  40. fractal_server/app/routes/api/v2/task_group.py +19 -9
  41. fractal_server/app/routes/api/v2/task_group_lifecycle.py +43 -86
  42. fractal_server/app/routes/api/v2/task_version_update.py +3 -3
  43. fractal_server/app/routes/api/v2/workflow.py +9 -9
  44. fractal_server/app/routes/api/v2/workflow_import.py +25 -13
  45. fractal_server/app/routes/api/v2/workflowtask.py +5 -5
  46. fractal_server/app/routes/auth/__init__.py +34 -5
  47. fractal_server/app/routes/auth/_aux_auth.py +39 -20
  48. fractal_server/app/routes/auth/current_user.py +56 -67
  49. fractal_server/app/routes/auth/group.py +29 -46
  50. fractal_server/app/routes/auth/oauth.py +55 -38
  51. fractal_server/app/routes/auth/register.py +2 -2
  52. fractal_server/app/routes/auth/router.py +4 -2
  53. fractal_server/app/routes/auth/users.py +29 -53
  54. fractal_server/app/routes/aux/_runner.py +2 -1
  55. fractal_server/app/routes/aux/validate_user_profile.py +62 -0
  56. fractal_server/app/schemas/__init__.py +0 -1
  57. fractal_server/app/schemas/user.py +43 -13
  58. fractal_server/app/schemas/user_group.py +2 -1
  59. fractal_server/app/schemas/v2/__init__.py +12 -0
  60. fractal_server/app/schemas/v2/profile.py +78 -0
  61. fractal_server/app/schemas/v2/resource.py +137 -0
  62. fractal_server/app/schemas/v2/task_collection.py +11 -3
  63. fractal_server/app/schemas/v2/task_group.py +5 -0
  64. fractal_server/app/security/__init__.py +174 -75
  65. fractal_server/app/security/signup_email.py +52 -34
  66. fractal_server/config/__init__.py +27 -0
  67. fractal_server/config/_data.py +68 -0
  68. fractal_server/config/_database.py +59 -0
  69. fractal_server/config/_email.py +133 -0
  70. fractal_server/config/_main.py +78 -0
  71. fractal_server/config/_oauth.py +69 -0
  72. fractal_server/config/_settings_config.py +7 -0
  73. fractal_server/data_migrations/2_17_0.py +339 -0
  74. fractal_server/images/tools.py +3 -3
  75. fractal_server/logger.py +3 -3
  76. fractal_server/main.py +17 -23
  77. fractal_server/migrations/naming_convention.py +1 -1
  78. fractal_server/migrations/versions/83bc2ad3ffcc_2_17_0.py +195 -0
  79. fractal_server/runner/config/__init__.py +2 -0
  80. fractal_server/runner/config/_local.py +21 -0
  81. fractal_server/runner/config/_slurm.py +129 -0
  82. fractal_server/runner/config/slurm_mem_to_MB.py +63 -0
  83. fractal_server/runner/exceptions.py +4 -0
  84. fractal_server/runner/executors/base_runner.py +17 -7
  85. fractal_server/runner/executors/local/get_local_config.py +21 -86
  86. fractal_server/runner/executors/local/runner.py +48 -5
  87. fractal_server/runner/executors/slurm_common/_batching.py +2 -2
  88. fractal_server/runner/executors/slurm_common/base_slurm_runner.py +60 -26
  89. fractal_server/runner/executors/slurm_common/get_slurm_config.py +39 -55
  90. fractal_server/runner/executors/slurm_common/remote.py +1 -1
  91. fractal_server/runner/executors/slurm_common/slurm_config.py +214 -0
  92. fractal_server/runner/executors/slurm_common/slurm_job_task_models.py +1 -1
  93. fractal_server/runner/executors/slurm_ssh/runner.py +12 -14
  94. fractal_server/runner/executors/slurm_sudo/_subprocess_run_as_user.py +2 -2
  95. fractal_server/runner/executors/slurm_sudo/runner.py +12 -12
  96. fractal_server/runner/v2/_local.py +36 -21
  97. fractal_server/runner/v2/_slurm_ssh.py +41 -4
  98. fractal_server/runner/v2/_slurm_sudo.py +42 -12
  99. fractal_server/runner/v2/db_tools.py +1 -1
  100. fractal_server/runner/v2/runner.py +3 -11
  101. fractal_server/runner/v2/runner_functions.py +42 -28
  102. fractal_server/runner/v2/submit_workflow.py +88 -109
  103. fractal_server/runner/versions.py +8 -3
  104. fractal_server/ssh/_fabric.py +6 -6
  105. fractal_server/tasks/config/__init__.py +3 -0
  106. fractal_server/tasks/config/_pixi.py +127 -0
  107. fractal_server/tasks/config/_python.py +51 -0
  108. fractal_server/tasks/v2/local/_utils.py +7 -7
  109. fractal_server/tasks/v2/local/collect.py +13 -5
  110. fractal_server/tasks/v2/local/collect_pixi.py +26 -10
  111. fractal_server/tasks/v2/local/deactivate.py +7 -1
  112. fractal_server/tasks/v2/local/deactivate_pixi.py +5 -1
  113. fractal_server/tasks/v2/local/delete.py +5 -1
  114. fractal_server/tasks/v2/local/reactivate.py +13 -5
  115. fractal_server/tasks/v2/local/reactivate_pixi.py +27 -9
  116. fractal_server/tasks/v2/ssh/_pixi_slurm_ssh.py +11 -10
  117. fractal_server/tasks/v2/ssh/_utils.py +6 -7
  118. fractal_server/tasks/v2/ssh/collect.py +19 -12
  119. fractal_server/tasks/v2/ssh/collect_pixi.py +34 -16
  120. fractal_server/tasks/v2/ssh/deactivate.py +12 -8
  121. fractal_server/tasks/v2/ssh/deactivate_pixi.py +14 -10
  122. fractal_server/tasks/v2/ssh/delete.py +12 -9
  123. fractal_server/tasks/v2/ssh/reactivate.py +18 -12
  124. fractal_server/tasks/v2/ssh/reactivate_pixi.py +36 -17
  125. fractal_server/tasks/v2/templates/4_pip_show.sh +4 -6
  126. fractal_server/tasks/v2/utils_database.py +2 -2
  127. fractal_server/tasks/v2/utils_pixi.py +3 -0
  128. fractal_server/tasks/v2/utils_python_interpreter.py +8 -16
  129. fractal_server/tasks/v2/utils_templates.py +7 -10
  130. fractal_server/utils.py +1 -1
  131. {fractal_server-2.16.6.dist-info → fractal_server-2.17.0.dist-info}/METADATA +4 -6
  132. {fractal_server-2.16.6.dist-info → fractal_server-2.17.0.dist-info}/RECORD +136 -117
  133. fractal_server/app/routes/aux/validate_user_settings.py +0 -73
  134. fractal_server/app/schemas/user_settings.py +0 -67
  135. fractal_server/app/user_settings.py +0 -42
  136. fractal_server/config.py +0 -906
  137. fractal_server/data_migrations/2_14_10.py +0 -48
  138. fractal_server/runner/executors/slurm_common/_slurm_config.py +0 -471
  139. /fractal_server/{runner → app}/shutdown.py +0 -0
  140. {fractal_server-2.16.6.dist-info → fractal_server-2.17.0.dist-info}/WHEEL +0 -0
  141. {fractal_server-2.16.6.dist-info → fractal_server-2.17.0.dist-info}/entry_points.txt +0 -0
  142. {fractal_server-2.16.6.dist-info → fractal_server-2.17.0.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,68 @@
1
+ from enum import StrEnum
2
+ from typing import Self
3
+
4
+ from pydantic import model_validator
5
+ from pydantic_settings import BaseSettings
6
+ from pydantic_settings import SettingsConfigDict
7
+
8
+ from ._settings_config import SETTINGS_CONFIG_DICT
9
+ from fractal_server.types import AbsolutePathStr
10
+
11
+
12
+ class DataAuthScheme(StrEnum):
13
+ VIEWER_PATHS = "viewer-paths"
14
+ USERS_FOLDERS = "users-folders"
15
+ NONE = "none"
16
+
17
+
18
+ class DataSettings(BaseSettings):
19
+ """
20
+ Settings for the `fractal-data` integration.
21
+ """
22
+
23
+ model_config = SettingsConfigDict(**SETTINGS_CONFIG_DICT)
24
+
25
+ FRACTAL_DATA_AUTH_SCHEME: DataAuthScheme = "none"
26
+ """
27
+ Defines how the list of allowed viewer paths is built.
28
+
29
+ This variable affects the `GET /auth/current-user/allowed-viewer-paths/`
30
+ response, which is then consumed by
31
+ [fractal-data](https://github.com/fractal-analytics-platform/fractal-data).
32
+
33
+ Options:
34
+
35
+ - "viewer-paths": The list of allowed viewer paths will include the user's
36
+ `project_dir` along with any path defined in user groups' `viewer_paths`
37
+ attributes.
38
+ - "users-folders": The list will consist of the user's `project_dir` and a
39
+ user-specific folder. The user folder is constructed by concatenating
40
+ the base folder `FRACTAL_DATA_BASE_FOLDER` with the user's profile
41
+ `username`.
42
+ - "none": An empty list will be returned, indicating no access to
43
+ viewer paths. Useful when vizarr viewer is not used.
44
+ """
45
+
46
+ FRACTAL_DATA_BASE_FOLDER: AbsolutePathStr | None = None
47
+ """
48
+ Base path to Zarr files that will be served by fractal-vizarr-viewer;
49
+ This variable is required and used only when
50
+ FRACTAL_DATA_AUTHORIZATION_SCHEME is set to "users-folders".
51
+ """
52
+
53
+ @model_validator(mode="after")
54
+ def check(self: Self) -> Self:
55
+ """
56
+ `FRACTAL_DATA_BASE_FOLDER` is required when
57
+ `FRACTAL_DATA_AUTHORIZATION_SCHEME` is set to `"users-folders"`.
58
+ """
59
+ if (
60
+ self.FRACTAL_DATA_AUTH_SCHEME == DataAuthScheme.USERS_FOLDERS
61
+ and self.FRACTAL_DATA_BASE_FOLDER is None
62
+ ):
63
+ raise ValueError(
64
+ "FRACTAL_DATA_BASE_FOLDER is required when "
65
+ "FRACTAL_DATA_AUTH_SCHEME is set to "
66
+ "users-folders"
67
+ )
68
+ return self
@@ -0,0 +1,59 @@
1
+ from pydantic import SecretStr
2
+ from pydantic.types import NonNegativeInt
3
+ from pydantic_settings import BaseSettings
4
+ from pydantic_settings import SettingsConfigDict
5
+ from sqlalchemy.engine import URL
6
+
7
+ from ._settings_config import SETTINGS_CONFIG_DICT
8
+ from fractal_server.types import NonEmptyStr
9
+
10
+
11
+ class DatabaseSettings(BaseSettings):
12
+ """
13
+ Minimal set of configurations needed for operating on the database (e.g
14
+ for schema migrations).
15
+ """
16
+
17
+ model_config = SettingsConfigDict(**SETTINGS_CONFIG_DICT)
18
+
19
+ DB_ECHO: bool = False
20
+ """
21
+ If `True`, make database operations verbose.
22
+ """
23
+ POSTGRES_USER: NonEmptyStr | None = None
24
+ """
25
+ User to use when connecting to the PostgreSQL database.
26
+ """
27
+ POSTGRES_PASSWORD: SecretStr | None = None
28
+ """
29
+ Password to use when connecting to the PostgreSQL database.
30
+ """
31
+ POSTGRES_HOST: NonEmptyStr = "localhost"
32
+ """
33
+ URL to the PostgreSQL server or path to a UNIX domain socket.
34
+ """
35
+ POSTGRES_PORT: NonNegativeInt = 5432
36
+ """
37
+ Port number to use when connecting to the PostgreSQL server.
38
+ """
39
+ POSTGRES_DB: NonEmptyStr
40
+ """
41
+ Name of the PostgreSQL database to connect to.
42
+ """
43
+
44
+ @property
45
+ def DATABASE_URL(self) -> URL:
46
+ if self.POSTGRES_PASSWORD is None:
47
+ password = None
48
+ else:
49
+ password = self.POSTGRES_PASSWORD.get_secret_value()
50
+
51
+ url = URL.create(
52
+ drivername="postgresql+psycopg",
53
+ username=self.POSTGRES_USER,
54
+ password=password,
55
+ host=self.POSTGRES_HOST,
56
+ port=self.POSTGRES_PORT,
57
+ database=self.POSTGRES_DB,
58
+ )
59
+ return url
@@ -0,0 +1,133 @@
1
+ from typing import Literal
2
+ from typing import Self
3
+
4
+ from pydantic import BaseModel
5
+ from pydantic import EmailStr
6
+ from pydantic import Field
7
+ from pydantic import model_validator
8
+ from pydantic import SecretStr
9
+ from pydantic_settings import BaseSettings
10
+ from pydantic_settings import SettingsConfigDict
11
+
12
+ from ._settings_config import SETTINGS_CONFIG_DICT
13
+
14
+
15
+ class PublicEmailSettings(BaseModel):
16
+ """
17
+ Schema for `EmailSettings.public`, namely the ready-to-use settings.
18
+
19
+ Attributes:
20
+ sender: Sender email address
21
+ recipients: List of recipients email address
22
+ smtp_server: SMTP server address
23
+ port: SMTP server port
24
+ password: Sender password
25
+ instance_name: Name of SMTP server instance
26
+ use_starttls: Whether to use the security protocol
27
+ use_login: Whether to use login
28
+ """
29
+
30
+ sender: EmailStr
31
+ recipients: list[EmailStr] = Field(min_length=1)
32
+ smtp_server: str
33
+ port: int
34
+ password: SecretStr | None = None
35
+ instance_name: str
36
+ use_starttls: bool
37
+ use_login: bool
38
+
39
+
40
+ class EmailSettings(BaseSettings):
41
+ """
42
+ Class with settings for email-sending feature.
43
+ """
44
+
45
+ model_config = SettingsConfigDict(**SETTINGS_CONFIG_DICT)
46
+
47
+ FRACTAL_EMAIL_SENDER: EmailStr | None = None
48
+ """
49
+ Address of the OAuth-signup email sender.
50
+ """
51
+ FRACTAL_EMAIL_PASSWORD: SecretStr | None = None
52
+ """
53
+ Password for the OAuth-signup email sender.
54
+ """
55
+ FRACTAL_EMAIL_SMTP_SERVER: str | None = None
56
+ """
57
+ SMTP server for the OAuth-signup emails.
58
+ """
59
+ FRACTAL_EMAIL_SMTP_PORT: int | None = None
60
+ """
61
+ SMTP server port for the OAuth-signup emails.
62
+ """
63
+ FRACTAL_EMAIL_INSTANCE_NAME: str | None = None
64
+ """
65
+ Fractal instance name, to be included in the OAuth-signup emails.
66
+ """
67
+ FRACTAL_EMAIL_RECIPIENTS: str | None = None
68
+ """
69
+ Comma-separated list of recipients of the OAuth-signup emails.
70
+ """
71
+ FRACTAL_EMAIL_USE_STARTTLS: Literal["true", "false"] = "true"
72
+ """
73
+ Whether to use StartTLS when using the SMTP server.
74
+ Accepted values: 'true', 'false'.
75
+ """
76
+ FRACTAL_EMAIL_USE_LOGIN: Literal["true", "false"] = "true"
77
+ """
78
+ Whether to use login when using the SMTP server.
79
+ If 'true', FRACTAL_EMAIL_PASSWORD must be provided.
80
+ Accepted values: 'true', 'false'.
81
+ """
82
+
83
+ public: PublicEmailSettings | None = None
84
+ """
85
+ The validated field which is actually used in `fractal-server
86
+ (automatically populated upon creation).
87
+ """
88
+
89
+ @model_validator(mode="after")
90
+ def validate_email_settings(self: Self) -> Self:
91
+ """
92
+ Set `self.public`.
93
+ """
94
+
95
+ email_values = [
96
+ self.FRACTAL_EMAIL_SENDER,
97
+ self.FRACTAL_EMAIL_SMTP_SERVER,
98
+ self.FRACTAL_EMAIL_SMTP_PORT,
99
+ self.FRACTAL_EMAIL_INSTANCE_NAME,
100
+ self.FRACTAL_EMAIL_RECIPIENTS,
101
+ ]
102
+ if len(set(email_values)) == 1:
103
+ # All required EMAIL attributes are None
104
+ pass
105
+ elif None in email_values:
106
+ # Not all required EMAIL attributes are set
107
+ error_msg = (
108
+ "Invalid FRACTAL_EMAIL configuration. "
109
+ f"Given values: {email_values}."
110
+ )
111
+ raise ValueError(error_msg)
112
+ else:
113
+ use_starttls = self.FRACTAL_EMAIL_USE_STARTTLS == "true"
114
+ use_login = self.FRACTAL_EMAIL_USE_LOGIN == "true"
115
+
116
+ if use_login and self.FRACTAL_EMAIL_PASSWORD is None:
117
+ raise ValueError(
118
+ "'FRACTAL_EMAIL_USE_LOGIN' is 'true' but "
119
+ "'FRACTAL_EMAIL_PASSWORD' is not provided."
120
+ )
121
+
122
+ self.public = PublicEmailSettings(
123
+ sender=self.FRACTAL_EMAIL_SENDER,
124
+ recipients=self.FRACTAL_EMAIL_RECIPIENTS.split(","),
125
+ smtp_server=self.FRACTAL_EMAIL_SMTP_SERVER,
126
+ port=self.FRACTAL_EMAIL_SMTP_PORT,
127
+ password=self.FRACTAL_EMAIL_PASSWORD,
128
+ instance_name=self.FRACTAL_EMAIL_INSTANCE_NAME,
129
+ use_starttls=use_starttls,
130
+ use_login=use_login,
131
+ )
132
+
133
+ return self
@@ -0,0 +1,78 @@
1
+ import logging
2
+ from typing import Literal
3
+
4
+ from pydantic import HttpUrl
5
+ from pydantic import SecretStr
6
+ from pydantic_settings import BaseSettings
7
+ from pydantic_settings import SettingsConfigDict
8
+
9
+ from ._settings_config import SETTINGS_CONFIG_DICT
10
+
11
+
12
+ class Settings(BaseSettings):
13
+ """
14
+ Contains all the configuration variables for Fractal Server
15
+
16
+ The attributes of this class are set from the environment.
17
+ """
18
+
19
+ model_config = SettingsConfigDict(**SETTINGS_CONFIG_DICT)
20
+
21
+ JWT_EXPIRE_SECONDS: int = 180
22
+ """
23
+ JWT token lifetime, in seconds.
24
+ """
25
+
26
+ JWT_SECRET_KEY: SecretStr
27
+ """
28
+ JWT secret
29
+
30
+ ⚠️ **IMPORTANT**: set this variable to a secure string, and do not disclose
31
+ it.
32
+ """
33
+
34
+ COOKIE_EXPIRE_SECONDS: int = 86400
35
+ """
36
+ Cookie token lifetime, in seconds.
37
+ """
38
+
39
+ # Note: we do not use ResourceType here to avoid circular imports
40
+ FRACTAL_RUNNER_BACKEND: Literal[
41
+ "local", "slurm_ssh", "slurm_sudo"
42
+ ] = "local"
43
+ """
44
+ Select which runner backend to use.
45
+ """
46
+
47
+ FRACTAL_LOGGING_LEVEL: int = logging.INFO
48
+ """
49
+ Logging-level threshold for logging
50
+
51
+ Only logs of with this level (or higher) will appear in the console logs.
52
+ """
53
+
54
+ FRACTAL_API_MAX_JOB_LIST_LENGTH: int = 25
55
+ """
56
+ Number of ids that can be stored in the `jobsV2` attribute of
57
+ `app.state`.
58
+ """
59
+
60
+ FRACTAL_GRACEFUL_SHUTDOWN_TIME: int = 30
61
+ """
62
+ Waiting time for the shutdown phase of executors
63
+ """
64
+
65
+ FRACTAL_HELP_URL: HttpUrl | None = None
66
+ """
67
+ The URL of an instance-specific Fractal help page.
68
+ """
69
+
70
+ FRACTAL_DEFAULT_GROUP_NAME: Literal["All"] | None = None
71
+ """
72
+ Name of the default user group.
73
+
74
+ If set to `"All"`, then the user group with that name is a special user
75
+ group (e.g. it cannot be deleted, and new users are automatically added
76
+ to it). If set to `None` (the default value), then user groups are all
77
+ equivalent, independently on their name.
78
+ """
@@ -0,0 +1,69 @@
1
+ from typing import Annotated
2
+ from typing import Self
3
+
4
+ from pydantic import model_validator
5
+ from pydantic import SecretStr
6
+ from pydantic import StringConstraints
7
+ from pydantic_settings import BaseSettings
8
+ from pydantic_settings import SettingsConfigDict
9
+
10
+ from ._settings_config import SETTINGS_CONFIG_DICT
11
+ from fractal_server.types import NonEmptyStr
12
+
13
+
14
+ class OAuthSettings(BaseSettings):
15
+ """
16
+ Minimal set of configurations needed for operating on the database (e.g
17
+ for schema migrations).
18
+ """
19
+
20
+ model_config = SettingsConfigDict(**SETTINGS_CONFIG_DICT)
21
+
22
+ OAUTH_CLIENT_NAME: (
23
+ Annotated[
24
+ NonEmptyStr,
25
+ StringConstraints(to_lower=True),
26
+ ]
27
+ | None
28
+ ) = None
29
+ """
30
+ The name of the client.
31
+ """
32
+ OAUTH_CLIENT_ID: SecretStr | None = None
33
+ """
34
+ ID of client.
35
+ """
36
+ OAUTH_CLIENT_SECRET: SecretStr | None = None
37
+ """
38
+ Secret to authorise against the identity provider.
39
+ """
40
+ OAUTH_OIDC_CONFIG_ENDPOINT: SecretStr | None = None
41
+ """
42
+ OpenID configuration endpoint, for autodiscovery of relevant endpoints.
43
+ """
44
+ OAUTH_REDIRECT_URL: str | None = None
45
+ """
46
+ String to be used as `redirect_url` argument in
47
+ `fastapi_users.get_oauth_router`, and then in
48
+ `httpx_oauth.integrations.fastapi.OAuth2AuthorizeCallback`
49
+ """
50
+
51
+ @model_validator(mode="after")
52
+ def check_configuration(self: Self) -> Self:
53
+ if (
54
+ self.OAUTH_CLIENT_NAME not in ["google", "github", None]
55
+ and self.OAUTH_OIDC_CONFIG_ENDPOINT is None
56
+ ):
57
+ raise ValueError(
58
+ f"self.OAUTH_OIDC_CONFIG_ENDPOINT=None but "
59
+ f"{self.OAUTH_CLIENT_NAME=}"
60
+ )
61
+ return self
62
+
63
+ @property
64
+ def is_set(self) -> bool:
65
+ return None not in (
66
+ self.OAUTH_CLIENT_NAME,
67
+ self.OAUTH_CLIENT_ID,
68
+ self.OAUTH_CLIENT_SECRET,
69
+ )
@@ -0,0 +1,7 @@
1
+ from pathlib import Path
2
+
3
+ SETTINGS_CONFIG_DICT = dict(
4
+ case_sensitive=True,
5
+ env_file=Path(".fractal_server.env"),
6
+ extra="ignore",
7
+ )