infrahub-server 1.1.0b2__py3-none-any.whl → 1.1.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (244) hide show
  1. infrahub/api/artifact.py +8 -15
  2. infrahub/api/dependencies.py +15 -2
  3. infrahub/api/diff/diff.py +2 -2
  4. infrahub/api/file.py +2 -7
  5. infrahub/api/menu.py +9 -7
  6. infrahub/api/oauth2.py +3 -3
  7. infrahub/api/oidc.py +3 -3
  8. infrahub/api/query.py +4 -4
  9. infrahub/api/schema.py +24 -41
  10. infrahub/api/transformation.py +3 -3
  11. infrahub/auth.py +0 -2
  12. infrahub/cli/db.py +9 -11
  13. infrahub/cli/tasks.py +3 -1
  14. infrahub/computed_attribute/constants.py +2 -2
  15. infrahub/computed_attribute/models.py +20 -8
  16. infrahub/computed_attribute/tasks.py +136 -61
  17. infrahub/config.py +18 -4
  18. infrahub/core/account.py +8 -11
  19. infrahub/core/attribute.py +15 -0
  20. infrahub/core/branch/constants.py +2 -0
  21. infrahub/core/branch/models.py +3 -2
  22. infrahub/core/branch/tasks.py +150 -52
  23. infrahub/core/constraint/node/runner.py +11 -10
  24. infrahub/core/diff/calculator.py +4 -3
  25. infrahub/core/diff/combiner.py +1 -0
  26. infrahub/core/diff/coordinator.py +309 -105
  27. infrahub/core/diff/data_check_synchronizer.py +33 -4
  28. infrahub/core/diff/enricher/hierarchy.py +2 -0
  29. infrahub/core/diff/merger/merger.py +1 -1
  30. infrahub/core/diff/model/path.py +101 -3
  31. infrahub/core/diff/query/artifact.py +52 -28
  32. infrahub/core/diff/query/field_specifiers.py +35 -0
  33. infrahub/core/diff/query/roots_metadata.py +48 -0
  34. infrahub/core/diff/query/save.py +1 -0
  35. infrahub/core/diff/query_parser.py +52 -19
  36. infrahub/core/diff/repository/deserializer.py +7 -3
  37. infrahub/core/diff/repository/repository.py +98 -7
  38. infrahub/core/diff/tasks.py +29 -25
  39. infrahub/core/graph/__init__.py +1 -1
  40. infrahub/core/graph/constraints.py +4 -2
  41. infrahub/core/integrity/object_conflict/conflict_recorder.py +6 -1
  42. infrahub/core/manager.py +157 -43
  43. infrahub/core/merge.py +3 -2
  44. infrahub/core/migrations/graph/__init__.py +4 -0
  45. infrahub/core/migrations/graph/m012_convert_account_generic.py +12 -6
  46. infrahub/core/migrations/graph/m013_convert_git_password_credential.py +7 -5
  47. infrahub/core/migrations/graph/m014_remove_index_attr_value.py +1 -1
  48. infrahub/core/migrations/graph/m015_diff_format_update.py +1 -1
  49. infrahub/core/migrations/graph/m016_diff_delete_bug_fix.py +1 -1
  50. infrahub/core/migrations/graph/m017_add_core_profile.py +44 -0
  51. infrahub/core/migrations/graph/m018_uniqueness_nulls.py +101 -0
  52. infrahub/core/migrations/query/attribute_add.py +2 -1
  53. infrahub/core/migrations/query/delete_element_in_schema.py +2 -1
  54. infrahub/core/migrations/query/node_duplicate.py +2 -1
  55. infrahub/core/migrations/query/relationship_duplicate.py +2 -1
  56. infrahub/core/migrations/query/schema_attribute_update.py +1 -1
  57. infrahub/core/migrations/schema/tasks.py +2 -2
  58. infrahub/core/migrations/shared.py +3 -3
  59. infrahub/core/node/__init__.py +34 -7
  60. infrahub/core/node/constraints/grouped_uniqueness.py +9 -2
  61. infrahub/core/query/__init__.py +12 -6
  62. infrahub/core/query/diff.py +23 -17
  63. infrahub/core/query/ipam.py +9 -4
  64. infrahub/core/query/node.py +161 -65
  65. infrahub/core/query/relationship.py +19 -17
  66. infrahub/core/query/resource_manager.py +21 -11
  67. infrahub/core/query/standard_node.py +13 -19
  68. infrahub/core/registry.py +0 -1
  69. infrahub/core/relationship/model.py +17 -5
  70. infrahub/core/schema/definitions/internal.py +1 -1
  71. infrahub/core/schema/generated/attribute_schema.py +2 -2
  72. infrahub/core/schema/generated/base_node_schema.py +2 -2
  73. infrahub/core/schema/generated/relationship_schema.py +1 -1
  74. infrahub/core/schema/schema_branch.py +16 -48
  75. infrahub/core/schema/schema_branch_computed.py +15 -4
  76. infrahub/core/task/task_log.py +1 -1
  77. infrahub/core/utils.py +5 -4
  78. infrahub/core/validators/interface.py +1 -2
  79. infrahub/core/validators/shared.py +2 -2
  80. infrahub/core/validators/tasks.py +8 -7
  81. infrahub/core/validators/uniqueness/index.py +2 -4
  82. infrahub/core/validators/uniqueness/query.py +2 -1
  83. infrahub/database/__init__.py +37 -20
  84. infrahub/database/index.py +1 -1
  85. infrahub/database/neo4j.py +3 -1
  86. infrahub/dependencies/builder/diff/data_check_synchronizer.py +2 -0
  87. infrahub/events/branch_action.py +13 -14
  88. infrahub/events/node_action.py +10 -10
  89. infrahub/events/schema_action.py +6 -5
  90. infrahub/exceptions.py +29 -16
  91. infrahub/generators/tasks.py +2 -1
  92. infrahub/git/base.py +106 -32
  93. infrahub/git/integrator.py +34 -3
  94. infrahub/git/models.py +5 -1
  95. infrahub/git/repository.py +19 -65
  96. infrahub/git/tasks.py +43 -22
  97. infrahub/graphql/app.py +2 -2
  98. infrahub/graphql/auth/query_permission_checker/default_branch_checker.py +2 -17
  99. infrahub/graphql/auth/query_permission_checker/merge_operation_checker.py +1 -12
  100. infrahub/graphql/auth/query_permission_checker/object_permission_checker.py +6 -40
  101. infrahub/graphql/auth/query_permission_checker/super_admin_checker.py +5 -8
  102. infrahub/graphql/enums.py +2 -2
  103. infrahub/graphql/initialization.py +30 -8
  104. infrahub/graphql/loaders/node.py +82 -0
  105. infrahub/graphql/manager.py +10 -4
  106. infrahub/graphql/models.py +6 -0
  107. infrahub/graphql/mutations/account.py +10 -6
  108. infrahub/graphql/mutations/branch.py +0 -2
  109. infrahub/graphql/mutations/computed_attribute.py +14 -23
  110. infrahub/graphql/mutations/diff.py +2 -0
  111. infrahub/graphql/mutations/ipam.py +13 -8
  112. infrahub/graphql/mutations/main.py +83 -8
  113. infrahub/graphql/mutations/proposed_change.py +11 -20
  114. infrahub/graphql/mutations/repository.py +3 -0
  115. infrahub/graphql/mutations/resource_manager.py +3 -0
  116. infrahub/graphql/mutations/schema.py +8 -7
  117. infrahub/graphql/mutations/tasks.py +36 -37
  118. infrahub/graphql/permissions.py +3 -4
  119. infrahub/graphql/queries/account.py +2 -11
  120. infrahub/graphql/queries/task.py +2 -12
  121. infrahub/graphql/query.py +3 -1
  122. infrahub/graphql/{resolver.py → resolvers/resolver.py} +14 -61
  123. infrahub/graphql/resolvers/single_relationship.py +169 -0
  124. infrahub/graphql/schema.py +0 -6
  125. infrahub/graphql/subscription/graphql_query.py +7 -1
  126. infrahub/graphql/types/task.py +14 -2
  127. infrahub/groups/tasks.py +9 -3
  128. infrahub/log.py +4 -0
  129. infrahub/menu/generator.py +6 -18
  130. infrahub/message_bus/messages/check_generator_run.py +1 -0
  131. infrahub/message_bus/messages/event_node_mutated.py +2 -2
  132. infrahub/message_bus/messages/refresh_git_fetch.py +1 -0
  133. infrahub/message_bus/messages/request_repository_userchecks.py +2 -1
  134. infrahub/message_bus/operations/check/artifact.py +3 -1
  135. infrahub/message_bus/operations/check/generator.py +20 -2
  136. infrahub/message_bus/operations/check/repository.py +31 -21
  137. infrahub/message_bus/operations/event/branch.py +2 -4
  138. infrahub/message_bus/operations/git/file.py +1 -3
  139. infrahub/message_bus/operations/git/repository.py +7 -2
  140. infrahub/message_bus/operations/requests/artifact_definition.py +6 -5
  141. infrahub/message_bus/operations/requests/generator_definition.py +10 -6
  142. infrahub/message_bus/operations/requests/proposed_change.py +31 -13
  143. infrahub/message_bus/operations/requests/repository.py +15 -13
  144. infrahub/message_bus/types.py +1 -1
  145. infrahub/permissions/__init__.py +12 -3
  146. infrahub/permissions/backend.py +2 -17
  147. infrahub/permissions/constants.py +12 -8
  148. infrahub/permissions/local_backend.py +5 -102
  149. infrahub/permissions/manager.py +135 -0
  150. infrahub/permissions/report.py +14 -25
  151. infrahub/permissions/types.py +6 -0
  152. infrahub/proposed_change/tasks.py +12 -9
  153. infrahub/server.py +3 -1
  154. infrahub/services/scheduler.py +1 -3
  155. infrahub/task_manager/models.py +34 -5
  156. infrahub/task_manager/task.py +10 -6
  157. infrahub/tasks/dummy.py +3 -0
  158. infrahub/tasks/telemetry.py +26 -24
  159. infrahub/transformations/tasks.py +2 -0
  160. infrahub/visuals.py +1 -3
  161. infrahub/webhook/models.py +6 -2
  162. infrahub/webhook/tasks.py +1 -1
  163. infrahub/workers/infrahub_async.py +14 -0
  164. infrahub/workflows/catalogue.py +24 -5
  165. infrahub/workflows/utils.py +11 -3
  166. infrahub_sdk/_importer.py +13 -4
  167. infrahub_sdk/analyzer.py +9 -7
  168. infrahub_sdk/batch.py +54 -8
  169. infrahub_sdk/branch.py +22 -20
  170. infrahub_sdk/checks.py +14 -41
  171. infrahub_sdk/client.py +769 -575
  172. infrahub_sdk/code_generator.py +21 -17
  173. infrahub_sdk/config.py +15 -13
  174. infrahub_sdk/ctl/branch.py +1 -1
  175. infrahub_sdk/ctl/check.py +15 -11
  176. infrahub_sdk/ctl/cli_commands.py +122 -21
  177. infrahub_sdk/ctl/client.py +18 -16
  178. infrahub_sdk/ctl/config.py +6 -7
  179. infrahub_sdk/ctl/exporter.py +2 -3
  180. infrahub_sdk/ctl/generator.py +11 -8
  181. infrahub_sdk/ctl/render.py +1 -1
  182. infrahub_sdk/ctl/repository.py +9 -7
  183. infrahub_sdk/ctl/schema.py +8 -4
  184. infrahub_sdk/ctl/transform.py +1 -1
  185. infrahub_sdk/ctl/utils.py +13 -9
  186. infrahub_sdk/ctl/validate.py +3 -2
  187. infrahub_sdk/data.py +5 -4
  188. infrahub_sdk/exceptions.py +14 -14
  189. infrahub_sdk/generator.py +9 -10
  190. infrahub_sdk/graphql.py +9 -4
  191. infrahub_sdk/groups.py +1 -3
  192. infrahub_sdk/node.py +188 -152
  193. infrahub_sdk/object_store.py +5 -5
  194. infrahub_sdk/playback.py +11 -7
  195. infrahub_sdk/protocols_base.py +30 -30
  196. infrahub_sdk/pytest_plugin/items/base.py +21 -7
  197. infrahub_sdk/pytest_plugin/items/check.py +11 -7
  198. infrahub_sdk/pytest_plugin/items/graphql_query.py +2 -2
  199. infrahub_sdk/pytest_plugin/items/jinja2_transform.py +5 -5
  200. infrahub_sdk/pytest_plugin/items/python_transform.py +12 -7
  201. infrahub_sdk/pytest_plugin/loader.py +2 -2
  202. infrahub_sdk/pytest_plugin/models.py +10 -10
  203. infrahub_sdk/pytest_plugin/plugin.py +3 -2
  204. infrahub_sdk/pytest_plugin/utils.py +1 -1
  205. infrahub_sdk/queries.py +69 -0
  206. infrahub_sdk/query_groups.py +17 -17
  207. infrahub_sdk/schema/__init__.py +687 -0
  208. infrahub_sdk/schema/main.py +343 -0
  209. infrahub_sdk/schema/repository.py +237 -0
  210. infrahub_sdk/spec/menu.py +2 -2
  211. infrahub_sdk/spec/object.py +14 -10
  212. infrahub_sdk/store.py +21 -23
  213. infrahub_sdk/task_report.py +20 -22
  214. infrahub_sdk/testing/__init__.py +0 -0
  215. infrahub_sdk/testing/docker.py +18 -0
  216. infrahub_sdk/testing/repository.py +107 -0
  217. infrahub_sdk/testing/schemas/__init__.py +0 -0
  218. infrahub_sdk/testing/schemas/animal.py +182 -0
  219. infrahub_sdk/testing/schemas/car_person.py +252 -0
  220. infrahub_sdk/timestamp.py +1 -2
  221. infrahub_sdk/transfer/exporter/interface.py +3 -2
  222. infrahub_sdk/transfer/exporter/json.py +13 -10
  223. infrahub_sdk/transfer/importer/json.py +9 -6
  224. infrahub_sdk/transfer/schema_sorter.py +8 -4
  225. infrahub_sdk/transforms.py +5 -46
  226. infrahub_sdk/types.py +19 -10
  227. infrahub_sdk/utils.py +22 -5
  228. infrahub_sdk/uuidt.py +5 -6
  229. infrahub_sdk/yaml.py +8 -6
  230. {infrahub_server-1.1.0b2.dist-info → infrahub_server-1.1.2.dist-info}/METADATA +3 -2
  231. {infrahub_server-1.1.0b2.dist-info → infrahub_server-1.1.2.dist-info}/RECORD +240 -225
  232. infrahub_testcontainers/__init__.py +6 -0
  233. {infrahub/testing → infrahub_testcontainers}/container.py +28 -22
  234. {infrahub/testing → infrahub_testcontainers}/docker-compose.test.yml +33 -40
  235. {infrahub/testing → infrahub_testcontainers}/helpers.py +31 -26
  236. infrahub/core/diff/query/empty_roots.py +0 -33
  237. infrahub/graphql/mutations/task.py +0 -147
  238. infrahub/testing/schemas/car_person.py +0 -125
  239. infrahub_sdk/schema.py +0 -1080
  240. /infrahub/{testing → graphql/loaders}/__init__.py +0 -0
  241. /infrahub/{testing/schemas → graphql/resolvers}/__init__.py +0 -0
  242. {infrahub_server-1.1.0b2.dist-info → infrahub_server-1.1.2.dist-info}/LICENSE.txt +0 -0
  243. {infrahub_server-1.1.0b2.dist-info → infrahub_server-1.1.2.dist-info}/WHEEL +0 -0
  244. {infrahub_server-1.1.0b2.dist-info → infrahub_server-1.1.2.dist-info}/entry_points.txt +0 -0
