fractal-server 2.18.0a1__tar.gz → 2.18.0a3__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.
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/PKG-INFO +1 -1
- fractal_server-2.18.0a3/fractal_server/__init__.py +1 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/__main__.py +2 -1
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/models/security.py +7 -5
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/routes/api/__init__.py +0 -9
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/routes/api/v2/dataset.py +35 -9
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/routes/api/v2/submit.py +1 -1
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/routes/api/v2/workflowtask.py +0 -27
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/routes/auth/current_user.py +0 -63
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/routes/auth/group.py +1 -30
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/routes/auth/router.py +2 -0
- fractal_server-2.18.0a3/fractal_server/app/routes/auth/viewer_paths.py +43 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/schemas/user.py +29 -12
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/schemas/user_group.py +0 -15
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/security/__init__.py +1 -1
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/config/__init__.py +0 -6
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/config/_main.py +5 -0
- fractal_server-2.18.0a3/fractal_server/data_migrations/2_18_1.py +29 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/main.py +57 -3
- fractal_server-2.18.0a3/fractal_server/migrations/versions/7910eed4cf97_user_project_dirs_and_usergroup_viewer_.py +60 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/runner/v2/_local.py +1 -1
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/runner/v2/_slurm_ssh.py +1 -1
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/runner/v2/_slurm_sudo.py +1 -1
- fractal_server-2.18.0a3/fractal_server/tasks/v2/__init__.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/types/__init__.py +13 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/types/validators/__init__.py +1 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/types/validators/_common_validators.py +10 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/pyproject.toml +2 -2
- fractal_server-2.18.0a1/fractal_server/__init__.py +0 -1
- fractal_server-2.18.0a1/fractal_server/config/_data.py +0 -79
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/LICENSE +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/README.md +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/alembic.ini +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/__init__.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/db/__init__.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/models/__init__.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/models/linkusergroup.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/models/linkuserproject.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/models/v2/__init__.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/models/v2/accounting.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/models/v2/dataset.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/models/v2/history.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/models/v2/job.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/models/v2/profile.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/models/v2/project.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/models/v2/resource.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/models/v2/task.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/models/v2/task_group.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/models/v2/workflow.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/models/v2/workflowtask.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/routes/__init__.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/routes/admin/__init__.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/routes/admin/v2/__init__.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/routes/admin/v2/_aux_functions.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/routes/admin/v2/accounting.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/routes/admin/v2/impersonate.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/routes/admin/v2/job.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/routes/admin/v2/profile.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/routes/admin/v2/resource.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/routes/admin/v2/sharing.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/routes/admin/v2/task.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/routes/admin/v2/task_group.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/routes/admin/v2/task_group_lifecycle.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/routes/api/v2/__init__.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/routes/api/v2/_aux_functions.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/routes/api/v2/_aux_functions_history.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/routes/api/v2/_aux_functions_sharing.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/routes/api/v2/_aux_functions_task_lifecycle.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/routes/api/v2/_aux_functions_task_version_update.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/routes/api/v2/_aux_functions_tasks.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/routes/api/v2/_aux_task_group_disambiguation.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/routes/api/v2/history.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/routes/api/v2/images.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/routes/api/v2/job.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/routes/api/v2/pre_submission_checks.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/routes/api/v2/project.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/routes/api/v2/sharing.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/routes/api/v2/status_legacy.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/routes/api/v2/task.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/routes/api/v2/task_collection.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/routes/api/v2/task_collection_custom.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/routes/api/v2/task_collection_pixi.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/routes/api/v2/task_group.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/routes/api/v2/task_group_lifecycle.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/routes/api/v2/task_version_update.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/routes/api/v2/workflow.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/routes/api/v2/workflow_import.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/routes/auth/__init__.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/routes/auth/_aux_auth.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/routes/auth/login.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/routes/auth/oauth.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/routes/auth/register.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/routes/auth/users.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/routes/aux/__init__.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/routes/aux/_job.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/routes/aux/_runner.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/routes/aux/validate_user_profile.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/routes/pagination.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/schemas/__init__.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/schemas/v2/__init__.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/schemas/v2/accounting.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/schemas/v2/dataset.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/schemas/v2/dumps.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/schemas/v2/history.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/schemas/v2/job.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/schemas/v2/manifest.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/schemas/v2/profile.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/schemas/v2/project.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/schemas/v2/resource.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/schemas/v2/sharing.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/schemas/v2/status_legacy.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/schemas/v2/task.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/schemas/v2/task_collection.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/schemas/v2/task_group.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/schemas/v2/workflow.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/schemas/v2/workflowtask.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/security/signup_email.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/shutdown.py +0 -0
- /fractal_server-2.18.0a1/fractal_server/py.typed → /fractal_server-2.18.0a3/fractal_server/config/_data.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/config/_database.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/config/_email.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/config/_oauth.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/config/_settings_config.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/data_migrations/README.md +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/data_migrations/tools.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/exceptions.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/gunicorn_fractal.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/images/__init__.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/images/models.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/images/status_tools.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/images/tools.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/logger.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/migrations/env.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/migrations/naming_convention.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/migrations/versions/034a469ec2eb_task_groups.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/migrations/versions/091b01f51f88_add_usergroup_and_linkusergroup_table.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/migrations/versions/0f5f85bb2ae7_add_pre_pinned_packages.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/migrations/versions/19eca0dd47a9_user_settings_project_dir.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/migrations/versions/1a83a5260664_rename.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/migrations/versions/1eac13a26c83_drop_v1_tables.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/migrations/versions/316140ff7ee1_remove_usersettings_cache_dir.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/migrations/versions/40d6d6511b20_add_index_to_history_models.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/migrations/versions/45fbb391d7af_make_resource_id_fk_non_nullable.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/migrations/versions/47351f8c7ebc_drop_dataset_filters.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/migrations/versions/49d0856e9569_drop_table.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/migrations/versions/4c308bcaea2b_add_task_args_schema_and_task_args_.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/migrations/versions/4cedeb448a53_workflowtask_foreign_keys_not_nullables.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/migrations/versions/501961cfcd85_remove_link_between_v1_and_v2_tasks_.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/migrations/versions/50a13d6138fd_initial_schema.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/migrations/versions/5bf02391cfef_v2.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/migrations/versions/70e77f1c38b0_add_applyworkflow_first_task_index_and_.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/migrations/versions/71eefd1dd202_add_slurm_accounts.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/migrations/versions/7673fe18c05d_remove_project_dir_server_default.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/migrations/versions/791ce783d3d8_add_indices.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/migrations/versions/83bc2ad3ffcc_2_17_0.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/migrations/versions/84bf0fffde30_add_dumps_to_applyworkflow.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/migrations/versions/8e8f227a3e36_update_taskv2_post_2_7_0.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/migrations/versions/8f79bd162e35_add_docs_info_and_docs_link_to_task_.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/migrations/versions/94a47ea2d3ff_remove_cache_dir_slurm_user_and_slurm_.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/migrations/versions/969d84257cac_add_historyrun_task_id.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/migrations/versions/97f444d47249_add_applyworkflow_project_dump.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/migrations/versions/981d588fe248_add_executor_error_log.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/migrations/versions/99ea79d9e5d2_add_dataset_history.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/migrations/versions/9c5ae74c9b98_add_user_settings_table.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/migrations/versions/9db60297b8b2_set_ondelete.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/migrations/versions/9fd26a2b0de4_add_workflow_timestamp_created.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/migrations/versions/a7f4d6137b53_add_workflow_dump_to_applyworkflow.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/migrations/versions/af1ef1c83c9b_add_accounting_tables.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/migrations/versions/af8673379a5c_drop_old_filter_columns.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/migrations/versions/b1e7f7a1ff71_task_group_for_pixi.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/migrations/versions/b3ffb095f973_json_to_jsonb.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/migrations/versions/bc0e8b3327a7_project_sharing.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/migrations/versions/c90a7c76e996_job_id_in_history_run.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/migrations/versions/caba9fb1ea5e_drop_useroauth_user_settings_id.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/migrations/versions/d256a7379ab8_taskgroup_activity_and_venv_info_to_.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/migrations/versions/d4fe3708d309_make_applyworkflow_workflow_dump_non_.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/migrations/versions/da2cb2ac4255_user_group_viewer_paths.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/migrations/versions/db09233ad13a_split_filters_and_keep_old_columns.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/migrations/versions/e0e717ae2f26_delete_linkuserproject_ondelete_project.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/migrations/versions/e75cac726012_make_applyworkflow_start_timestamp_not_.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/migrations/versions/e81103413827_add_job_type_filters.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/migrations/versions/efa89c30e0a4_add_project_timestamp_created.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/migrations/versions/f37aceb45062_make_historyunit_logfile_required.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/migrations/versions/f384e1c0cf5d_drop_task_default_args_columns.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/migrations/versions/fbce16ff4e47_new_history_items.py +0 -0
- /fractal_server-2.18.0a1/fractal_server/runner/__init__.py → /fractal_server-2.18.0a3/fractal_server/py.typed +0 -0
- {fractal_server-2.18.0a1/fractal_server/runner/executors → fractal_server-2.18.0a3/fractal_server/runner}/__init__.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/runner/components.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/runner/config/__init__.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/runner/config/_local.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/runner/config/_slurm.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/runner/config/slurm_mem_to_MB.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/runner/exceptions.py +0 -0
- {fractal_server-2.18.0a1/fractal_server/runner/executors/local → fractal_server-2.18.0a3/fractal_server/runner/executors}/__init__.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/runner/executors/base_runner.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/runner/executors/call_command_wrapper.py +0 -0
- {fractal_server-2.18.0a1/fractal_server/runner/executors/slurm_common → fractal_server-2.18.0a3/fractal_server/runner/executors/local}/__init__.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/runner/executors/local/get_local_config.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/runner/executors/local/runner.py +0 -0
- {fractal_server-2.18.0a1/fractal_server/runner/executors/slurm_ssh → fractal_server-2.18.0a3/fractal_server/runner/executors/slurm_common}/__init__.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/runner/executors/slurm_common/_batching.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/runner/executors/slurm_common/_job_states.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/runner/executors/slurm_common/base_slurm_runner.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/runner/executors/slurm_common/get_slurm_config.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/runner/executors/slurm_common/remote.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/runner/executors/slurm_common/slurm_config.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/runner/executors/slurm_common/slurm_job_task_models.py +0 -0
- {fractal_server-2.18.0a1/fractal_server/runner/executors/slurm_sudo → fractal_server-2.18.0a3/fractal_server/runner/executors/slurm_ssh}/__init__.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/runner/executors/slurm_ssh/run_subprocess.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/runner/executors/slurm_ssh/runner.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/runner/executors/slurm_ssh/tar_commands.py +0 -0
- {fractal_server-2.18.0a1/fractal_server/runner/v2 → fractal_server-2.18.0a3/fractal_server/runner/executors/slurm_sudo}/__init__.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/runner/executors/slurm_sudo/_subprocess_run_as_user.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/runner/executors/slurm_sudo/runner.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/runner/filenames.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/runner/set_start_and_last_task_index.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/runner/task_files.py +0 -0
- {fractal_server-2.18.0a1/fractal_server/tasks → fractal_server-2.18.0a3/fractal_server/runner}/v2/__init__.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/runner/v2/db_tools.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/runner/v2/deduplicate_list.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/runner/v2/merge_outputs.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/runner/v2/runner.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/runner/v2/runner_functions.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/runner/v2/submit_workflow.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/runner/v2/task_interface.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/runner/versions.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/ssh/__init__.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/ssh/_fabric.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/string_tools.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/syringe.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/tasks/__init__.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/tasks/config/__init__.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/tasks/config/_pixi.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/tasks/config/_python.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/tasks/utils.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/tasks/v2/local/__init__.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/tasks/v2/local/_utils.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/tasks/v2/local/collect.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/tasks/v2/local/collect_pixi.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/tasks/v2/local/deactivate.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/tasks/v2/local/deactivate_pixi.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/tasks/v2/local/delete.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/tasks/v2/local/reactivate.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/tasks/v2/local/reactivate_pixi.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/tasks/v2/ssh/__init__.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/tasks/v2/ssh/_pixi_slurm_ssh.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/tasks/v2/ssh/_utils.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/tasks/v2/ssh/collect.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/tasks/v2/ssh/collect_pixi.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/tasks/v2/ssh/deactivate.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/tasks/v2/ssh/deactivate_pixi.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/tasks/v2/ssh/delete.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/tasks/v2/ssh/reactivate.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/tasks/v2/ssh/reactivate_pixi.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/tasks/v2/templates/1_create_venv.sh +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/tasks/v2/templates/2_pip_install.sh +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/tasks/v2/templates/3_pip_freeze.sh +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/tasks/v2/templates/4_pip_show.sh +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/tasks/v2/templates/5_get_venv_size_and_file_number.sh +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/tasks/v2/templates/6_pip_install_from_freeze.sh +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/tasks/v2/templates/pixi_1_extract.sh +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/tasks/v2/templates/pixi_2_install.sh +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/tasks/v2/templates/pixi_3_post_install.sh +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/tasks/v2/utils_background.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/tasks/v2/utils_database.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/tasks/v2/utils_package_names.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/tasks/v2/utils_pixi.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/tasks/v2/utils_python_interpreter.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/tasks/v2/utils_templates.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/types/validators/_filter_validators.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/types/validators/_workflow_task_arguments_validators.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/urls.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/utils.py +0 -0
- {fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/zip_tools.py +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__VERSION__ = "2.18.0a3"
|
|
@@ -6,7 +6,6 @@ from pydantic import EmailStr
|
|
|
6
6
|
from sqlalchemy import Column
|
|
7
7
|
from sqlalchemy import String
|
|
8
8
|
from sqlalchemy.dialects.postgresql import ARRAY
|
|
9
|
-
from sqlalchemy.dialects.postgresql import JSONB
|
|
10
9
|
from sqlalchemy.types import DateTime
|
|
11
10
|
from sqlmodel import Field
|
|
12
11
|
from sqlmodel import Relationship
|
|
@@ -113,7 +112,13 @@ class UserOAuth(SQLModel, table=True):
|
|
|
113
112
|
ondelete="RESTRICT",
|
|
114
113
|
)
|
|
115
114
|
|
|
116
|
-
|
|
115
|
+
# TODO-2.18.1: drop `project_dir`
|
|
116
|
+
project_dir: str | None = Field(default=None, nullable=True)
|
|
117
|
+
# TODO-2.18.1: `project_dirs: list[str] = Field(min_length=1)`
|
|
118
|
+
project_dirs: list[str] = Field(
|
|
119
|
+
sa_column=Column(ARRAY(String), nullable=False, server_default="{}"),
|
|
120
|
+
)
|
|
121
|
+
|
|
117
122
|
slurm_accounts: list[str] = Field(
|
|
118
123
|
sa_column=Column(ARRAY(String), server_default="{}"),
|
|
119
124
|
)
|
|
@@ -135,6 +140,3 @@ class UserGroup(SQLModel, table=True):
|
|
|
135
140
|
default_factory=get_timestamp,
|
|
136
141
|
sa_column=Column(DateTime(timezone=True), nullable=False),
|
|
137
142
|
)
|
|
138
|
-
viewer_paths: list[str] = Field(
|
|
139
|
-
sa_column=Column(JSONB, server_default="[]", nullable=False)
|
|
140
|
-
)
|
{fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/routes/api/__init__.py
RENAMED
|
@@ -8,7 +8,6 @@ from fastapi import Depends
|
|
|
8
8
|
import fractal_server
|
|
9
9
|
from fractal_server.app.models import UserOAuth
|
|
10
10
|
from fractal_server.app.routes.auth import current_superuser_act
|
|
11
|
-
from fractal_server.config import get_data_settings
|
|
12
11
|
from fractal_server.config import get_db_settings
|
|
13
12
|
from fractal_server.config import get_email_settings
|
|
14
13
|
from fractal_server.config import get_oauth_settings
|
|
@@ -50,14 +49,6 @@ async def view_email_settings(
|
|
|
50
49
|
return settings.model_dump()
|
|
51
50
|
|
|
52
51
|
|
|
53
|
-
@router_api.get("/settings/data/")
|
|
54
|
-
async def view_data_settings(
|
|
55
|
-
user: UserOAuth = Depends(current_superuser_act),
|
|
56
|
-
):
|
|
57
|
-
settings = Inject(get_data_settings)
|
|
58
|
-
return settings.model_dump()
|
|
59
|
-
|
|
60
|
-
|
|
61
52
|
@router_api.get("/settings/oauth/")
|
|
62
53
|
async def view_oauth_settings(
|
|
63
54
|
user: UserOAuth = Depends(current_superuser_act),
|
{fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/routes/api/v2/dataset.py
RENAMED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
|
|
1
3
|
from fastapi import APIRouter
|
|
2
4
|
from fastapi import Depends
|
|
3
5
|
from fastapi import HTTPException
|
|
@@ -58,7 +60,7 @@ async def create_dataset(
|
|
|
58
60
|
await db.commit()
|
|
59
61
|
await db.refresh(db_dataset)
|
|
60
62
|
path = (
|
|
61
|
-
f"{user.
|
|
63
|
+
f"{user.project_dirs[0]}/fractal/"
|
|
62
64
|
f"{project_id}_{sanitize_string(project.name)}/"
|
|
63
65
|
f"{db_dataset.id}_{sanitize_string(db_dataset.name)}"
|
|
64
66
|
)
|
|
@@ -69,6 +71,18 @@ async def create_dataset(
|
|
|
69
71
|
await db.commit()
|
|
70
72
|
await db.refresh(db_dataset)
|
|
71
73
|
else:
|
|
74
|
+
if not any(
|
|
75
|
+
Path(dataset.zarr_dir).is_relative_to(project_dir)
|
|
76
|
+
for project_dir in user.project_dirs
|
|
77
|
+
):
|
|
78
|
+
raise HTTPException(
|
|
79
|
+
status_code=status.HTTP_422_UNPROCESSABLE_CONTENT,
|
|
80
|
+
detail=(
|
|
81
|
+
"Dataset zarr_dir is not relative to any of the user "
|
|
82
|
+
"project directories."
|
|
83
|
+
),
|
|
84
|
+
)
|
|
85
|
+
|
|
72
86
|
db_dataset = DatasetV2(project_id=project_id, **dataset.model_dump())
|
|
73
87
|
db.add(db_dataset)
|
|
74
88
|
await db.commit()
|
|
@@ -154,14 +168,26 @@ async def update_dataset(
|
|
|
154
168
|
)
|
|
155
169
|
db_dataset = output["dataset"]
|
|
156
170
|
|
|
157
|
-
if
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
171
|
+
if dataset_update.zarr_dir is not None:
|
|
172
|
+
if db_dataset.images:
|
|
173
|
+
raise HTTPException(
|
|
174
|
+
status_code=status.HTTP_422_UNPROCESSABLE_CONTENT,
|
|
175
|
+
detail=(
|
|
176
|
+
"Cannot modify `zarr_dir` because the dataset has a "
|
|
177
|
+
"non-empty image list."
|
|
178
|
+
),
|
|
179
|
+
)
|
|
180
|
+
if not any(
|
|
181
|
+
Path(dataset_update.zarr_dir).is_relative_to(project_dir)
|
|
182
|
+
for project_dir in user.project_dirs
|
|
183
|
+
):
|
|
184
|
+
raise HTTPException(
|
|
185
|
+
status_code=status.HTTP_422_UNPROCESSABLE_CONTENT,
|
|
186
|
+
detail=(
|
|
187
|
+
"Dataset zarr_dir is not relative to any of the user "
|
|
188
|
+
"project directories."
|
|
189
|
+
),
|
|
190
|
+
)
|
|
165
191
|
|
|
166
192
|
for key, value in dataset_update.model_dump(exclude_unset=True).items():
|
|
167
193
|
setattr(db_dataset, key, value)
|
{fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/routes/api/v2/submit.py
RENAMED
|
@@ -238,7 +238,7 @@ async def apply_workflow(
|
|
|
238
238
|
)
|
|
239
239
|
|
|
240
240
|
# Define user-side job directory
|
|
241
|
-
cache_dir = Path(user.
|
|
241
|
+
cache_dir = Path(user.project_dirs[0], FRACTAL_CACHE_DIR)
|
|
242
242
|
match resource.type:
|
|
243
243
|
case ResourceType.LOCAL:
|
|
244
244
|
WORKFLOW_DIR_REMOTE = WORKFLOW_DIR_LOCAL
|
{fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/routes/api/v2/workflowtask.py
RENAMED
|
@@ -5,12 +5,10 @@ from fastapi import Depends
|
|
|
5
5
|
from fastapi import HTTPException
|
|
6
6
|
from fastapi import Response
|
|
7
7
|
from fastapi import status
|
|
8
|
-
from sqlmodel import select
|
|
9
8
|
|
|
10
9
|
from fractal_server.app.db import AsyncSession
|
|
11
10
|
from fractal_server.app.db import get_async_db
|
|
12
11
|
from fractal_server.app.models import UserOAuth
|
|
13
|
-
from fractal_server.app.models.linkuserproject import LinkUserProjectV2
|
|
14
12
|
from fractal_server.app.routes.auth import current_user_act_ver_prof
|
|
15
13
|
from fractal_server.app.schemas.v2 import TaskType
|
|
16
14
|
from fractal_server.app.schemas.v2 import WorkflowTaskCreateV2
|
|
@@ -53,31 +51,6 @@ async def create_workflowtask(
|
|
|
53
51
|
db=db,
|
|
54
52
|
)
|
|
55
53
|
|
|
56
|
-
res = await db.execute(
|
|
57
|
-
select(UserOAuth.id)
|
|
58
|
-
.join(LinkUserProjectV2, LinkUserProjectV2.user_id == UserOAuth.id)
|
|
59
|
-
.where(LinkUserProjectV2.project_id == project_id)
|
|
60
|
-
.where(LinkUserProjectV2.is_owner.is_(True))
|
|
61
|
-
)
|
|
62
|
-
project_owner_id = res.scalar_one()
|
|
63
|
-
if project_owner_id != user.id:
|
|
64
|
-
try:
|
|
65
|
-
await _get_task_read_access(
|
|
66
|
-
task_id=task_id,
|
|
67
|
-
user_id=project_owner_id,
|
|
68
|
-
db=db,
|
|
69
|
-
require_active=True,
|
|
70
|
-
)
|
|
71
|
-
except HTTPException as e:
|
|
72
|
-
raise (
|
|
73
|
-
HTTPException(
|
|
74
|
-
status_code=status.HTTP_422_UNPROCESSABLE_CONTENT,
|
|
75
|
-
detail="The task must be accessible to the project owner.",
|
|
76
|
-
)
|
|
77
|
-
if e.status_code == 403
|
|
78
|
-
else e
|
|
79
|
-
)
|
|
80
|
-
|
|
81
54
|
task = await _get_task_read_access(
|
|
82
55
|
task_id=task_id, user_id=user.id, db=db, require_active=True
|
|
83
56
|
)
|
{fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/routes/auth/current_user.py
RENAMED
|
@@ -2,21 +2,16 @@
|
|
|
2
2
|
Definition of `/auth/current-user/` endpoints
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
|
-
import os
|
|
6
|
-
|
|
7
5
|
from fastapi import APIRouter
|
|
8
6
|
from fastapi import Depends
|
|
9
7
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
10
8
|
from sqlmodel import select
|
|
11
9
|
|
|
12
10
|
from fractal_server.app.db import get_async_db
|
|
13
|
-
from fractal_server.app.models import LinkUserGroup
|
|
14
11
|
from fractal_server.app.models import Profile
|
|
15
12
|
from fractal_server.app.models import Resource
|
|
16
|
-
from fractal_server.app.models import UserGroup
|
|
17
13
|
from fractal_server.app.models import UserOAuth
|
|
18
14
|
from fractal_server.app.routes.auth import current_user_act
|
|
19
|
-
from fractal_server.app.routes.auth import current_user_act_ver
|
|
20
15
|
from fractal_server.app.routes.auth._aux_auth import (
|
|
21
16
|
_get_single_user_with_groups,
|
|
22
17
|
)
|
|
@@ -26,9 +21,6 @@ from fractal_server.app.schemas.user import UserUpdate
|
|
|
26
21
|
from fractal_server.app.schemas.user import UserUpdateStrict
|
|
27
22
|
from fractal_server.app.security import UserManager
|
|
28
23
|
from fractal_server.app.security import get_user_manager
|
|
29
|
-
from fractal_server.config import DataAuthScheme
|
|
30
|
-
from fractal_server.config import get_data_settings
|
|
31
|
-
from fractal_server.syringe import Inject
|
|
32
24
|
|
|
33
25
|
router_current_user = APIRouter()
|
|
34
26
|
|
|
@@ -106,58 +98,3 @@ async def get_current_user_profile_info(
|
|
|
106
98
|
)
|
|
107
99
|
|
|
108
100
|
return response_data
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
@router_current_user.get(
|
|
112
|
-
"/current-user/allowed-viewer-paths/", response_model=list[str]
|
|
113
|
-
)
|
|
114
|
-
async def get_current_user_allowed_viewer_paths(
|
|
115
|
-
current_user: UserOAuth = Depends(current_user_act_ver),
|
|
116
|
-
db: AsyncSession = Depends(get_async_db),
|
|
117
|
-
) -> list[str]:
|
|
118
|
-
"""
|
|
119
|
-
Returns the allowed viewer paths for current user, according to the
|
|
120
|
-
selected FRACTAL_DATA_AUTH_SCHEME
|
|
121
|
-
"""
|
|
122
|
-
|
|
123
|
-
data_settings = Inject(get_data_settings)
|
|
124
|
-
|
|
125
|
-
authorized_paths = []
|
|
126
|
-
|
|
127
|
-
if data_settings.FRACTAL_DATA_AUTH_SCHEME == DataAuthScheme.NONE:
|
|
128
|
-
return authorized_paths
|
|
129
|
-
|
|
130
|
-
# Append `project_dir` to the list of authorized paths
|
|
131
|
-
authorized_paths.append(current_user.project_dir)
|
|
132
|
-
|
|
133
|
-
# If auth scheme is "users-folders" and `slurm_user` is set,
|
|
134
|
-
# build and append the user folder
|
|
135
|
-
if (
|
|
136
|
-
data_settings.FRACTAL_DATA_AUTH_SCHEME == DataAuthScheme.USERS_FOLDERS
|
|
137
|
-
and current_user.profile_id is not None
|
|
138
|
-
):
|
|
139
|
-
profile = await db.get(Profile, current_user.profile_id)
|
|
140
|
-
if profile is not None and profile.username is not None:
|
|
141
|
-
base_folder = data_settings.FRACTAL_DATA_BASE_FOLDER
|
|
142
|
-
user_folder = os.path.join(base_folder, profile.username)
|
|
143
|
-
authorized_paths.append(user_folder)
|
|
144
|
-
|
|
145
|
-
if data_settings.FRACTAL_DATA_AUTH_SCHEME == DataAuthScheme.VIEWER_PATHS:
|
|
146
|
-
# Returns the union of `viewer_paths` for all user's groups
|
|
147
|
-
cmd = (
|
|
148
|
-
select(UserGroup.viewer_paths)
|
|
149
|
-
.join(LinkUserGroup, LinkUserGroup.group_id == UserGroup.id)
|
|
150
|
-
.where(LinkUserGroup.user_id == current_user.id)
|
|
151
|
-
)
|
|
152
|
-
res = await db.execute(cmd)
|
|
153
|
-
viewer_paths_nested = res.scalars().all()
|
|
154
|
-
|
|
155
|
-
# Flatten a nested object and make its elements unique
|
|
156
|
-
all_viewer_paths_set = {
|
|
157
|
-
path
|
|
158
|
-
for _viewer_paths in viewer_paths_nested
|
|
159
|
-
for path in _viewer_paths
|
|
160
|
-
}
|
|
161
|
-
authorized_paths.extend(all_viewer_paths_set)
|
|
162
|
-
|
|
163
|
-
return authorized_paths
|
|
@@ -16,7 +16,6 @@ from fractal_server.app.models import UserGroup
|
|
|
16
16
|
from fractal_server.app.models import UserOAuth
|
|
17
17
|
from fractal_server.app.schemas.user_group import UserGroupCreate
|
|
18
18
|
from fractal_server.app.schemas.user_group import UserGroupRead
|
|
19
|
-
from fractal_server.app.schemas.user_group import UserGroupUpdate
|
|
20
19
|
from fractal_server.config import get_settings
|
|
21
20
|
from fractal_server.logger import set_logger
|
|
22
21
|
from fractal_server.syringe import Inject
|
|
@@ -101,41 +100,13 @@ async def create_single_group(
|
|
|
101
100
|
)
|
|
102
101
|
|
|
103
102
|
# Create and return new group
|
|
104
|
-
new_group = UserGroup(
|
|
105
|
-
name=group_create.name, viewer_paths=group_create.viewer_paths
|
|
106
|
-
)
|
|
103
|
+
new_group = UserGroup(name=group_create.name)
|
|
107
104
|
db.add(new_group)
|
|
108
105
|
await db.commit()
|
|
109
106
|
|
|
110
107
|
return dict(new_group.model_dump(), user_ids=[])
|
|
111
108
|
|
|
112
109
|
|
|
113
|
-
@router_group.patch(
|
|
114
|
-
"/group/{group_id}/",
|
|
115
|
-
response_model=UserGroupRead,
|
|
116
|
-
status_code=status.HTTP_200_OK,
|
|
117
|
-
)
|
|
118
|
-
async def update_single_group(
|
|
119
|
-
group_id: int,
|
|
120
|
-
group_update: UserGroupUpdate,
|
|
121
|
-
user: UserOAuth = Depends(current_superuser_act),
|
|
122
|
-
db: AsyncSession = Depends(get_async_db),
|
|
123
|
-
) -> UserGroupRead:
|
|
124
|
-
group = await _usergroup_or_404(group_id, db)
|
|
125
|
-
|
|
126
|
-
# Patch `viewer_paths`
|
|
127
|
-
if group_update.viewer_paths is not None:
|
|
128
|
-
group.viewer_paths = group_update.viewer_paths
|
|
129
|
-
db.add(group)
|
|
130
|
-
await db.commit()
|
|
131
|
-
|
|
132
|
-
updated_group = await _get_single_usergroup_with_user_ids(
|
|
133
|
-
group_id=group_id, db=db
|
|
134
|
-
)
|
|
135
|
-
|
|
136
|
-
return updated_group
|
|
137
|
-
|
|
138
|
-
|
|
139
110
|
@router_group.delete("/group/{group_id}/", status_code=204)
|
|
140
111
|
async def delete_single_group(
|
|
141
112
|
group_id: int,
|
{fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/routes/auth/router.py
RENAMED
|
@@ -6,6 +6,7 @@ from .login import router_login
|
|
|
6
6
|
from .oauth import get_oauth_router
|
|
7
7
|
from .register import router_register
|
|
8
8
|
from .users import router_users
|
|
9
|
+
from .viewer_paths import router_viewer_paths
|
|
9
10
|
|
|
10
11
|
router_auth = APIRouter()
|
|
11
12
|
|
|
@@ -14,6 +15,7 @@ router_auth.include_router(router_current_user)
|
|
|
14
15
|
router_auth.include_router(router_login)
|
|
15
16
|
router_auth.include_router(router_users)
|
|
16
17
|
router_auth.include_router(router_group)
|
|
18
|
+
router_auth.include_router(router_viewer_paths)
|
|
17
19
|
router_oauth = get_oauth_router()
|
|
18
20
|
if router_oauth is not None:
|
|
19
21
|
router_auth.include_router(router_oauth)
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
from fastapi import APIRouter
|
|
2
|
+
from fastapi import Depends
|
|
3
|
+
from sqlalchemy.ext.asyncio import AsyncSession
|
|
4
|
+
from sqlmodel import select
|
|
5
|
+
|
|
6
|
+
from fractal_server.app.db import get_async_db
|
|
7
|
+
from fractal_server.app.models import UserOAuth
|
|
8
|
+
from fractal_server.app.models.linkuserproject import LinkUserProjectV2
|
|
9
|
+
from fractal_server.app.models.v2.dataset import DatasetV2
|
|
10
|
+
from fractal_server.app.models.v2.project import ProjectV2
|
|
11
|
+
from fractal_server.app.routes.auth import current_user_act_ver
|
|
12
|
+
|
|
13
|
+
router_viewer_paths = APIRouter()
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@router_viewer_paths.get(
|
|
17
|
+
"/current-user/allowed-viewer-paths/", response_model=list[str]
|
|
18
|
+
)
|
|
19
|
+
async def get_current_user_allowed_viewer_paths(
|
|
20
|
+
include_shared_projects: bool = True,
|
|
21
|
+
current_user: UserOAuth = Depends(current_user_act_ver),
|
|
22
|
+
db: AsyncSession = Depends(get_async_db),
|
|
23
|
+
) -> list[str]:
|
|
24
|
+
"""
|
|
25
|
+
Returns the allowed viewer paths for current user.
|
|
26
|
+
"""
|
|
27
|
+
authorized_paths = current_user.project_dirs.copy()
|
|
28
|
+
|
|
29
|
+
if include_shared_projects:
|
|
30
|
+
res = await db.execute(
|
|
31
|
+
select(DatasetV2.zarr_dir)
|
|
32
|
+
.join(ProjectV2, ProjectV2.id == DatasetV2.project_id)
|
|
33
|
+
.join(
|
|
34
|
+
LinkUserProjectV2, LinkUserProjectV2.project_id == ProjectV2.id
|
|
35
|
+
)
|
|
36
|
+
.where(LinkUserProjectV2.user_id == current_user.id)
|
|
37
|
+
.where(LinkUserProjectV2.is_owner.is_(False))
|
|
38
|
+
)
|
|
39
|
+
authorized_paths.extend(res.unique().scalars().all())
|
|
40
|
+
# Note that `project_dirs` and the `db.execute` result may have some
|
|
41
|
+
# common elements, and then this list may have non-unique items.
|
|
42
|
+
|
|
43
|
+
return authorized_paths
|
|
@@ -8,12 +8,18 @@ from pydantic import EmailStr
|
|
|
8
8
|
from pydantic import Field
|
|
9
9
|
|
|
10
10
|
from fractal_server.string_tools import validate_cmd
|
|
11
|
-
from fractal_server.types import
|
|
11
|
+
from fractal_server.types import ListUniqueAbsolutePathStr
|
|
12
12
|
from fractal_server.types import ListUniqueNonEmptyString
|
|
13
13
|
from fractal_server.types import ListUniqueNonNegativeInt
|
|
14
14
|
from fractal_server.types import NonEmptyStr
|
|
15
15
|
|
|
16
16
|
|
|
17
|
+
def _validate_cmd_list(value: list[str]) -> list[str]:
|
|
18
|
+
for v in value:
|
|
19
|
+
validate_cmd(v)
|
|
20
|
+
return value
|
|
21
|
+
|
|
22
|
+
|
|
17
23
|
class OAuthAccountRead(BaseModel):
|
|
18
24
|
"""
|
|
19
25
|
Schema for storing essential `OAuthAccount` information within
|
|
@@ -38,20 +44,17 @@ class UserRead(schemas.BaseUser[int]):
|
|
|
38
44
|
group_ids_names:
|
|
39
45
|
oauth_accounts:
|
|
40
46
|
profile_id:
|
|
47
|
+
project_dirs:
|
|
48
|
+
slurm_accounts:
|
|
41
49
|
"""
|
|
42
50
|
|
|
43
51
|
group_ids_names: list[tuple[int, str]] | None = None
|
|
44
52
|
oauth_accounts: list[OAuthAccountRead]
|
|
45
53
|
profile_id: int | None = None
|
|
46
|
-
|
|
54
|
+
project_dirs: list[str]
|
|
47
55
|
slurm_accounts: list[str]
|
|
48
56
|
|
|
49
57
|
|
|
50
|
-
def _validate_cmd(value: str) -> str:
|
|
51
|
-
validate_cmd(value)
|
|
52
|
-
return value
|
|
53
|
-
|
|
54
|
-
|
|
55
58
|
class UserUpdate(schemas.BaseUserUpdate):
|
|
56
59
|
"""
|
|
57
60
|
Schema for `User` update.
|
|
@@ -63,7 +66,7 @@ class UserUpdate(schemas.BaseUserUpdate):
|
|
|
63
66
|
is_superuser:
|
|
64
67
|
is_verified:
|
|
65
68
|
profile_id:
|
|
66
|
-
|
|
69
|
+
project_dirs:
|
|
67
70
|
slurm_accounts:
|
|
68
71
|
"""
|
|
69
72
|
|
|
@@ -74,9 +77,9 @@ class UserUpdate(schemas.BaseUserUpdate):
|
|
|
74
77
|
is_superuser: bool = None
|
|
75
78
|
is_verified: bool = None
|
|
76
79
|
profile_id: int | None = None
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
+
project_dirs: Annotated[
|
|
81
|
+
ListUniqueAbsolutePathStr, AfterValidator(_validate_cmd_list)
|
|
82
|
+
] = None
|
|
80
83
|
slurm_accounts: ListUniqueNonEmptyString = None
|
|
81
84
|
|
|
82
85
|
|
|
@@ -98,10 +101,14 @@ class UserCreate(schemas.BaseUserCreate):
|
|
|
98
101
|
|
|
99
102
|
Attributes:
|
|
100
103
|
profile_id:
|
|
104
|
+
project_dirs:
|
|
105
|
+
slurm_accounts:
|
|
101
106
|
"""
|
|
102
107
|
|
|
103
108
|
profile_id: int | None = None
|
|
104
|
-
|
|
109
|
+
project_dirs: Annotated[
|
|
110
|
+
ListUniqueAbsolutePathStr, AfterValidator(_validate_cmd_list)
|
|
111
|
+
] = Field(min_length=1)
|
|
105
112
|
slurm_accounts: list[str] = Field(default_factory=list)
|
|
106
113
|
|
|
107
114
|
|
|
@@ -109,6 +116,8 @@ class UserUpdateGroups(BaseModel):
|
|
|
109
116
|
"""
|
|
110
117
|
Schema for `POST /auth/users/{user_id}/set-groups/`
|
|
111
118
|
|
|
119
|
+
Attributes:
|
|
120
|
+
group_ids:
|
|
112
121
|
"""
|
|
113
122
|
|
|
114
123
|
model_config = ConfigDict(extra="forbid")
|
|
@@ -117,6 +126,14 @@ class UserUpdateGroups(BaseModel):
|
|
|
117
126
|
|
|
118
127
|
|
|
119
128
|
class UserProfileInfo(BaseModel):
|
|
129
|
+
"""
|
|
130
|
+
Attributes:
|
|
131
|
+
has_profile:
|
|
132
|
+
resource_name:
|
|
133
|
+
profile_name:
|
|
134
|
+
username:
|
|
135
|
+
"""
|
|
136
|
+
|
|
120
137
|
has_profile: bool
|
|
121
138
|
resource_name: str | None = None
|
|
122
139
|
profile_name: str | None = None
|
{fractal_server-2.18.0a1 → fractal_server-2.18.0a3}/fractal_server/app/schemas/user_group.py
RENAMED
|
@@ -2,16 +2,13 @@ from datetime import datetime
|
|
|
2
2
|
|
|
3
3
|
from pydantic import BaseModel
|
|
4
4
|
from pydantic import ConfigDict
|
|
5
|
-
from pydantic import Field
|
|
6
5
|
from pydantic import field_serializer
|
|
7
6
|
from pydantic.types import AwareDatetime
|
|
8
7
|
|
|
9
|
-
from fractal_server.types import ListUniqueAbsolutePathStr
|
|
10
8
|
from fractal_server.types import NonEmptyStr
|
|
11
9
|
|
|
12
10
|
__all__ = (
|
|
13
11
|
"UserGroupRead",
|
|
14
|
-
"UserGroupUpdate",
|
|
15
12
|
"UserGroupCreate",
|
|
16
13
|
)
|
|
17
14
|
|
|
@@ -34,7 +31,6 @@ class UserGroupRead(BaseModel):
|
|
|
34
31
|
name: str
|
|
35
32
|
timestamp_created: AwareDatetime
|
|
36
33
|
user_ids: list[int] | None = None
|
|
37
|
-
viewer_paths: list[str]
|
|
38
34
|
|
|
39
35
|
@field_serializer("timestamp_created")
|
|
40
36
|
def serialize_datetime(v: datetime) -> str:
|
|
@@ -52,14 +48,3 @@ class UserGroupCreate(BaseModel):
|
|
|
52
48
|
model_config = ConfigDict(extra="forbid")
|
|
53
49
|
|
|
54
50
|
name: NonEmptyStr
|
|
55
|
-
viewer_paths: ListUniqueAbsolutePathStr = Field(default_factory=list)
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
class UserGroupUpdate(BaseModel):
|
|
59
|
-
"""
|
|
60
|
-
Schema for `UserGroup` update
|
|
61
|
-
"""
|
|
62
|
-
|
|
63
|
-
model_config = ConfigDict(extra="forbid")
|
|
64
|
-
|
|
65
|
-
viewer_paths: ListUniqueAbsolutePathStr = None
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
from ._data import DataAuthScheme # noqa F401
|
|
2
|
-
from ._data import DataSettings
|
|
3
1
|
from ._database import DatabaseSettings
|
|
4
2
|
from ._email import EmailSettings
|
|
5
3
|
from ._email import PublicEmailSettings # noqa F401
|
|
@@ -21,7 +19,3 @@ def get_email_settings(email_settings=EmailSettings()) -> EmailSettings:
|
|
|
21
19
|
|
|
22
20
|
def get_oauth_settings(oauth_settings=OAuthSettings()) -> OAuthSettings:
|
|
23
21
|
return oauth_settings
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
def get_data_settings(data_settings=DataSettings()) -> DataSettings:
|
|
27
|
-
return data_settings
|
|
@@ -41,6 +41,10 @@ class Settings(BaseSettings):
|
|
|
41
41
|
user group (e.g. it cannot be deleted, and new users are
|
|
42
42
|
automatically added to it). If set to `None` (the default value),
|
|
43
43
|
then user groups are all equivalent, independently on their name.
|
|
44
|
+
FRACTAL_LONG_REQUEST_TIME:
|
|
45
|
+
Time limit beyond which the execution of an API request is
|
|
46
|
+
considered *slow* and an appropriate warning is logged by the
|
|
47
|
+
middleware.
|
|
44
48
|
"""
|
|
45
49
|
|
|
46
50
|
model_config = SettingsConfigDict(**SETTINGS_CONFIG_DICT)
|
|
@@ -57,3 +61,4 @@ class Settings(BaseSettings):
|
|
|
57
61
|
FRACTAL_GRACEFUL_SHUTDOWN_TIME: float = 30.0
|
|
58
62
|
FRACTAL_HELP_URL: HttpUrl | None = None
|
|
59
63
|
FRACTAL_DEFAULT_GROUP_NAME: Literal["All"] | None = None
|
|
64
|
+
FRACTAL_LONG_REQUEST_TIME: float = 30.0
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import sys
|
|
3
|
+
|
|
4
|
+
from sqlalchemy.orm.attributes import flag_modified
|
|
5
|
+
from sqlmodel import select
|
|
6
|
+
|
|
7
|
+
from fractal_server.app.db import get_sync_db
|
|
8
|
+
from fractal_server.app.models import UserOAuth
|
|
9
|
+
|
|
10
|
+
logging.basicConfig(level=logging.INFO)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def fix_db():
|
|
14
|
+
logging.info("START - fix db")
|
|
15
|
+
|
|
16
|
+
with next(get_sync_db()) as db:
|
|
17
|
+
res = db.execute(select(UserOAuth).order_by(UserOAuth.email))
|
|
18
|
+
user_list = res.scalars().unique().all()
|
|
19
|
+
|
|
20
|
+
for user in user_list:
|
|
21
|
+
logging.info(f"Now handling user {user.email}.")
|
|
22
|
+
if user.project_dirs != []:
|
|
23
|
+
sys.exit(f"Non empty `project_dirs` for User[{user.id}]")
|
|
24
|
+
user.project_dirs.append(user.project_dir)
|
|
25
|
+
flag_modified(user, "project_dirs")
|
|
26
|
+
|
|
27
|
+
db.commit()
|
|
28
|
+
|
|
29
|
+
logging.info("END - fix db")
|