fractal-server 2.17.0a0__tar.gz → 2.17.0a2__tar.gz

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 (267) hide show
  1. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/PKG-INFO +1 -1
  2. fractal_server-2.17.0a2/fractal_server/__init__.py +1 -0
  3. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/__main__.py +10 -8
  4. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/app/routes/api/__init__.py +9 -0
  5. fractal_server-2.17.0a2/fractal_server/app/routes/auth/oauth.py +72 -0
  6. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/app/routes/auth/router.py +4 -2
  7. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/app/routes/aux/validate_user_profile.py +4 -4
  8. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/app/schemas/v2/profile.py +8 -2
  9. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/app/schemas/v2/resource.py +32 -12
  10. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/config/__init__.py +5 -0
  11. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/config/_main.py +0 -95
  12. fractal_server-2.17.0a2/fractal_server/config/_oauth.py +69 -0
  13. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/pyproject.toml +2 -2
  14. fractal_server-2.17.0a0/fractal_server/__init__.py +0 -1
  15. fractal_server-2.17.0a0/fractal_server/app/routes/auth/oauth.py +0 -65
  16. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/LICENSE +0 -0
  17. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/README.md +0 -0
  18. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/alembic.ini +0 -0
  19. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/app/__init__.py +0 -0
  20. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/app/db/__init__.py +0 -0
  21. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/app/models/__init__.py +0 -0
  22. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/app/models/linkusergroup.py +0 -0
  23. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/app/models/linkuserproject.py +0 -0
  24. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/app/models/security.py +0 -0
  25. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/app/models/user_settings.py +0 -0
  26. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/app/models/v2/__init__.py +0 -0
  27. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/app/models/v2/accounting.py +0 -0
  28. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/app/models/v2/dataset.py +0 -0
  29. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/app/models/v2/history.py +0 -0
  30. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/app/models/v2/job.py +0 -0
  31. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/app/models/v2/profile.py +0 -0
  32. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/app/models/v2/project.py +0 -0
  33. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/app/models/v2/resource.py +0 -0
  34. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/app/models/v2/task.py +0 -0
  35. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/app/models/v2/task_group.py +0 -0
  36. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/app/models/v2/workflow.py +0 -0
  37. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/app/models/v2/workflowtask.py +0 -0
  38. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/app/routes/__init__.py +0 -0
  39. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/app/routes/admin/__init__.py +0 -0
  40. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/app/routes/admin/v2/__init__.py +0 -0
  41. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/app/routes/admin/v2/_aux_functions.py +0 -0
  42. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/app/routes/admin/v2/accounting.py +0 -0
  43. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/app/routes/admin/v2/impersonate.py +0 -0
  44. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/app/routes/admin/v2/job.py +0 -0
  45. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/app/routes/admin/v2/profile.py +0 -0
  46. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/app/routes/admin/v2/project.py +0 -0
  47. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/app/routes/admin/v2/resource.py +0 -0
  48. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/app/routes/admin/v2/task.py +0 -0
  49. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/app/routes/admin/v2/task_group.py +0 -0
  50. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/app/routes/admin/v2/task_group_lifecycle.py +0 -0
  51. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/app/routes/api/v2/__init__.py +0 -0
  52. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/app/routes/api/v2/_aux_functions.py +0 -0
  53. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/app/routes/api/v2/_aux_functions_history.py +0 -0
  54. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/app/routes/api/v2/_aux_functions_task_lifecycle.py +0 -0
  55. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/app/routes/api/v2/_aux_functions_task_version_update.py +0 -0
  56. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/app/routes/api/v2/_aux_functions_tasks.py +0 -0
  57. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/app/routes/api/v2/_aux_task_group_disambiguation.py +0 -0
  58. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/app/routes/api/v2/dataset.py +0 -0
  59. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/app/routes/api/v2/history.py +0 -0
  60. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/app/routes/api/v2/images.py +0 -0
  61. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/app/routes/api/v2/job.py +0 -0
  62. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/app/routes/api/v2/pre_submission_checks.py +0 -0
  63. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/app/routes/api/v2/project.py +0 -0
  64. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/app/routes/api/v2/status_legacy.py +0 -0
  65. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/app/routes/api/v2/submit.py +0 -0
  66. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/app/routes/api/v2/task.py +0 -0
  67. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/app/routes/api/v2/task_collection.py +0 -0
  68. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/app/routes/api/v2/task_collection_custom.py +0 -0
  69. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/app/routes/api/v2/task_collection_pixi.py +0 -0
  70. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/app/routes/api/v2/task_group.py +0 -0
  71. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/app/routes/api/v2/task_group_lifecycle.py +0 -0
  72. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/app/routes/api/v2/task_version_update.py +0 -0
  73. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/app/routes/api/v2/workflow.py +0 -0
  74. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/app/routes/api/v2/workflow_import.py +0 -0
  75. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/app/routes/api/v2/workflowtask.py +0 -0
  76. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/app/routes/auth/__init__.py +0 -0
  77. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/app/routes/auth/_aux_auth.py +0 -0
  78. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/app/routes/auth/current_user.py +0 -0
  79. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/app/routes/auth/group.py +0 -0
  80. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/app/routes/auth/login.py +0 -0
  81. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/app/routes/auth/register.py +0 -0
  82. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/app/routes/auth/users.py +0 -0
  83. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/app/routes/aux/__init__.py +0 -0
  84. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/app/routes/aux/_job.py +0 -0
  85. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/app/routes/aux/_runner.py +0 -0
  86. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/app/routes/aux/validate_user_settings.py +0 -0
  87. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/app/routes/pagination.py +0 -0
  88. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/app/schemas/__init__.py +0 -0
  89. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/app/schemas/user.py +0 -0
  90. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/app/schemas/user_group.py +0 -0
  91. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/app/schemas/user_settings.py +0 -0
  92. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/app/schemas/v2/__init__.py +0 -0
  93. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/app/schemas/v2/accounting.py +0 -0
  94. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/app/schemas/v2/dataset.py +0 -0
  95. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/app/schemas/v2/dumps.py +0 -0
  96. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/app/schemas/v2/history.py +0 -0
  97. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/app/schemas/v2/job.py +0 -0
  98. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/app/schemas/v2/manifest.py +0 -0
  99. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/app/schemas/v2/project.py +0 -0
  100. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/app/schemas/v2/status_legacy.py +0 -0
  101. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/app/schemas/v2/task.py +0 -0
  102. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/app/schemas/v2/task_collection.py +0 -0
  103. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/app/schemas/v2/task_group.py +0 -0
  104. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/app/schemas/v2/workflow.py +0 -0
  105. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/app/schemas/v2/workflowtask.py +0 -0
  106. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/app/security/__init__.py +0 -0
  107. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/app/security/signup_email.py +0 -0
  108. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/app/shutdown.py +0 -0
  109. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/app/user_settings.py +0 -0
  110. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/config/_database.py +0 -0
  111. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/config/_email.py +0 -0
  112. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/config/_init_data.py +0 -0
  113. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/config/_settings_config.py +0 -0
  114. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/data_migrations/2_14_10.py +0 -0
  115. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/data_migrations/README.md +0 -0
  116. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/data_migrations/tools.py +0 -0
  117. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/exceptions.py +0 -0
  118. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/gunicorn_fractal.py +0 -0
  119. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/images/__init__.py +0 -0
  120. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/images/models.py +0 -0
  121. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/images/status_tools.py +0 -0
  122. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/images/tools.py +0 -0
  123. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/logger.py +0 -0
  124. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/main.py +0 -0
  125. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/migrations/env.py +0 -0
  126. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/migrations/naming_convention.py +0 -0
  127. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/migrations/versions/034a469ec2eb_task_groups.py +0 -0
  128. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/migrations/versions/091b01f51f88_add_usergroup_and_linkusergroup_table.py +0 -0
  129. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/migrations/versions/0f5f85bb2ae7_add_pre_pinned_packages.py +0 -0
  130. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/migrations/versions/19eca0dd47a9_user_settings_project_dir.py +0 -0
  131. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/migrations/versions/1a83a5260664_rename.py +0 -0
  132. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/migrations/versions/1eac13a26c83_drop_v1_tables.py +0 -0
  133. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/migrations/versions/316140ff7ee1_remove_usersettings_cache_dir.py +0 -0
  134. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/migrations/versions/47351f8c7ebc_drop_dataset_filters.py +0 -0
  135. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/migrations/versions/4c308bcaea2b_add_task_args_schema_and_task_args_.py +0 -0
  136. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/migrations/versions/4cedeb448a53_workflowtask_foreign_keys_not_nullables.py +0 -0
  137. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/migrations/versions/501961cfcd85_remove_link_between_v1_and_v2_tasks_.py +0 -0
  138. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/migrations/versions/50a13d6138fd_initial_schema.py +0 -0
  139. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/migrations/versions/5bf02391cfef_v2.py +0 -0
  140. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/migrations/versions/70e77f1c38b0_add_applyworkflow_first_task_index_and_.py +0 -0
  141. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/migrations/versions/71eefd1dd202_add_slurm_accounts.py +0 -0
  142. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/migrations/versions/791ce783d3d8_add_indices.py +0 -0
  143. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/migrations/versions/84bf0fffde30_add_dumps_to_applyworkflow.py +0 -0
  144. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/migrations/versions/8e8f227a3e36_update_taskv2_post_2_7_0.py +0 -0
  145. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/migrations/versions/8f79bd162e35_add_docs_info_and_docs_link_to_task_.py +0 -0
  146. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/migrations/versions/90f6508c6379_drop_useroauth_username.py +0 -0
  147. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/migrations/versions/94a47ea2d3ff_remove_cache_dir_slurm_user_and_slurm_.py +0 -0
  148. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/migrations/versions/969d84257cac_add_historyrun_task_id.py +0 -0
  149. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/migrations/versions/97f444d47249_add_applyworkflow_project_dump.py +0 -0
  150. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/migrations/versions/981d588fe248_add_executor_error_log.py +0 -0
  151. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/migrations/versions/99ea79d9e5d2_add_dataset_history.py +0 -0
  152. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/migrations/versions/9c5ae74c9b98_add_user_settings_table.py +0 -0
  153. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/migrations/versions/9db60297b8b2_set_ondelete.py +0 -0
  154. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/migrations/versions/9fd26a2b0de4_add_workflow_timestamp_created.py +0 -0
  155. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/migrations/versions/a7f4d6137b53_add_workflow_dump_to_applyworkflow.py +0 -0
  156. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/migrations/versions/a80ac5a352bf_resource_profile.py +0 -0
  157. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/migrations/versions/af1ef1c83c9b_add_accounting_tables.py +0 -0
  158. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/migrations/versions/af8673379a5c_drop_old_filter_columns.py +0 -0
  159. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/migrations/versions/b1e7f7a1ff71_task_group_for_pixi.py +0 -0
  160. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/migrations/versions/b3ffb095f973_json_to_jsonb.py +0 -0
  161. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/migrations/versions/c90a7c76e996_job_id_in_history_run.py +0 -0
  162. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/migrations/versions/d256a7379ab8_taskgroup_activity_and_venv_info_to_.py +0 -0
  163. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/migrations/versions/d4fe3708d309_make_applyworkflow_workflow_dump_non_.py +0 -0
  164. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/migrations/versions/da2cb2ac4255_user_group_viewer_paths.py +0 -0
  165. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/migrations/versions/db09233ad13a_split_filters_and_keep_old_columns.py +0 -0
  166. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/migrations/versions/e75cac726012_make_applyworkflow_start_timestamp_not_.py +0 -0
  167. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/migrations/versions/e81103413827_add_job_type_filters.py +0 -0
  168. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/migrations/versions/efa89c30e0a4_add_project_timestamp_created.py +0 -0
  169. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/migrations/versions/f37aceb45062_make_historyunit_logfile_required.py +0 -0
  170. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/migrations/versions/f384e1c0cf5d_drop_task_default_args_columns.py +0 -0
  171. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/migrations/versions/fbce16ff4e47_new_history_items.py +0 -0
  172. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/py.typed +0 -0
  173. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/runner/__init__.py +0 -0
  174. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/runner/components.py +0 -0
  175. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/runner/config/__init__.py +0 -0
  176. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/runner/config/_local.py +0 -0
  177. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/runner/config/_slurm.py +0 -0
  178. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/runner/config/slurm_mem_to_MB.py +0 -0
  179. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/runner/exceptions.py +0 -0
  180. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/runner/executors/__init__.py +0 -0
  181. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/runner/executors/base_runner.py +0 -0
  182. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/runner/executors/call_command_wrapper.py +0 -0
  183. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/runner/executors/local/__init__.py +0 -0
  184. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/runner/executors/local/get_local_config.py +0 -0
  185. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/runner/executors/local/runner.py +0 -0
  186. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/runner/executors/slurm_common/__init__.py +0 -0
  187. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/runner/executors/slurm_common/_batching.py +0 -0
  188. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/runner/executors/slurm_common/_job_states.py +0 -0
  189. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/runner/executors/slurm_common/base_slurm_runner.py +0 -0
  190. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/runner/executors/slurm_common/get_slurm_config.py +0 -0
  191. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/runner/executors/slurm_common/remote.py +0 -0
  192. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/runner/executors/slurm_common/slurm_config.py +0 -0
  193. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/runner/executors/slurm_common/slurm_job_task_models.py +0 -0
  194. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/runner/executors/slurm_ssh/__init__.py +0 -0
  195. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/runner/executors/slurm_ssh/run_subprocess.py +0 -0
  196. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/runner/executors/slurm_ssh/runner.py +0 -0
  197. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/runner/executors/slurm_ssh/tar_commands.py +0 -0
  198. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/runner/executors/slurm_sudo/__init__.py +0 -0
  199. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/runner/executors/slurm_sudo/_subprocess_run_as_user.py +0 -0
  200. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/runner/executors/slurm_sudo/runner.py +0 -0
  201. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/runner/filenames.py +0 -0
  202. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/runner/set_start_and_last_task_index.py +0 -0
  203. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/runner/task_files.py +0 -0
  204. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/runner/v2/__init__.py +0 -0
  205. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/runner/v2/_local.py +0 -0
  206. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/runner/v2/_slurm_ssh.py +0 -0
  207. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/runner/v2/_slurm_sudo.py +0 -0
  208. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/runner/v2/db_tools.py +0 -0
  209. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/runner/v2/deduplicate_list.py +0 -0
  210. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/runner/v2/merge_outputs.py +0 -0
  211. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/runner/v2/runner.py +0 -0
  212. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/runner/v2/runner_functions.py +0 -0
  213. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/runner/v2/submit_workflow.py +0 -0
  214. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/runner/v2/task_interface.py +0 -0
  215. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/runner/versions.py +0 -0
  216. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/ssh/__init__.py +0 -0
  217. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/ssh/_fabric.py +0 -0
  218. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/string_tools.py +0 -0
  219. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/syringe.py +0 -0
  220. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/tasks/__init__.py +0 -0
  221. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/tasks/config/__init__.py +0 -0
  222. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/tasks/config/_pixi.py +0 -0
  223. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/tasks/config/_python.py +0 -0
  224. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/tasks/utils.py +0 -0
  225. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/tasks/v2/__init__.py +0 -0
  226. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/tasks/v2/local/__init__.py +0 -0
  227. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/tasks/v2/local/_utils.py +0 -0
  228. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/tasks/v2/local/collect.py +0 -0
  229. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/tasks/v2/local/collect_pixi.py +0 -0
  230. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/tasks/v2/local/deactivate.py +0 -0
  231. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/tasks/v2/local/deactivate_pixi.py +0 -0
  232. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/tasks/v2/local/delete.py +0 -0
  233. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/tasks/v2/local/reactivate.py +0 -0
  234. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/tasks/v2/local/reactivate_pixi.py +0 -0
  235. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/tasks/v2/ssh/__init__.py +0 -0
  236. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/tasks/v2/ssh/_pixi_slurm_ssh.py +0 -0
  237. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/tasks/v2/ssh/_utils.py +0 -0
  238. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/tasks/v2/ssh/collect.py +0 -0
  239. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/tasks/v2/ssh/collect_pixi.py +0 -0
  240. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/tasks/v2/ssh/deactivate.py +0 -0
  241. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/tasks/v2/ssh/deactivate_pixi.py +0 -0
  242. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/tasks/v2/ssh/delete.py +0 -0
  243. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/tasks/v2/ssh/reactivate.py +0 -0
  244. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/tasks/v2/ssh/reactivate_pixi.py +0 -0
  245. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/tasks/v2/templates/1_create_venv.sh +0 -0
  246. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/tasks/v2/templates/2_pip_install.sh +0 -0
  247. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/tasks/v2/templates/3_pip_freeze.sh +0 -0
  248. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/tasks/v2/templates/4_pip_show.sh +0 -0
  249. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/tasks/v2/templates/5_get_venv_size_and_file_number.sh +0 -0
  250. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/tasks/v2/templates/6_pip_install_from_freeze.sh +0 -0
  251. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/tasks/v2/templates/pixi_1_extract.sh +0 -0
  252. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/tasks/v2/templates/pixi_2_install.sh +0 -0
  253. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/tasks/v2/templates/pixi_3_post_install.sh +0 -0
  254. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/tasks/v2/utils_background.py +0 -0
  255. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/tasks/v2/utils_database.py +0 -0
  256. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/tasks/v2/utils_package_names.py +0 -0
  257. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/tasks/v2/utils_pixi.py +0 -0
  258. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/tasks/v2/utils_python_interpreter.py +0 -0
  259. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/tasks/v2/utils_templates.py +0 -0
  260. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/types/__init__.py +0 -0
  261. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/types/validators/__init__.py +0 -0
  262. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/types/validators/_common_validators.py +0 -0
  263. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/types/validators/_filter_validators.py +0 -0
  264. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/types/validators/_workflow_task_arguments_validators.py +0 -0
  265. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/urls.py +0 -0
  266. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/utils.py +0 -0
  267. {fractal_server-2.17.0a0 → fractal_server-2.17.0a2}/fractal_server/zip_tools.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fractal-server