infrahub/api/artifact.py CHANGED
@@ -5,20 +5,20 @@ from typing import TYPE_CHECKING
5
5
  from fastapi import APIRouter, Body, Depends, Request, Response
6
6
  from pydantic import BaseModel, Field
7
7
 
8
- from infrahub.api.dependencies import BranchParams, get_branch_params, get_current_user, get_db
8
+ from infrahub.api.dependencies import BranchParams, get_branch_params, get_current_user, get_db, get_permission_manager
9
9
  from infrahub.core import registry
10
10
  from infrahub.core.account import ObjectPermission
11
11
  from infrahub.core.constants import GLOBAL_BRANCH_NAME, InfrahubKind, PermissionAction
12
12
  from infrahub.core.protocols import CoreArtifactDefinition
13
- from infrahub.database import InfrahubDatabase # noqa: TCH001
14
- from infrahub.exceptions import NodeNotFoundError, PermissionDeniedError
13
+ from infrahub.database import InfrahubDatabase # noqa: TC001
14
+ from infrahub.exceptions import NodeNotFoundError
15
15
  from infrahub.git.models import RequestArtifactDefinitionGenerate
16
16
  from infrahub.log import get_logger
17
17
  from infrahub.permissions.constants import PermissionDecisionFlag
18
18
  from infrahub.workflows.catalogue import REQUEST_ARTIFACT_DEFINITION_GENERATE
