cornflow 1.2.3a4__tar.gz → 1.2.3a5__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 (185) hide show
  1. {cornflow-1.2.3a4/cornflow.egg-info → cornflow-1.2.3a5}/PKG-INFO +2 -2
  2. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/commands/auxiliar.py +8 -2
  3. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/commands/permissions.py +27 -8
  4. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/commands/roles.py +1 -1
  5. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/shared/const.py +1 -1
  6. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/tests/unit/test_external_role_creation.py +246 -0
  7. {cornflow-1.2.3a4 → cornflow-1.2.3a5/cornflow.egg-info}/PKG-INFO +2 -2
  8. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow.egg-info/requires.txt +1 -1
  9. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/requirements.txt +1 -1
  10. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/setup.py +1 -1
  11. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/MANIFEST.in +0 -0
  12. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/README.rst +0 -0
  13. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/airflow_config/__init__.py +0 -0
  14. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/airflow_config/airflow_local_settings.py +0 -0
  15. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/airflow_config/plugins/XCom/__init__.py +0 -0
  16. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/airflow_config/plugins/XCom/gce_xcom_backend.py +0 -0
  17. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/airflow_config/plugins/__init__.py +0 -0
  18. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/airflow_config/webserver_ldap.py +0 -0
  19. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/__init__.py +0 -0
  20. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/app.py +0 -0
  21. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/cli/__init__.py +0 -0
  22. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/cli/actions.py +0 -0
  23. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/cli/arguments.py +0 -0
  24. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/cli/config.py +0 -0
  25. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/cli/migrations.py +0 -0
  26. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/cli/permissions.py +0 -0
  27. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/cli/roles.py +0 -0
  28. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/cli/schemas.py +0 -0
  29. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/cli/service.py +0 -0
  30. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/cli/tools/__init__.py +0 -0
  31. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/cli/tools/api_generator.py +0 -0
  32. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/cli/tools/endpoint_tools.py +0 -0
  33. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/cli/tools/models_tools.py +0 -0
  34. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/cli/tools/schema_generator.py +0 -0
  35. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/cli/tools/schemas_tools.py +0 -0
  36. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/cli/tools/tools.py +0 -0
  37. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/cli/users.py +0 -0
  38. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/cli/utils.py +0 -0
  39. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/cli/views.py +0 -0
  40. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/commands/__init__.py +0 -0
  41. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/commands/access.py +0 -0
  42. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/commands/actions.py +0 -0
  43. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/commands/cleanup.py +0 -0
  44. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/commands/dag.py +0 -0
  45. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/commands/schemas.py +0 -0
  46. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/commands/users.py +0 -0
  47. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/commands/views.py +0 -0
  48. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/config.py +0 -0
  49. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/endpoints/__init__.py +0 -0
  50. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/endpoints/action.py +0 -0
  51. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/endpoints/alarms.py +0 -0
  52. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/endpoints/apiview.py +0 -0
  53. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/endpoints/case.py +0 -0
  54. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/endpoints/dag.py +0 -0
  55. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/endpoints/data_check.py +0 -0
  56. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/endpoints/example_data.py +0 -0
  57. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/endpoints/execution.py +0 -0
  58. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/endpoints/health.py +0 -0
  59. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/endpoints/instance.py +0 -0
  60. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/endpoints/licenses.py +0 -0
  61. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/endpoints/login.py +0 -0
  62. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/endpoints/main_alarms.py +0 -0
  63. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/endpoints/meta_resource.py +0 -0
  64. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/endpoints/permission.py +0 -0
  65. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/endpoints/roles.py +0 -0
  66. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/endpoints/schemas.py +0 -0
  67. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/endpoints/signup.py +0 -0
  68. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/endpoints/tables.py +0 -0
  69. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/endpoints/token.py +0 -0
  70. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/endpoints/user.py +0 -0
  71. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/endpoints/user_role.py +0 -0
  72. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/gunicorn.py +0 -0
  73. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/migrations/README +0 -0
  74. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/migrations/alembic.ini +0 -0
  75. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/migrations/env.py +0 -0
  76. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/migrations/script.py.mako +0 -0
  77. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/migrations/versions/00757b557b02_.py +0 -0
  78. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/migrations/versions/1af47a419bbd_.py +0 -0
  79. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/migrations/versions/4aac5e0c6e66_.py +0 -0
  80. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/migrations/versions/7c3ea5ab5501_.py +0 -0
  81. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/migrations/versions/991b98e24225_.py +0 -0
  82. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/migrations/versions/a472b5ad50b7_.py +0 -0
  83. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/migrations/versions/c2db9409cb5f_.py +0 -0
  84. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/migrations/versions/c8a6c762e818_.py +0 -0
  85. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/migrations/versions/ca449af8034c_.py +0 -0
  86. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/migrations/versions/d0e0700dcd8e_.py +0 -0
  87. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/migrations/versions/d1b5be1f0549_.py +0 -0
  88. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/migrations/versions/e1a50dae1ac9_.py +0 -0
  89. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/migrations/versions/e937a5234ce4_.py +0 -0
  90. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/migrations/versions/ebdd955fcc5e_.py +0 -0
  91. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/migrations/versions/f3bee20314a2_.py +0 -0
  92. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/models/__init__.py +0 -0
  93. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/models/action.py +0 -0
  94. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/models/alarms.py +0 -0
  95. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/models/base_data_model.py +0 -0
  96. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/models/case.py +0 -0
  97. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/models/dag.py +0 -0
  98. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/models/dag_permissions.py +0 -0
  99. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/models/execution.py +0 -0
  100. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/models/instance.py +0 -0
  101. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/models/main_alarms.py +0 -0
  102. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/models/meta_models.py +0 -0
  103. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/models/permissions.py +0 -0
  104. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/models/role.py +0 -0
  105. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/models/user.py +0 -0
  106. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/models/user_role.py +0 -0
  107. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/models/view.py +0 -0
  108. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/schemas/__init__.py +0 -0
  109. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/schemas/action.py +0 -0
  110. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/schemas/alarms.py +0 -0
  111. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/schemas/case.py +0 -0
  112. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/schemas/common.py +0 -0
  113. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/schemas/dag.py +0 -0
  114. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/schemas/example_data.py +0 -0
  115. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/schemas/execution.py +0 -0
  116. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/schemas/health.py +0 -0
  117. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/schemas/instance.py +0 -0
  118. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/schemas/main_alarms.py +0 -0
  119. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/schemas/model_json.py +0 -0
  120. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/schemas/patch.py +0 -0
  121. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/schemas/permissions.py +0 -0
  122. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/schemas/query.py +0 -0
  123. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/schemas/role.py +0 -0
  124. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/schemas/schemas.py +0 -0
  125. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/schemas/solution_log.py +0 -0
  126. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/schemas/tables.py +0 -0
  127. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/schemas/user.py +0 -0
  128. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/schemas/user_role.py +0 -0
  129. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/schemas/view.py +0 -0
  130. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/shared/__init__.py +0 -0
  131. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/shared/authentication/__init__.py +0 -0
  132. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/shared/authentication/auth.py +0 -0
  133. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/shared/authentication/decorators.py +0 -0
  134. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/shared/authentication/ldap.py +0 -0
  135. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/shared/compress.py +0 -0
  136. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/shared/email.py +0 -0
  137. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/shared/exceptions.py +0 -0
  138. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/shared/licenses.py +0 -0
  139. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/shared/log_config.py +0 -0
  140. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/shared/query_tools.py +0 -0
  141. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/shared/utils.py +0 -0
  142. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/shared/utils_tables.py +0 -0
  143. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/shared/validators.py +0 -0
  144. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/tests/__init__.py +0 -0
  145. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/tests/const.py +0 -0
  146. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/tests/custom_liveServer.py +0 -0
  147. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/tests/custom_test_case.py +0 -0
  148. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/tests/integration/__init__.py +0 -0
  149. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/tests/integration/test_commands.py +0 -0
  150. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/tests/integration/test_cornflowclient.py +0 -0
  151. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/tests/ldap/__init__.py +0 -0
  152. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/tests/ldap/test_ldap_authentication.py +0 -0
  153. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/tests/unit/__init__.py +0 -0
  154. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/tests/unit/test_actions.py +0 -0
  155. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/tests/unit/test_alarms.py +0 -0
  156. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/tests/unit/test_apiview.py +0 -0
  157. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/tests/unit/test_application.py +0 -0
  158. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/tests/unit/test_cases.py +0 -0
  159. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/tests/unit/test_cli.py +0 -0
  160. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/tests/unit/test_commands.py +0 -0
  161. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/tests/unit/test_dags.py +0 -0
  162. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/tests/unit/test_data_checks.py +0 -0
  163. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/tests/unit/test_example_data.py +0 -0
  164. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/tests/unit/test_executions.py +0 -0
  165. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/tests/unit/test_generate_from_schema.py +0 -0
  166. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/tests/unit/test_health.py +0 -0
  167. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/tests/unit/test_instances.py +0 -0
  168. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/tests/unit/test_instances_file.py +0 -0
  169. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/tests/unit/test_licenses.py +0 -0
  170. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/tests/unit/test_log_in.py +0 -0
  171. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/tests/unit/test_main_alarms.py +0 -0
  172. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/tests/unit/test_permissions.py +0 -0
  173. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/tests/unit/test_roles.py +0 -0
  174. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/tests/unit/test_schema_from_models.py +0 -0
  175. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/tests/unit/test_schemas.py +0 -0
  176. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/tests/unit/test_sign_up.py +0 -0
  177. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/tests/unit/test_tables.py +0 -0
  178. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/tests/unit/test_token.py +0 -0
  179. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/tests/unit/test_users.py +0 -0
  180. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow/tests/unit/tools.py +0 -0
  181. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow.egg-info/SOURCES.txt +0 -0
  182. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow.egg-info/dependency_links.txt +0 -0
  183. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow.egg-info/entry_points.txt +0 -0
  184. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/cornflow.egg-info/top_level.txt +0 -0
  185. {cornflow-1.2.3a4 → cornflow-1.2.3a5}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cornflow