3
- Version: 2.17.0a0
3
+ Version: 2.17.0a2
4
4
  Summary: Backend component of the Fractal analytics platform
5
5
  License-Expression: BSD-3-Clause
6
6
  License-File: LICENSE
@@ -0,0 +1 @@
1
+ __VERSION__ = "2.17.0a2"
@@ -136,8 +136,8 @@ def init_db_data(
136
136
  from sqlalchemy import select, func
137
137
  from fractal_server.app.models.security import UserOAuth
138
138
  from fractal_server.app.models import Resource, Profile
139
- from fractal_server.app.schemas.v2.resource import validate_resource_data
140
- from fractal_server.app.schemas.v2.profile import validate_profile_data
139
+ from fractal_server.app.schemas.v2.resource import cast_serialize_resource
140
+ from fractal_server.app.schemas.v2.profile import cast_serialize_profile
141
141
 
142
142
  init_data_settings = Inject(get_init_data_settings)
143
143
 
@@ -203,15 +203,17 @@ def init_db_data(
203
203
 
204
204
  # Validate resource/profile data
205
205
  try:
206
- validate_resource_data(resource_data)
206
+ resource_data = cast_serialize_resource(resource_data)
207
207
  except ValidationError as e:
208
- print(e)
209
- sys.exit("ERROR: Invalid resource data.")
208
+ sys.exit(
209
+ f"ERROR: Invalid resource data.\nOriginal error:\n{str(e)}"
210
+ )
210
211
  try:
211
- validate_profile_data(profile_data)
212
+ profile_data = cast_serialize_profile(profile_data)
212
213
  except ValidationError as e:
213
- print(e)
214
- sys.exit("ERROR: Invalid profile data.")
214
+ sys.exit(
215
+ f"ERROR: Invalid profile data.\nOriginal error:\n{str(e)}"
216
+ )
215
217
 
216
218
  # Create resource/profile db objects
217
219
  resource_obj = Resource(**resource_data)
@@ -9,6 +9,7 @@ from fractal_server.app.models import UserOAuth
9
9
  from fractal_server.app.routes.auth import current_active_superuser
10
10
  from fractal_server.config import get_db_settings
11
11
  from fractal_server.config import get_email_settings
12
+ from fractal_server.config import get_oauth_settings
12
13
  from fractal_server.config import get_settings
13
14
  from fractal_server.syringe import Inject
14
15
 
@@ -45,3 +46,11 @@ async def view_email_settings(
45
46
  ):
46
47
  settings = Inject(get_email_settings)
47
48
  return settings.model_dump()
49
+
50
+
51
+ @router_api.get("/settings/oauth/")
52
+ async def view_oauth_settings(
53
+ user: UserOAuth = Depends(current_active_superuser),
54
+ ):
55
+ settings = Inject(get_oauth_settings)
56
+ return settings.model_dump()
@@ -0,0 +1,72 @@
1
+ from fastapi import APIRouter
2
+ from httpx_oauth.clients.github import GitHubOAuth2
3
+ from httpx_oauth.clients.google import GoogleOAuth2
4
+ from httpx_oauth.clients.openid import OpenID
5
+
6
+ from . import cookie_backend
7
+ from . import fastapi_users
8
+ from fractal_server.config import get_oauth_settings
9
+ from fractal_server.config import get_settings
10
+ from fractal_server.config import OAuthSettings
11
+ from fractal_server.syringe import Inject
12
+
13
+
14
+ def _create_client_github(cfg: OAuthSettings) -> GitHubOAuth2:
15
+ return GitHubOAuth2(
16
+ client_id=cfg.OAUTH_CLIENT_ID.get_secret_value(),
17
+ client_secret=cfg.OAUTH_CLIENT_SECRET.get_secret_value(),
18
+ )
19
+
20
+
21
+ def _create_client_google(cfg: OAuthSettings) -> GoogleOAuth2:
22
+ return GoogleOAuth2(
23
+ client_id=cfg.OAUTH_CLIENT_ID.get_secret_value(),
24
+ client_secret=cfg.OAUTH_CLIENT_SECRET.get_secret_value(),
25
+ )
26
+
27
+
28
+ def _create_client_oidc(cfg: OAuthSettings) -> OpenID:
29
+ return OpenID(
30
+ client_id=cfg.OAUTH_CLIENT_ID.get_secret_value(),
31
+ client_secret=cfg.OAUTH_CLIENT_SECRET.get_secret_value(),
32
+ openid_configuration_endpoint=cfg.OAUTH_OIDC_CONFIG_ENDPOINT,
33
+ )
34
+
35
+
36
+ def get_oauth_router() -> APIRouter | None:
37
+ """
38
+ Get the `APIRouter` object for OAuth endpoints.
39
+ """
40
+ router_oauth = APIRouter()
41
+ settings = Inject(get_settings)
42
+ oauth_settings = Inject(get_oauth_settings)
43
+ if not oauth_settings.is_set:
44
+ return None
45
+
46
+ client_name = oauth_settings.OAUTH_CLIENT_NAME
47
+
48
+ if client_name == "google":
49
+ client = _create_client_google(oauth_settings)
50
+ elif client_name == "github":
51
+ client = _create_client_github(oauth_settings)
52
+ else:
53
+ client = _create_client_oidc(oauth_settings)
54
+
55
+ router_oauth.include_router(
56
+ fastapi_users.get_oauth_router(
57
+ client,
58
+ cookie_backend,
59
+ settings.JWT_SECRET_KEY,
60
+ is_verified_by_default=False,
61
+ associate_by_email=True,
62
+ redirect_url=oauth_settings.OAUTH_REDIRECT_URL,
63
+ ),
64
+ prefix=f"/{client_name}",
65
+ )
66
+
67
+ # Add trailing slash to all routes' paths
68
+ for route in router_oauth.routes:
69
+ if not route.path.endswith("/"):
70
+ route.path = f"{route.path}/"
71
+
72
+ return router_oauth
@@ -3,7 +3,7 @@ from fastapi import APIRouter
3
3
  from .current_user import router_current_user
4
4
  from .group import router_group
5
5
  from .login import router_login
6
- from .oauth import router_oauth
6
+ from .oauth import get_oauth_router
7
7
  from .register import router_register
8
8
  from .users import router_users
9
9
 
@@ -14,4 +14,6 @@ router_auth.include_router(router_current_user)
14
14
  router_auth.include_router(router_login)
15
15
  router_auth.include_router(router_users)
16
16
  router_auth.include_router(router_group)
17
- router_auth.include_router(router_oauth)
17
+ router_oauth = get_oauth_router()
18
+ if router_oauth is not None:
19
+ router_auth.include_router(router_oauth)
@@ -6,8 +6,8 @@ from fractal_server.app.db import AsyncSession
6
6
  from fractal_server.app.models import Profile
7
7
  from fractal_server.app.models import Resource
8
8
  from fractal_server.app.models import UserOAuth
9
- from fractal_server.app.schemas.v2.profile import validate_profile_data
10
- from fractal_server.app.schemas.v2.resource import validate_resource_data
9
+ from fractal_server.app.schemas.v2.profile import cast_serialize_profile
10
+ from fractal_server.app.schemas.v2.resource import cast_serialize_resource
11
11
  from fractal_server.logger import set_logger
12
12
 
13
13
  logger = set_logger(__name__)
@@ -38,10 +38,10 @@ async def validate_user_profile(
38
38
  profile = await db.get(Profile, user.profile_id)
39
39
  resource = await db.get(Resource, profile.resource_id)
40
40
  try:
41
- validate_resource_data(
41
+ cast_serialize_resource(
42
42
  resource.model_dump(exclude={"id", "timestamp_created"}),
43
43
  )
44
- validate_profile_data(
44
+ cast_serialize_profile(
45
45
  profile.model_dump(exclude={"resource_id", "id"}),
46
46
  )
47
47
  db.expunge(resource)
@@ -65,8 +65,14 @@ class ProfileRead(BaseModel):
65
65
 
66
66
 
67
67
  @validate_call
68
- def validate_profile_data(_data: ProfileCreate):
68
+ def cast_serialize_profile(_data: ProfileCreate) -> dict[str, Any]:
69
69
  """
70
- We use `@validate_call` because `ProfileCreate` is a `Union` type and it
70
+ Cast/serialize round-trip for `Profile` data.
71
+
72
+ We use `@validate_call` because `ProfileeCreate` is a `Union` type and it
71
73
  cannot be instantiated directly.
74
+
75
+ Return:
76
+ Serialized version of a valid profile object.
72
77
  """
78
+ return _data.model_dump()
@@ -4,6 +4,7 @@ from typing import Any
4
4
  from typing import Literal
5
5
  from typing import Self
6
6
 
7
+ from pydantic import AfterValidator
7
8
  from pydantic import BaseModel
8
9
  from pydantic import Discriminator
9
10
  from pydantic import model_validator
@@ -25,13 +26,27 @@ class ResourceType(StrEnum):
25
26
  LOCAL = "local"
26
27
 
27
28
 
29
+ def cast_serialize_pixi_settings(
30
+ v: dict[NonEmptyStr, Any],
31
+ ) -> dict[NonEmptyStr, Any]:
32
+ """
33
+ Validate current value, and enrich it with default values.
34
+ """
35
+ if v != {}:
36
+ v = TasksPixiSettings(**v).model_dump()
37
+ return v
38
+
39
+
28
40
  class _ValidResourceBase(BaseModel):
29
41
  type: ResourceType
30
42
  name: NonEmptyStr
31
43
 
32
44
  # Tasks
33
45
  tasks_python_config: TasksPythonSettings
34
- tasks_pixi_config: dict[NonEmptyStr, Any]
46
+ tasks_pixi_config: Annotated[
47
+ dict[NonEmptyStr, Any],
48
+ AfterValidator(cast_serialize_pixi_settings),
49
+ ]
35
50
  tasks_local_dir: AbsolutePathStr
36
51
 
37
52
  # Jobs
@@ -40,16 +55,15 @@ class _ValidResourceBase(BaseModel):
40
55
  jobs_poll_interval: int = 5
41
56
 
42
57
  @model_validator(mode="after")
43
- def _tasks_configurations(self) -> Self:
44
- if self.tasks_pixi_config != {}:
45
- pixi_settings = TasksPixiSettings(**self.tasks_pixi_config)
46
- if (
47
- self.type == ResourceType.SLURM_SSH
48
- and pixi_settings.SLURM_CONFIG is None
49
- ):
50
- raise ValueError(
51
- "`tasks_pixi_config` must include `SLURM_CONFIG`."
52
- )
58
+ def _pixi_slurm_config(self) -> Self:
59
+ if (
60
+ self.tasks_pixi_config != {}
61
+ and self.type == ResourceType.SLURM_SSH
62
+ and self.tasks_pixi_config["SLURM_CONFIG"] is None
63
+ ):
64
+ raise ValueError(
65
+ "`tasks_pixi_config` must include `SLURM_CONFIG`."
66
+ )
53
67
  return self
54
68
 
55
69
 
@@ -110,8 +124,14 @@ class ResourceRead(BaseModel):
110
124
 
111
125
 
112
126
  @validate_call
113
- def validate_resource_data(_data: ResourceCreate):
127
+ def cast_serialize_resource(_data: ResourceCreate) -> dict[str, Any]:
114
128
  """
129
+ Cast/serialize round-trip for `Resource` data.
130
+
115
131
  We use `@validate_call` because `ResourceCreate` is a `Union` type and it
116
132
  cannot be instantiated directly.
133
+
134
+ Return:
135
+ Serialized version of a valid resource object.
117
136
  """
137
+ return _data.model_dump()
@@ -3,6 +3,7 @@ from ._email import EmailSettings
3
3
  from ._email import PublicEmailSettings # noqa F401
4
4
  from ._init_data import InitDataSettings
5
5
  from ._main import Settings
6
+ from ._oauth import OAuthSettings
6
7
 
7
8
 
8
9
  def get_db_settings(db_settings=DatabaseSettings()) -> DatabaseSettings:
@@ -21,3 +22,7 @@ def get_init_data_settings(
21
22
  init_data_settings=InitDataSettings(),
22
23
  ) -> InitDataSettings:
23
24
  return init_data_settings
25
+
26
+
27
+ def get_oauth_settings(oauth_settings=OAuthSettings()) -> OAuthSettings:
28
+ return oauth_settings
@@ -1,12 +1,7 @@
1
1
  import logging
2
- from os import environ
3
- from os import getenv
4
2
  from typing import Literal
5
3
  from typing import TypeVar
6
4
 
7
- from pydantic import BaseModel
8
- from pydantic import Field
9
- from pydantic import model_validator
10
5
  from pydantic import SecretStr
11
6
  from pydantic_settings import BaseSettings
12
7
  from pydantic_settings import SettingsConfigDict
@@ -22,48 +17,6 @@ class FractalConfigurationError(ValueError):
22
17
  T = TypeVar("T")
23
18
 
24
19
 
25
- class OAuthClientConfig(BaseModel):
26
- """
27
- OAuth Client Config Model
28
-
29
- This model wraps the variables that define a client against an Identity
30
- Provider. As some providers are supported by the libraries used within the
31
- server, some attributes are optional.
32
-
33
- Attributes:
34
- CLIENT_NAME:
35
- The name of the client
36
- CLIENT_ID:
37
- ID of client
38
- CLIENT_SECRET:
39
- Secret to authorise against the identity provider
40
- OIDC_CONFIGURATION_ENDPOINT:
41
- OpenID configuration endpoint,
42
- allowing to discover the required endpoints automatically
43
- REDIRECT_URL:
44
- String to be used as `redirect_url` argument for
45
- `fastapi_users.get_oauth_router`, and then in
46
- `httpx_oauth.integrations.fastapi.OAuth2AuthorizeCallback`.
47
- """
48
-
49
- CLIENT_NAME: str
50
- CLIENT_ID: str
51
- CLIENT_SECRET: SecretStr
52
- OIDC_CONFIGURATION_ENDPOINT: str | None = None
53
- REDIRECT_URL: str | None = None
54
-
55
- @model_validator(mode="before")
56
- @classmethod
57
- def check_configuration(cls, values):
58
- if values.get("CLIENT_NAME") not in ["GOOGLE", "GITHUB"]:
59
- if not values.get("OIDC_CONFIGURATION_ENDPOINT"):
60
- raise FractalConfigurationError(
61
- f"Missing OAUTH_{values.get('CLIENT_NAME')}"
62
- "_OIDC_CONFIGURATION_ENDPOINT"
63
- )
64
- return values
65
-
66
-
67
20
  class Settings(BaseSettings):
68
21
  """
69
22
  Contains all the configuration variables for Fractal Server
@@ -73,8 +26,6 @@ class Settings(BaseSettings):
73
26
 
74
27
  model_config = SettingsConfigDict(**SETTINGS_CONFIG_DICT)
75
28
 
76
- OAUTH_CLIENTS_CONFIG: list[OAuthClientConfig] = Field(default_factory=list)
77
-
78
29
  # JWT TOKEN
79
30
  JWT_EXPIRE_SECONDS: int = 180
80
31
  """
@@ -95,52 +46,6 @@ class Settings(BaseSettings):
95
46
  Cookie token lifetime, in seconds.
96
47
  """
97
48
 
98
- @model_validator(mode="before")
99
- @classmethod
100
- def collect_oauth_clients(cls, values):
101
- """
102
- Automatic collection of OAuth Clients
103
-
104
- This method collects the environment variables relative to a single
105
- OAuth client and saves them within the `Settings` object in the form
106
- of an `OAuthClientConfig` instance.
107
-
108
- Fractal can support an arbitrary number of OAuth providers, which are
109
- automatically detected by parsing the environment variable names. In
110
- particular, to set the provider `FOO`, one must specify the variables
111
-
112
- OAUTH_FOO_CLIENT_ID
113
- OAUTH_FOO_CLIENT_SECRET
114
- ...
115
-
116
- etc (cf. OAuthClientConfig).
117
- """
118
- oauth_env_variable_keys = [
119
- key for key in environ.keys() if key.startswith("OAUTH_")
120
- ]
121
- clients_available = {
122
- var.split("_")[1] for var in oauth_env_variable_keys
123
- }
124
-
125
- values["OAUTH_CLIENTS_CONFIG"] = []
126
- for client in clients_available:
127
- prefix = f"OAUTH_{client}"
128
- oauth_client_config = OAuthClientConfig(
129
- CLIENT_NAME=client,
130
- CLIENT_ID=getenv(f"{prefix}_CLIENT_ID", None),
131
- CLIENT_SECRET=getenv(f"{prefix}_CLIENT_SECRET", None),
132
- OIDC_CONFIGURATION_ENDPOINT=getenv(
133
- f"{prefix}_OIDC_CONFIGURATION_ENDPOINT", None
134
- ),
135
- REDIRECT_URL=getenv(f"{prefix}_REDIRECT_URL", None),
136
- )
137
- values["OAUTH_CLIENTS_CONFIG"].append(oauth_client_config)
138
- return values
139
-
140
- ###########################################################################
141
- # FRACTAL SPECIFIC
142
- ###########################################################################
143
-
144
49
  # Note: we do not use ResourceType here to avoid circular imports
145
50
  FRACTAL_RUNNER_BACKEND: Literal[
146
51
  "local", "slurm_ssh", "slurm_sudo"
@@ -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: str | 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=} 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
+ )
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "fractal-server"
3
- version = "2.17.0a0"
3
+ version = "2.17.0a2"
4
4
  description = "Backend component of the Fractal analytics platform"
5
5
  authors = [
6
6
  { name="Tommaso Comparin", email="tommaso.comparin@exact-lab.it" },
@@ -96,7 +96,7 @@ filterwarnings = [
96
96
  markers = ["container", "ssh", "fails_on_macos"]
97
97
 
98
98
  [tool.bumpver]
99
- current_version = "2.17.0a0"
99
+ current_version = "2.17.0a2"
100
100
  version_pattern = "MAJOR.MINOR.PATCH[PYTAGNUM]"
101
101
  commit_message = "bump version {old_version} -> {new_version}"
102
102
  commit = true
@@ -1 +0,0 @@
1
- __VERSION__ = "2.17.0a0"
@@ -1,65 +0,0 @@
1
- from fastapi import APIRouter
2
-
3
- from . import cookie_backend
4
- from . import fastapi_users
5
- from ....config import get_settings
6
- from ....syringe import Inject
7
-
8
- router_oauth = APIRouter()
9
-
10
-
11
- # OAUTH CLIENTS
12
-
13
- # NOTE: settings.OAUTH_CLIENTS are collected by
14
- # Settings.collect_oauth_clients(). If no specific client is specified in the
15
- # environment variables (e.g. by setting OAUTH_FOO_CLIENT_ID and
16
- # OAUTH_FOO_CLIENT_SECRET), this list is empty
17
-
18
- # Note: dependency injection should be wrapped within a function call to make
19
- # it truly lazy. This function could then be called on startup of the FastAPI
20
- # app (cf. fractal_server.main)
21
- settings = Inject(get_settings)
22
-
23
- for client_config in settings.OAUTH_CLIENTS_CONFIG:
24
- client_name = client_config.CLIENT_NAME.lower()
25
-
26
- if client_name == "google":
27
- from httpx_oauth.clients.google import GoogleOAuth2
28
-
29
- client = GoogleOAuth2(
30
- client_config.CLIENT_ID,
31
- client_config.CLIENT_SECRET.get_secret_value(),
32
- )
33
- elif client_name == "github":
34
- from httpx_oauth.clients.github import GitHubOAuth2
35
-
36
- client = GitHubOAuth2(
37
- client_config.CLIENT_ID,
38
- client_config.CLIENT_SECRET.get_secret_value(),
39
- )
40
- else:
41
- from httpx_oauth.clients.openid import OpenID
42
-
43
- client = OpenID(
44
- client_config.CLIENT_ID,
45
- client_config.CLIENT_SECRET.get_secret_value(),
46
- client_config.OIDC_CONFIGURATION_ENDPOINT,
47
- )
48
-
49
- router_oauth.include_router(
50
- fastapi_users.get_oauth_router(
51
- client,
52
- cookie_backend,
53
- settings.JWT_SECRET_KEY,
54
- is_verified_by_default=False,
55
- associate_by_email=True,
56
- redirect_url=client_config.REDIRECT_URL,
57
- ),
58
- prefix=f"/{client_name}",
59
- )
60
-
61
-
62
- # Add trailing slash to all routes' paths
63
- for route in router_oauth.routes:
64
- if not route.path.endswith("/"):
65
- route.path = f"{route.path}/"