19
19
 
20
20
  if TYPE_CHECKING:
21
- from infrahub.auth import AccountSession
21
+ from infrahub.permissions import PermissionManager
22
22
 
23
23
  log = get_logger()
24
24
  router = APIRouter(prefix="/artifact")
@@ -61,25 +61,18 @@ async def generate_artifact(
61
61
  ),
62
62
  db: InfrahubDatabase = Depends(get_db),
63
63
  branch_params: BranchParams = Depends(get_branch_params),
64
- account_session: AccountSession = Depends(get_current_user),
64
+ permission_manager: PermissionManager = Depends(get_permission_manager),
65
65
  ) -> None:
66
66
  permission_decision = (
67
67
  PermissionDecisionFlag.ALLOW_DEFAULT
68
68
  if branch_params.branch.name in (GLOBAL_BRANCH_NAME, registry.default_branch)
69
69
  else PermissionDecisionFlag.ALLOW_OTHER
70
70
  )
71
- for permission in [
71
+ permissions = [
72
72
  ObjectPermission(namespace="Core", name="Artifact", action=action.value, decision=permission_decision)
73
73
  for action in (PermissionAction.CREATE, PermissionAction.UPDATE)
74
- ]:
75
- has_permission = False
76
- for permission_backend in registry.permission_backends:
77
- if has_permission := await permission_backend.has_permission(
78
- db=db, account_session=account_session, permission=permission, branch=branch_params.branch
79
- ):
80
- break
81
- if not has_permission:
82
- raise PermissionDeniedError(f"You do not have the following permission: {permission}")
74
+ ]
75
+ permission_manager.raise_for_permissions(permissions=permissions)
83
76
 