3
- Version: 1.2.3a4
3
+ Version: 1.2.3a5
4
4
  Summary: cornflow is an open source multi-solver optimization server with a REST API built using flask.
5
5
  Home-page: https://github.com/baobabsoluciones/cornflow
6
6
  Author: baobab soluciones
@@ -14,7 +14,7 @@ Requires-Dist: alembic==1.9.2
14
14
  Requires-Dist: apispec<=6.3.0
15
15
  Requires-Dist: cachetools==5.3.3
16
16
  Requires-Dist: click<=8.1.7
17
- Requires-Dist: cornflow-client>=1.2.3.a4
17
+ Requires-Dist: cornflow-client>=1.2.3.a5
18
18
  Requires-Dist: cryptography<=44.0.1
19
19
  Requires-Dist: disposable-email-domains>=0.0.86
20
20
  Requires-Dist: Flask==2.3.2
@@ -14,12 +14,13 @@ from cornflow.shared.const import ROLES_MAP
14
14
 
15
15
  def get_all_external(external_app):
16
16
  """
17
- Get all resources and extra permissions.
17
+ Get all resources, extra permissions, and custom roles actions.
18
18
  external_app: If provided, it will get the resources and extra permissions for the external app.
19
19
  """
20
20
  if external_app is None:
21
21
  resources_to_register = resources