84
77
  # Verify that the artifact definition exists for the requested branch
85
78
  artifact_definition = await registry.manager.get_one_by_id_or_default_filter(
@@ -8,11 +8,12 @@ from pydantic import BaseModel, ConfigDict
8
8
 
9
9
  from infrahub import config
10
10
  from infrahub.auth import AccountSession, authentication_token, validate_jwt_access_token, validate_jwt_refresh_token
11
- from infrahub.core.branch import Branch # noqa: TCH001
11
+ from infrahub.core.branch import Branch # noqa: TC001
12
12
  from infrahub.core.registry import registry
13
13
  from infrahub.core.timestamp import Timestamp
14
- from infrahub.database import InfrahubDatabase # noqa: TCH001
14
+ from infrahub.database import InfrahubDatabase # noqa: TC001
15
15
  from infrahub.exceptions import AuthorizationError
16
+ from infrahub.permissions import PermissionManager
16
17
 
17
18
  if TYPE_CHECKING:
18
19
  from neo4j import AsyncSession
@@ -120,3 +121,15 @@ async def get_current_user(
120
121
  return account_session
121
122
 
122
123
  raise AuthorizationError("Authentication is required")
124
+
125
+
126
+ async def get_permission_manager(
127
+ db: InfrahubDatabase = Depends(get_db),
128
+ branch_params: BranchParams = Depends(get_branch_params),
129
+ account_session: AccountSession = Depends(get_current_user),
130
+ ) -> PermissionManager:
131
+ """Return a `PermissionManager` for an account session based on a branch."""
132
+ permission_manager = PermissionManager(account_session=account_session)
133
+ await permission_manager.load_permissions(db=db, branch=branch_params.branch)
134
+
135
+ return permission_manager
infrahub/api/diff/diff.py CHANGED
@@ -7,7 +7,7 @@ from fastapi import APIRouter, Depends, Request
7
7
 
8
8
  from infrahub.api.dependencies import get_branch_dep, get_current_user, get_db
9
9
  from infrahub.core import registry
10
- from infrahub.core.branch import Branch # noqa: TCH001
10
+ from infrahub.core.branch import Branch # noqa: TC001
11
11
  from infrahub.core.diff.artifacts.calculator import ArtifactDiffCalculator
12
12
  from infrahub.core.diff.branch_differ import BranchDiffer
13
13
  from infrahub.core.diff.model.diff import (
@@ -15,7 +15,7 @@ from infrahub.core.diff.model.diff import (
15
15
  BranchDiffFile,
16
16
  BranchDiffRepository,
17
17
  )
18
- from infrahub.database import InfrahubDatabase # noqa: TCH001
18
+ from infrahub.database import InfrahubDatabase # noqa: TC001
19
19
 
20
20
  if TYPE_CHECKING:
21
21
  from infrahub.services import InfrahubServices
infrahub/api/file.py CHANGED
@@ -5,15 +5,10 @@ from typing import TYPE_CHECKING, Optional, Union
5
5
  from fastapi import APIRouter, Depends, Request
6
6
  from starlette.responses import PlainTextResponse
7
7
 
8
- from infrahub.api.dependencies import (
9
- BranchParams,
10
- get_branch_params,
11
- get_current_user,
12
- get_db,
13
- )
8
+ from infrahub.api.dependencies import BranchParams, get_branch_params, get_current_user, get_db
14
9
  from infrahub.core.constants import InfrahubKind
15
10
  from infrahub.core.manager import NodeManager
16
- from infrahub.database import InfrahubDatabase # noqa: TCH001
11
+ from infrahub.database import InfrahubDatabase # noqa: TC001
17
12
  from infrahub.exceptions import CommitNotFoundError, PropagatedFromWorkerError
18
13
  from infrahub.message_bus.messages import GitFileGet, GitFileGetResponse
19
14
 
infrahub/api/menu.py CHANGED
@@ -4,17 +4,17 @@ from typing import TYPE_CHECKING
4
4
 
5
5
  from fastapi import APIRouter, Depends
6
6
 
7
- from infrahub.api.dependencies import get_branch_dep, get_current_user, get_db
7
+ from infrahub.api.dependencies import get_branch_dep, get_db, get_permission_manager
8
8
  from infrahub.core import registry
9
- from infrahub.core.branch import Branch # noqa: TCH001
9
+ from infrahub.core.branch import Branch # noqa: TC001
10
10
  from infrahub.core.protocols import CoreMenuItem
11
11
  from infrahub.log import get_logger
12
12
  from infrahub.menu.generator import generate_restricted_menu
13
- from infrahub.menu.models import Menu # noqa: TCH001
13
+ from infrahub.menu.models import Menu # noqa: TC001
14
14
 
15
15
  if TYPE_CHECKING:
16
- from infrahub.auth import AccountSession
17
16
  from infrahub.database import InfrahubDatabase
17
+ from infrahub.permissions import PermissionManager
18
18
 
19
19
 
20
20
  log = get_logger()
@@ -25,10 +25,12 @@ router = APIRouter(prefix="/menu")
25
25
  async def get_menu(
26
26
  db: InfrahubDatabase = Depends(get_db),
27
27
  branch: Branch = Depends(get_branch_dep),
28
- account_session: AccountSession = Depends(get_current_user),
28
+ permission_manager: PermissionManager = Depends(get_permission_manager),
29
29
  ) -> Menu:
30
30
  log.info("menu_request", branch=branch.name)
31
31
 
32
- menu_items = await registry.manager.query(db=db, schema=CoreMenuItem, branch=branch)
33
- menu = await generate_restricted_menu(db=db, branch=branch, account=account_session, menu_items=menu_items)
32
+ menu_items = await registry.manager.query(db=db, schema=CoreMenuItem, branch=branch, prefetch_relationships=True)
33
+ menu = await generate_restricted_menu(
34
+ db=db, branch=branch, menu_items=menu_items, account_permissions=permission_manager
35
+ )
34
36
  return menu.to_rest()
infrahub/api/oauth2.py CHANGED
@@ -25,8 +25,8 @@ router = APIRouter(prefix="/oauth2")
25
25
 
26
26
 
27
27
  def _get_redirect_url(request: Request, provider_name: str) -> str:
28
- """This function is mostly to support local development when the frontend runs on different ports compared to the API."""
29
- base_url = config.SETTINGS.dev.frontend_url or str(request.base_url)
28
+ """Return public redirect URL."""
29
+ base_url = config.SETTINGS.main.public_url or str(request.base_url)
30
30
  return urljoin(base_url, f"auth/oauth2/{provider_name}/callback")
31
31
 
32
32
 
@@ -40,7 +40,7 @@ async def authorize(request: Request, provider_name: str, final_url: str | None
40
40
  )
41
41
 
42
42
  redirect_uri = _get_redirect_url(request=request, provider_name=provider_name)
43
- final_url = final_url or config.SETTINGS.dev.frontend_url or str(request.base_url)
43
+ final_url = final_url or config.SETTINGS.main.public_url or str(request.base_url)
44
44
 
45
45
  authorization_uri, state = client.create_authorization_url(
46
46
  url=provider.authorization_url, redirect_uri=redirect_uri, scope=provider.scopes, final_url=final_url
infrahub/api/oidc.py CHANGED
@@ -54,8 +54,8 @@ class OIDCDiscoveryConfig(BaseModel):
54
54
 
55
55
 
56
56
  def _get_redirect_url(request: Request, provider_name: str) -> str:
57
- """This function is mostly to support local development when the frontend runs on different ports compared to the API."""
58
- base_url = config.SETTINGS.dev.frontend_url or str(request.base_url)
57
+ """Return public redirect URL."""
58
+ base_url = config.SETTINGS.main.public_url or str(request.base_url)
59
59
  return urljoin(base_url, f"auth/oidc/{provider_name}/callback")
60
60
 
61
61
 
@@ -75,7 +75,7 @@ async def authorize(request: Request, provider_name: str, final_url: str | None
75
75
  )
76
76
 
77
77
  redirect_uri = _get_redirect_url(request=request, provider_name=provider_name)
78
- final_url = final_url or config.SETTINGS.dev.frontend_url or str(request.base_url)
78
+ final_url = final_url or config.SETTINGS.main.public_url or str(request.base_url)
79
79
 
80
80
  authorization_uri, state = client.create_authorization_url(
81
81
  url=str(oidc_config.authorization_endpoint), redirect_uri=redirect_uri, scope=provider.scopes
infrahub/api/query.py CHANGED
@@ -10,7 +10,7 @@ from infrahub.api.dependencies import BranchParams, get_branch_params, get_curre
10
10
  from infrahub.core import registry
11
11
  from infrahub.core.constants import InfrahubKind
12
12
  from infrahub.core.protocols import CoreGraphQLQuery
13
- from infrahub.database import InfrahubDatabase # noqa: TCH001
13
+ from infrahub.database import InfrahubDatabase # noqa: TC001
14
14
  from infrahub.graphql.analyzer import InfrahubGraphQLQueryAnalyzer
15
15
  from infrahub.graphql.api.dependencies import build_graphql_query_permission_checker
16
16
  from infrahub.graphql.initialization import prepare_graphql_params
@@ -26,7 +26,7 @@ from infrahub.graphql.metrics import (
26
26
  from infrahub.graphql.utils import extract_data
27
27
  from infrahub.groups.models import RequestGraphQLQueryGroupUpdate
28
28
  from infrahub.log import get_logger
29
- from infrahub.workflows.catalogue import UPDATE_GRAPHQL_QUERY_GROUP
29
+ from infrahub.workflows.catalogue import GRAPHQL_QUERY_GROUP_UPDATE
30
30
 
31
31
  if TYPE_CHECKING:
32
32
  from infrahub.auth import AccountSession
@@ -57,7 +57,7 @@ async def execute_query(
57
57
  db=db, id=query_id, kind=CoreGraphQLQuery, branch=branch_params.branch, at=branch_params.at
58
58
  )
59
59
 
60
- gql_params = prepare_graphql_params(
60
+ gql_params = await prepare_graphql_params(
61
61
  db=db, branch=branch_params.branch, at=branch_params.at, account_session=account_session
62
62
  )
63
63
  analyzed_query = InfrahubGraphQLQueryAnalyzer(
@@ -115,7 +115,7 @@ async def execute_query(
115
115
  subscribers=sorted(subscribers),
116
116
  params=params,
117
117
  )
118
- await service.workflow.submit_workflow(workflow=UPDATE_GRAPHQL_QUERY_GROUP, parameters={"model": model})
118
+ await service.workflow.submit_workflow(workflow=GRAPHQL_QUERY_GROUP_UPDATE, parameters={"model": model})
119
119
 
120
120
  return response_payload
121
121
 
infrahub/api/schema.py CHANGED
@@ -13,28 +13,28 @@ from pydantic import (
13
13
  from starlette.responses import JSONResponse
14
14
 
15
15
  from infrahub import lock
16
- from infrahub.api.dependencies import get_branch_dep, get_current_user, get_db
16
+ from infrahub.api.dependencies import get_branch_dep, get_current_user, get_db, get_permission_manager
17
17
  from infrahub.api.exceptions import SchemaNotValidError
18
18
  from infrahub.core import registry
19
19
  from infrahub.core.account import GlobalPermission
20
- from infrahub.core.branch import Branch # noqa: TCH001
20
+ from infrahub.core.branch import Branch # noqa: TC001
21
21
  from infrahub.core.constants import GLOBAL_BRANCH_NAME, GlobalPermissions, PermissionDecision
22
22
  from infrahub.core.migrations.schema.models import SchemaApplyMigrationData
23
- from infrahub.core.models import ( # noqa: TCH001
23
+ from infrahub.core.models import ( # noqa: TC001
24
24
  SchemaBranchHash,
25
25
  SchemaDiff,
26
26
  SchemaUpdateValidationResult,
27
27
  )
28
28
  from infrahub.core.schema import GenericSchema, MainSchemaTypes, NodeSchema, ProfileSchema, SchemaRoot
29
- from infrahub.core.schema.constants import SchemaNamespace # noqa: TCH001
29
+ from infrahub.core.schema.constants import SchemaNamespace # noqa: TC001
30
30
  from infrahub.core.validators.models.validate_migration import (
31
31
  SchemaValidateMigrationData,
32
32
  SchemaValidatorPathResponseData,
33
33
  )
34
- from infrahub.database import InfrahubDatabase # noqa: TCH001
34
+ from infrahub.database import InfrahubDatabase # noqa: TC001
35
35
  from infrahub.events import EventMeta
36
36
  from infrahub.events.schema_action import SchemaUpdatedEvent
37
- from infrahub.exceptions import MigrationError, PermissionDeniedError
37
+ from infrahub.exceptions import MigrationError
38
38
  from infrahub.log import get_log_data, get_logger
39
39
  from infrahub.types import ATTRIBUTE_PYTHON_TYPES
40
40
  from infrahub.worker import WORKER_IDENTITY
@@ -45,6 +45,7 @@ if TYPE_CHECKING:
45
45
 
46
46
  from infrahub.auth import AccountSession
47
47
  from infrahub.core.schema.schema_branch import SchemaBranch
48
+ from infrahub.permissions import PermissionManager
48
49
  from infrahub.services import InfrahubServices
49
50
 
50
51
 
@@ -248,43 +249,25 @@ async def load_schema(
248
249
  db: InfrahubDatabase = Depends(get_db),
249
250
  branch: Branch = Depends(get_branch_dep),
250
251
  account_session: AccountSession = Depends(get_current_user),
252
+ permission_manager: PermissionManager = Depends(get_permission_manager),
251
253
  ) -> SchemaUpdate:
252
- has_permission = False
253
- has_branch_permission = branch.name not in (GLOBAL_BRANCH_NAME, registry.default_branch)
254
- for permission_backend in registry.permission_backends:
255
- if not has_permission:
256
- has_permission = await permission_backend.has_permission(
257
- db=db,
258
- account_session=account_session,
259
- permission=GlobalPermission(
260
- action=GlobalPermissions.MANAGE_SCHEMA.value,
261
- decision=(
262
- PermissionDecision.ALLOW_DEFAULT
263
- if branch.name in (GLOBAL_BRANCH_NAME, registry.default_branch)
264
- else PermissionDecision.ALLOW_OTHER
265
- ).value,
266
- ),
267
- branch=branch,
268
- )
269
-
270
- if not has_branch_permission:
271
- has_branch_permission = await permission_backend.has_permission(
272
- db=db,
273
- account_session=account_session,
274
- permission=GlobalPermission(
275
- action=GlobalPermissions.EDIT_DEFAULT_BRANCH.value,
276
- decision=PermissionDecision.ALLOW_DEFAULT.value,
277
- ),
278
- branch=branch,
279
- )
280
-
281
- if has_permission and has_branch_permission:
282
- break
254
+ permission_manager.raise_for_permission(
255
+ permission=GlobalPermission(
256
+ action=GlobalPermissions.MANAGE_SCHEMA.value,
257
+ decision=(
258
+ PermissionDecision.ALLOW_DEFAULT
259
+ if branch.name in (GLOBAL_BRANCH_NAME, registry.default_branch)
260
+ else PermissionDecision.ALLOW_OTHER
261
+ ).value,
262
+ )
263
+ )
283
264
 
284
- if not has_permission:
285
- raise PermissionDeniedError("You are not allowed to manage the schema")
286
- if not has_branch_permission:
287
- raise PermissionDeniedError("You are not allowed to edit the schema in the default branch")
265
+ if branch.name in (GLOBAL_BRANCH_NAME, registry.default_branch):
266
+ permission_manager.raise_for_permission(
267
+ permission=GlobalPermission(
268
+ action=GlobalPermissions.EDIT_DEFAULT_BRANCH.value, decision=PermissionDecision.ALLOW_DEFAULT.value
269
+ ),
270
+ )
288
271
 
289
272
  service: InfrahubServices = request.app.state.service
290
273
  log.info("schema_load_request", branch=branch.name)
@@ -19,7 +19,7 @@ from infrahub.core.protocols import (
19
19
  CoreTransformJinja2,
20
20
  CoreTransformPython,
21
21
  )
22
- from infrahub.database import InfrahubDatabase # noqa: TCH001
22
+ from infrahub.database import InfrahubDatabase # noqa: TC001
23
23
  from infrahub.exceptions import TransformError
24
24
  from infrahub.graphql.initialization import prepare_graphql_params
25
25
  from infrahub.graphql.utils import extract_data
@@ -61,7 +61,7 @@ async def transform_python(
61
61
  message="Repository doesn't have a commit",
62
62
  )
63
63
 
64
- gql_params = prepare_graphql_params(db=request.app.state.db, branch=branch_params.branch, at=branch_params.at)
64
+ gql_params = await prepare_graphql_params(db=request.app.state.db, branch=branch_params.branch, at=branch_params.at)
65
65
 
66
66
  result = await graphql(
67
67
  schema=gql_params.schema,
@@ -120,7 +120,7 @@ async def transform_jinja2(
120
120
  message="Repository doesn't have a commit",
121
121
  )
122
122
 
123
- gql_params = prepare_graphql_params(db=request.app.state.db, branch=branch_params.branch, at=branch_params.at)
123
+ gql_params = await prepare_graphql_params(db=request.app.state.db, branch=branch_params.branch, at=branch_params.at)
124
124
 
125
125
  result = await graphql(
126
126
  schema=gql_params.schema,
infrahub/auth.py CHANGED
@@ -22,8 +22,6 @@ if TYPE_CHECKING:
22
22
  from infrahub.core.protocols import CoreGenericAccount
23
23
  from infrahub.database import InfrahubDatabase
24
24
 
25
- # from ..datatypes import AuthResult
26
-
27
25
 
28
26
  class AuthType(str, Enum):
29
27
  NONE = "none"
infrahub/cli/db.py CHANGED
@@ -35,17 +35,18 @@ from infrahub.core.initialization import (
35
35
  from infrahub.core.manager import NodeManager
36
36
  from infrahub.core.migrations.graph import get_graph_migrations
37
37
  from infrahub.core.migrations.schema.models import SchemaApplyMigrationData
38
+ from infrahub.core.migrations.schema.tasks import schema_apply_migrations
38
39
  from infrahub.core.schema import SchemaRoot, core_models, internal_schema
39
40
  from infrahub.core.schema.definitions.deprecated import deprecated_models
40
41
  from infrahub.core.schema.manager import SchemaManager
41
42
  from infrahub.core.utils import delete_all_nodes
42
43
  from infrahub.core.validators.models.validate_migration import SchemaValidateMigrationData
44
+ from infrahub.core.validators.tasks import schema_validate_migrations
43
45
  from infrahub.database import DatabaseType
44
46
  from infrahub.log import get_logger
45
47
  from infrahub.services import InfrahubServices, services
46
48
  from infrahub.services.adapters.message_bus.local import BusSimulator
47
49
  from infrahub.services.adapters.workflow.local import WorkflowLocalExecution
48
- from infrahub.workflows.catalogue import SCHEMA_APPLY_MIGRATION, SCHEMA_VALIDATE_MIGRATION
49
50
 
50
51
  if TYPE_CHECKING:
51
52
  from infrahub.cli.context import CliContext
@@ -142,6 +143,10 @@ async def migrate(
142
143
  config_file: str = typer.Argument("infrahub.toml", envvar="INFRAHUB_CONFIG"),
143
144
  ) -> None:
144
145
  """Check the current format of the internal graph and apply the necessary migrations"""
146
+ logging.getLogger("infrahub").setLevel(logging.WARNING)
147
+ logging.getLogger("neo4j").setLevel(logging.ERROR)
148
+ logging.getLogger("prefect").setLevel(logging.ERROR)
149
+
145
150
  log = get_logger()
146
151
 
147
152
  config.load_and_exit(config_file_name=config_file)
@@ -264,11 +269,8 @@ async def update_core_schema( # pylint: disable=too-many-statements
264
269
  schema_branch=candidate_schema,
265
270
  constraints=result.constraints,
266
271
  )
267
- error_messages = await service.workflow.execute_workflow(
268
- workflow=SCHEMA_VALIDATE_MIGRATION,
269
- expected_return=list[str],
270
- parameters={"message": validate_migration_data},
271
- )
272
+ responses = await schema_validate_migrations(message=validate_migration_data)
273
+ error_messages = [violation.message for response in responses for violation in response.violations]
272
274
  if error_messages:
273
275
  rprint(f"{error_badge} | Unable to update the schema, due to failed validations")
274
276
  for message in error_messages:
@@ -309,11 +311,7 @@ async def update_core_schema( # pylint: disable=too-many-statements
309
311
  previous_schema=origin_schema,
310
312
  migrations=result.migrations,
311
313
  )
312
- migration_error_msgs = await service.workflow.execute_workflow(
313
- workflow=SCHEMA_APPLY_MIGRATION,
314
- expected_return=list[str],
315
- parameters={"message": apply_migration_data},
316
- )
314
+ migration_error_msgs = await schema_apply_migrations(message=apply_migration_data)
317
315
 
318
316
  if migration_error_msgs:
319
317
  rprint(f"{error_badge} | Some error(s) happened while running the schema migrations")
infrahub/cli/tasks.py CHANGED
@@ -44,7 +44,9 @@ async def execute(
44
44
 
45
45
  async with get_client(sync_client=False) as client:
46
46
  worker = WorkflowWorkerExecution()
47
- await DUMMY_FLOW.save(client=client, work_pool=WorkerPoolDefinition(name="testing", worker_type="process"))
47
+ await DUMMY_FLOW.save(
48
+ client=client, work_pool=WorkerPoolDefinition(name="infrahub-worker", worker_type="infrahubasync")
49
+ )
48
50
 
49
51
  result = await worker.execute_workflow(
50
52
  workflow=DUMMY_FLOW, parameters={"data": DummyInput(firstname="John", lastname="Doe")}
@@ -4,7 +4,7 @@ PROCESS_PYTHON_AUTOMATION_NAME_PREFIX = "Computed-attribute-process-python"
4
4
  PROCESS_AUTOMATION_NAME_PREFIX = "Computed-attribute-process"
5
5
  QUERY_AUTOMATION_NAME_PREFIX = "Computed-attribute-query"
6
6
 
7
- PROCESS_AUTOMATION_NAME = "{prefix}::{identifier}::{scope}"
8
- QUERY_AUTOMATION_NAME = QUERY_AUTOMATION_NAME_PREFIX + "::{identifier}::{scope}"
7
+ PROCESS_AUTOMATION_NAME = "{prefix}::{scope}::{identifier}"
8
+ QUERY_AUTOMATION_NAME = QUERY_AUTOMATION_NAME_PREFIX + "::{scope}::{identifier}"
9
9
 
10
10
  VALID_KINDS = ["Text", "URL"]
@@ -1,16 +1,18 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  from collections import defaultdict
4
- from dataclasses import dataclass
4
+ from dataclasses import dataclass, field
5
5
  from typing import TYPE_CHECKING
6
6
 
7
- from prefect.events.schemas.automations import Automation # noqa: TCH002
7
+ from prefect.events.schemas.automations import Automation # noqa: TC002
8
8
  from pydantic import BaseModel, Field
9
9
  from typing_extensions import Self
10
10
 
11
11
  if TYPE_CHECKING:
12
12
  from uuid import UUID
13
13
 
14
+ from infrahub_sdk.data import RepositoryData
15
+
14
16
  from infrahub.core.schema.schema_branch_computed import PythonDefinition
15
17
 
16
18
 
@@ -28,8 +30,8 @@ class ComputedAttributeAutomations(BaseModel):
28
30
  if len(name_split) != 3:
29
31
  continue
30
32
 
31
- identifier = name_split[1]
32
- scope = name_split[2]
33
+ scope = name_split[1]
34
+ identifier = name_split[2]
33
35
 
34
36
  obj.data[identifier][scope] = automation
35
37
 
@@ -46,12 +48,15 @@ class ComputedAttributeAutomations(BaseModel):
46
48
  return False
47
49
 
48
50
  def return_obsolete(self, keep: list[UUID]) -> list[UUID]:
49
- remove = []
51
+ return [automation_id for automation_id in self.all_automation_ids if automation_id not in keep]
52
+
53
+ @property
54
+ def all_automation_ids(self) -> list[UUID]:
55
+ automation_ids: list[UUID] = []
50
56
  for identifier in self.data.values():
51
57
  for automation in identifier.values():
52
- if automation.id not in keep:
53
- remove.append(automation.id)
54
- return remove
58
+ automation_ids.append(automation.id)
59
+ return automation_ids
55
60
 
56
61
 
57
62
  @dataclass
@@ -63,6 +68,13 @@ class PythonTransformComputedAttribute:
63
68
  query_name: str
64
69
  query_models: list[str]
65
70
  computed_attribute: PythonDefinition
71
+ default_schema: bool
72
+ branch_commit: dict[str, str] = field(default_factory=dict)
73
+
74
+ def populate_branch_commit(self, repository_data: RepositoryData | None = None) -> None:
75
+ if repository_data:
76
+ for branch, commit in repository_data.branches.items():
77
+ self.branch_commit[branch] = commit
66
78
 
67
79
 
68
80
  @dataclass