22
22
  extra_permissions = EXTRA_PERMISSION_ASSIGNATION
23
+ custom_roles_actions = {}
23
24
  if current_app.config["ALARMS_ENDPOINTS"]:
24
25
  resources_to_register = resources + alarms_resources
25
26
  else:
@@ -33,13 +34,18 @@ def get_all_external(external_app):
33
34
  except AttributeError:
34
35
  extra_permissions = EXTRA_PERMISSION_ASSIGNATION
35
36
 
37
+ try:
38
+ custom_roles_actions = external_module.shared.const.CUSTOM_ROLES_ACTIONS
39
+ except AttributeError:
40
+ custom_roles_actions = {}
41
+
36
42
  if current_app.config["ALARMS_ENDPOINTS"]:
37
43
  resources_to_register = (
38
44
  external_module.endpoints.resources + resources + alarms_resources
39
45
  )
40
46
  else:
41
47
  resources_to_register = external_module.endpoints.resources + resources
42
- return resources_to_register, extra_permissions
48
+ return resources_to_register, extra_permissions, custom_roles_actions
43
49
 
44
50
 
45
51
  def get_all_resources(resources_to_register):
@@ -19,15 +19,22 @@ def register_base_permissions_command(external_app: str = None, verbose: bool =
19
19
  external_app: If provided, it will register the permissions for the external app.
20
20
  verbose: If True, it will print the permissions that are being registered.
21
21
  """
22
- # Get all resources and extra permissions
23
- resources_to_register, extra_permissions = get_all_external(external_app)
22
+ # Get all resources, extra permissions, and custom roles actions
23
+ resources_to_register, extra_permissions, custom_roles_actions = get_all_external(
24
+ external_app
25
+ )
26
+
24
27
  # Get all views in the database
25
28
  views_in_db = {view.name: view.id for view in ViewModel.get_all_objects()}
26
29
  permissions_in_db, permissions_in_db_keys = get_db_permissions()
30
+
27
31
  # Get all resources and roles with access
28
32
  resources_roles_with_access = get_all_resources(resources_to_register)
33
+
29
34
  # Get the new roles and base permissions assignation
30
- base_permissions_assignation = get_base_permissions(resources_roles_with_access)
35
+ base_permissions_assignation = get_base_permissions(
36
+ resources_roles_with_access, custom_roles_actions
37
+ )
31
38
  # Get the permissions to register and delete
32
39
  permissions_tuples = get_permissions_in_code_as_tuples(
33
40
  resources_to_register,
@@ -165,11 +172,11 @@ def get_permissions_in_code_as_tuples(
165
172
  return permissions_tuples
166
173
 
167
174
 
168
- def get_base_permissions(resources_roles_with_access):
175
+ def get_base_permissions(resources_roles_with_access, custom_roles_actions):
169
176
  """
170
177
  Get the new roles and base permissions assignation.
171
- new_roles_to_add: List of new roles to add.
172
178
  resources_roles_with_access: Dictionary of resources and roles with access.
179
+ custom_roles_actions: Dictionary mapping custom roles to their allowed actions.
173
180
  """
174
181
  # Get all custom roles (both new and existing) that appear in ROLES_WITH_ACCESS
175
182
  all_custom_roles_in_access = set(
@@ -181,12 +188,24 @@ def get_base_permissions(resources_roles_with_access):
181
188
  ]
182
189
  )
183
190
 
191
+ # Validate that all custom roles are defined in custom_roles_actions
192
+ undefined_roles = all_custom_roles_in_access - set(custom_roles_actions.keys())
193
+ if undefined_roles:
194
+ raise ValueError(
195
+ f"The following custom roles are used in code but not defined in CUSTOM_ROLES_ACTIONS: {undefined_roles}. "
196
+ f"Please define their allowed actions in the CUSTOM_ROLES_ACTIONS dictionary in shared/const.py."
197
+ )
198
+
184
199
  # Create extended permission assignation including all custom roles
185
- # For custom roles (not in ALL_DEFAULT_ROLES), only grant GET access
186
- base_permissions_assignation = BASE_PERMISSION_ASSIGNATION + [
187
- (custom_role, GET_ACTION) for custom_role in all_custom_roles_in_access
200
+ # For custom roles, use the actions defined in custom_roles_actions
201
+ custom_permissions = [
202
+ (custom_role, action)
203
+ for custom_role in all_custom_roles_in_access
204
+ for action in custom_roles_actions[custom_role]
188
205
  ]
189
206
 
207
+ base_permissions_assignation = BASE_PERMISSION_ASSIGNATION + custom_permissions
208
+
190
209
  return base_permissions_assignation
191
210
 
192
211
 
@@ -10,7 +10,7 @@ def register_roles_command(external_app: str = None, verbose: bool = True):
10
10
  get_new_roles_to_add,
11
11
  )
12
12
 
13
- resources_to_register, extra_permissions = get_all_external(external_app)
13
+ resources_to_register, extra_permissions, _ = get_all_external(external_app)
14
14
  resources_roles_with_access = get_all_resources(resources_to_register)
15
15
  new_roles_to_add = get_new_roles_to_add(
16
16
  extra_permissions, resources_roles_with_access
@@ -1,7 +1,7 @@
1
1
  """
2
2
  In this file we import the values for different constants on cornflow server
3
3
  """
4
- CORNFLOW_VERSION = "1.2.3.a4"
4
+ CORNFLOW_VERSION = "1.2.3.a5"
5
5
  INTERNAL_TOKEN_ISSUER = "cornflow"
6
6
 
7
7
  # endpoints responses for health check
@@ -13,6 +13,7 @@ from cornflow.shared.const import (
13
13
  PATCH_ACTION,
14
14
  DELETE_ACTION,
15
15
  GET_ACTION,
16
+ PUT_ACTION,
16
17
  )
17
18
 
18
19
 
@@ -106,6 +107,13 @@ class ExternalRoleCreationTestCase(CustomTestCase):
106
107
  (VIEWER_ROLE, POST_ACTION, "scheduling_optimizer"),
107
108
  (PLANNER_ROLE, DELETE_ACTION, "quality_control"),
108
109
  ]
110
+ # Define permissions for custom roles used in endpoints
111
+ mock_const.CUSTOM_ROLES_ACTIONS = {
112
+ # Default permission for role 888
113
+ 888: [GET_ACTION],
114
+ # Default permission for role 777
115
+ 777: [GET_ACTION],
116
+ }
109
117
  mock_shared.const = mock_const
110
118
  mock_external_app.shared = mock_shared
111
119
 
@@ -206,6 +214,17 @@ class ExternalRoleCreationTestCase(CustomTestCase):
206
214
  (10000, POST_ACTION, "production_planning"),
207
215
  (999, PATCH_ACTION, "quality_control"),
208
216
  ]
217
+ # Define permissions for custom roles used in endpoints (888, 777) and test roles (10000, 999)
218
+ mock_const.CUSTOM_ROLES_ACTIONS = {
219
+ # Used in endpoints
220
+ 888: [GET_ACTION],
221
+ # Used in endpoints
222
+ 777: [GET_ACTION],
223
+ # Used in test
224
+ 10000: [GET_ACTION],
225
+ # Used in test
226
+ 999: [GET_ACTION],
227
+ }
209
228
  mock_shared.const = mock_const
210
229
  mock_external_app.shared = mock_shared
211
230
 
@@ -224,6 +243,7 @@ class ExternalRoleCreationTestCase(CustomTestCase):
224
243
  mock_const.EXTRA_PERMISSION_ASSIGNATION = [
225
244
  (10000, POST_ACTION, "production_planning"),
226
245
  ]
246
+ # Keep the same CUSTOM_ROLES_ACTIONS (role definitions don't change)
227
247
 
228
248
  # Re-run permissions registration
229
249
  access_init_command(verbose=True)
@@ -266,6 +286,13 @@ class ExternalRoleCreationTestCase(CustomTestCase):
266
286
  mock_const = MagicMock()
267
287
  # Don't set EXTRA_PERMISSION_ASSIGNATION to trigger AttributeError
268
288
  del mock_const.EXTRA_PERMISSION_ASSIGNATION
289
+ # Define permissions for custom roles used in endpoints
290
+ mock_const.CUSTOM_ROLES_ACTIONS = {
291
+ # Used in endpoints
292
+ 888: [GET_ACTION],
293
+ # Used in endpoints
294
+ 777: [GET_ACTION],
295
+ }
269
296
  mock_shared.const = mock_const
270
297
  mock_external_app.shared = mock_shared
271
298
 
@@ -304,6 +331,13 @@ class ExternalRoleCreationTestCase(CustomTestCase):
304
331
  (VIEWER_ROLE, POST_ACTION, "production_planning"), # Extend standard role
305
332
  (PLANNER_ROLE, DELETE_ACTION, "quality_control"), # Extend standard role
306
333
  ]
334
+ # Define permissions for custom roles used in endpoints
335
+ mock_const.CUSTOM_ROLES_ACTIONS = {
336
+ # Used in endpoints
337
+ 888: [GET_ACTION],
338
+ # Used in endpoints
339
+ 777: [GET_ACTION],
340
+ }
307
341
  mock_shared.const = mock_const
308
342
  mock_external_app.shared = mock_shared
309
343
 
@@ -385,6 +419,13 @@ class ExternalRoleCreationTestCase(CustomTestCase):
385
419
  mock_shared_initial = MagicMock()
386
420
  mock_const_initial = MagicMock()
387
421
  mock_const_initial.EXTRA_PERMISSION_ASSIGNATION = []
422
+ # Define permissions for custom roles used in test endpoints
423
+ mock_const_initial.CUSTOM_ROLES_ACTIONS = {
424
+ # Used in test endpoints
425
+ 888: [GET_ACTION],
426
+ # Used in test endpoints
427
+ 777: [GET_ACTION],
428
+ }
388
429
  mock_shared_initial.const = mock_const_initial
389
430
  mock_external_app_initial.shared = mock_shared_initial
390
431
 
@@ -459,6 +500,13 @@ class ExternalRoleCreationTestCase(CustomTestCase):
459
500
  mock_shared_updated = MagicMock()
460
501
  mock_const_updated = MagicMock()
461
502
  mock_const_updated.EXTRA_PERMISSION_ASSIGNATION = [] # Empty list
503
+ # Define permissions for custom roles used in test endpoints
504
+ mock_const_updated.CUSTOM_ROLES_ACTIONS = {
505
+ # Used in test endpoints
506
+ 888: [GET_ACTION],
507
+ # Used in test endpoints
508
+ 777: [GET_ACTION],
509
+ }
462
510
  mock_shared_updated.const = mock_const_updated
463
511
  mock_external_app_updated.shared = mock_shared_updated
464
512
 
@@ -534,6 +582,204 @@ class ExternalRoleCreationTestCase(CustomTestCase):
534
582
  f"Permissions for remaining views should still exist. Found views: {set(all_view_names)}",
535
583
  )
536
584
 
585
+ @patch("cornflow.commands.auxiliar.import_module")
586
+ @patch("cornflow.commands.views.import_module")
587
+ @patch.dict(
588
+ os.environ, {"EXTERNAL_APP": "1", "EXTERNAL_APP_MODULE": "external_test_app"}
589
+ )
590
+ def test_custom_roles_actions_success(
591
+ self, mock_import_views, mock_import_auxiliar
592
+ ):
593
+ """
594
+ Test that custom roles get their defined actions from CUSTOM_ROLES_ACTIONS
595
+ """
596
+ # Mock external app configuration
597
+ mock_external_app = MagicMock()
598
+
599
+ # Mock the shared.const module with CUSTOM_ROLES_ACTIONS
600
+ mock_shared = MagicMock()
601
+ mock_const = MagicMock()
602
+ mock_const.EXTRA_PERMISSION_ASSIGNATION = []
603
+ # Define custom roles actions
604
+ mock_const.CUSTOM_ROLES_ACTIONS = {
605
+ # Custom role with multiple actions
606
+ 888: [
607
+ GET_ACTION,
608
+ POST_ACTION,
609
+ PUT_ACTION,
610
+ ],
611
+ # Another custom role with different actions
612
+ 777: [
613
+ GET_ACTION,
614
+ PATCH_ACTION,
615
+ ],
616
+ }
617
+ mock_shared.const = mock_const
618
+ mock_external_app.shared = mock_shared
619
+
620
+ # Mock the endpoints.resources with fake external app endpoints
621
+ mock_endpoints = MagicMock()
622
+ mock_endpoints.resources = self._create_mock_external_app_resources()
623
+ mock_external_app.endpoints = mock_endpoints
624
+
625
+ mock_import_views.return_value = mock_external_app
626
+ mock_import_auxiliar.return_value = mock_external_app
627
+
628
+ # Mock the database session for testing
629
+ with patch.object(db.session, "commit"):
630
+ with patch.object(db.session, "rollback"):
631
+ # Run the complete access initialization
632
+ access_init_command(verbose=True)
633
+
634
+ # Verify that custom permissions were created with the correct actions
635
+ from cornflow.models import PermissionViewRoleModel
636
+
637
+ # Get all permissions for role 888
638
+ permissions_888 = PermissionViewRoleModel.query.filter_by(
639
+ role_id=888
640
+ ).all()
641
+ actions_888 = {perm.action_id for perm in permissions_888}
642
+
643
+ # Get all permissions for role 777
644
+ permissions_777 = PermissionViewRoleModel.query.filter_by(
645
+ role_id=777
646
+ ).all()
647
+ actions_777 = {perm.action_id for perm in permissions_777}
648
+
649
+ # Verify role 888 has GET, POST, PUT actions
650
+ expected_actions_888 = {GET_ACTION, POST_ACTION, PUT_ACTION}
651
+ self.assertTrue(
652
+ expected_actions_888.issubset(actions_888),
653
+ f"Role 888 should have actions {expected_actions_888}, but got {actions_888}",
654
+ )
655
+
656
+ # Verify role 777 has GET, PATCH actions
657
+ expected_actions_777 = {GET_ACTION, PATCH_ACTION}
658
+ self.assertTrue(
659
+ expected_actions_777.issubset(actions_777),
660
+ f"Role 777 should have actions {expected_actions_777}, but got {actions_777}",
661
+ )
662
+
663
+ # Verify that role 888 does NOT have actions that were not defined
664
+ # We check that no DELETE or PATCH actions exist for role 888
665
+ forbidden_actions_888 = {DELETE_ACTION, PATCH_ACTION}
666
+ actual_forbidden_888 = actions_888.intersection(forbidden_actions_888)
667
+ self.assertEqual(
668
+ len(actual_forbidden_888),
669
+ 0,
670
+ f"Role 888 should not have actions {forbidden_actions_888}, but found {actual_forbidden_888}",
671
+ )
672
+
673
+ # Verify that role 777 does NOT have actions that were not defined
674
+ # We check that no POST, PUT, DELETE actions exist for role 777
675
+ forbidden_actions_777 = {POST_ACTION, PUT_ACTION, DELETE_ACTION}
676
+ actual_forbidden_777 = actions_777.intersection(forbidden_actions_777)
677
+ self.assertEqual(
678
+ len(actual_forbidden_777),
679
+ 0,
680
+ f"Role 777 should not have actions {forbidden_actions_777}, but found {actual_forbidden_777}",
681
+ )
682
+
683
+ @patch("cornflow.commands.auxiliar.import_module")
684
+ @patch("cornflow.commands.views.import_module")
685
+ @patch.dict(
686
+ os.environ, {"EXTERNAL_APP": "1", "EXTERNAL_APP_MODULE": "external_test_app"}
687
+ )
688
+ def test_custom_roles_actions_error_on_undefined_role(
689
+ self, mock_import_views, mock_import_auxiliar
690
+ ):
691
+ """
692
+ Test that an error is raised when a custom role is used but not defined in CUSTOM_ROLES_ACTIONS
693
+ """
694
+ # Mock external app configuration
695
+ mock_external_app = MagicMock()
696
+
697
+ # Mock the shared.const module with CUSTOM_ROLES_ACTIONS that doesn't include role 888
698
+ mock_shared = MagicMock()
699
+ mock_const = MagicMock()
700
+ mock_const.EXTRA_PERMISSION_ASSIGNATION = []
701
+ # Define custom roles permissions but MISSING role 888 which is used in endpoints
702
+ mock_const.CUSTOM_ROLES_ACTIONS = {
703
+ # Only define role 777, but role 888 is used in endpoints
704
+ 777: [
705
+ GET_ACTION,
706
+ PATCH_ACTION,
707
+ ],
708
+ }
709
+ mock_shared.const = mock_const
710
+ mock_external_app.shared = mock_shared
711
+
712
+ # Mock the endpoints.resources with fake external app endpoints that use role 888
713
+ mock_endpoints = MagicMock()
714
+ mock_endpoints.resources = (
715
+ self._create_mock_external_app_resources()
716
+ ) # This includes role 888
717
+ mock_external_app.endpoints = mock_endpoints
718
+
719
+ mock_import_views.return_value = mock_external_app
720
+ mock_import_auxiliar.return_value = mock_external_app
721
+
722
+ # Verify that a ValueError is raised for undefined role 888
723
+ with self.assertRaises(ValueError) as context:
724
+ access_init_command(verbose=True)
725
+
726
+ # Verify the error message contains the undefined role
727
+ error_message = str(context.exception)
728
+ self.assertIn("888", error_message)
729
+ self.assertIn("CUSTOM_ROLES_ACTIONS", error_message)
730
+ self.assertIn("not defined", error_message)
731
+
732
+ @patch("cornflow.commands.auxiliar.import_module")
733
+ @patch("cornflow.commands.views.import_module")
734
+ @patch.dict(
735
+ os.environ, {"EXTERNAL_APP": "1", "EXTERNAL_APP_MODULE": "external_test_app"}
736
+ )
737
+ def test_custom_roles_actions_fallback_when_not_defined(
738
+ self, mock_import_views, mock_import_auxiliar
739
+ ):
740
+ """
741
+ Test that the system falls back gracefully when CUSTOM_ROLES_ACTIONS is not defined
742
+ but no custom roles are used
743
+ """
744
+ # Mock external app configuration
745
+ mock_external_app = MagicMock()
746
+
747
+ # Mock the shared.const module WITHOUT CUSTOM_ROLES_ACTIONS
748
+ mock_shared = MagicMock()
749
+ mock_const = MagicMock()
750
+ mock_const.EXTRA_PERMISSION_ASSIGNATION = []
751
+ # Don't set CUSTOM_ROLES_ACTIONS to trigger AttributeError
752
+ # This simulates an external app that doesn't define the new constant
753
+ mock_shared.const = mock_const
754
+ mock_external_app.shared = mock_shared
755
+
756
+ # Mock endpoints that only use standard roles (no custom roles)
757
+ mock_production_endpoint = MagicMock()
758
+ # Only standard role
759
+ mock_production_endpoint.ROLES_WITH_ACCESS = [PLANNER_ROLE]
760
+ mock_production_endpoint.DESCRIPTION = "Production planning endpoint"
761
+
762
+ mock_resources = [
763
+ {
764
+ "endpoint": "production_planning",
765
+ "urls": "/production-planning/",
766
+ "resource": mock_production_endpoint,
767
+ }
768
+ ]
769
+
770
+ mock_endpoints = MagicMock()
771
+ mock_endpoints.resources = mock_resources
772
+ mock_external_app.endpoints = mock_endpoints
773
+
774
+ mock_import_views.return_value = mock_external_app
775
+ mock_import_auxiliar.return_value = mock_external_app
776
+
777
+ # Should not raise any exceptions since no custom roles are used
778
+ try:
779
+ access_init_command(verbose=True)
780
+ except Exception as e:
781
+ self.fail(f"access_init_command raised an exception when it shouldn't: {e}")
782
+
537
783
 
538
784
  if __name__ == "__main__":
539
785
  unittest.main()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cornflow
3
- Version: 1.2.3a4
3
+ Version: 1.2.3a5
4
4
  Summary: cornflow is an open source multi-solver optimization server with a REST API built using flask.
5
5
  Home-page: https://github.com/baobabsoluciones/cornflow
6
6
  Author: baobab soluciones
@@ -14,7 +14,7 @@ Requires-Dist: alembic==1.9.2
14
14
  Requires-Dist: apispec<=6.3.0
15
15
  Requires-Dist: cachetools==5.3.3
16
16
  Requires-Dist: click<=8.1.7
17
- Requires-Dist: cornflow-client>=1.2.3.a4
17
+ Requires-Dist: cornflow-client>=1.2.3.a5
18
18
  Requires-Dist: cryptography<=44.0.1
19
19
  Requires-Dist: disposable-email-domains>=0.0.86
20
20
  Requires-Dist: Flask==2.3.2
@@ -2,7 +2,7 @@ alembic==1.9.2
2
2
  apispec<=6.3.0
3
3
  cachetools==5.3.3
4
4
  click<=8.1.7
5
- cornflow-client>=1.2.3.a4
5
+ cornflow-client>=1.2.3.a5
6
6
  cryptography<=44.0.1
7
7
  disposable-email-domains>=0.0.86
8
8
  Flask==2.3.2
@@ -2,7 +2,7 @@ alembic==1.9.2
2
2
  apispec<=6.3.0
3
3
  cachetools==5.3.3
4
4
  click<=8.1.7
5
- cornflow-client>=1.2.3.a4
5
+ cornflow-client>=1.2.3.a5
6
6
  cryptography<=44.0.1
7
7
  disposable-email-domains>=0.0.86
8
8
  Flask==2.3.2
@@ -9,7 +9,7 @@ with open("requirements.txt", "r") as fh:
9
9
 
10
10
  setuptools.setup(
11
11
  name="cornflow",
12
- version="1.2.3.a4",
12
+ version="1.2.3.a5",
13
13
  author="baobab soluciones",
14
14
  author_email="cornflow@baobabsoluciones.es",
15
15
  description="cornflow is an open source multi-solver optimization server with a REST API built using flask.",
File without changes
File without changes
File without changes
File without changes