infrahub-server 1.1.1__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 (113) 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 +8 -6
  6. infrahub/api/oauth2.py +3 -3
  7. infrahub/api/oidc.py +3 -3
  8. infrahub/api/query.py +2 -2
  9. infrahub/api/schema.py +24 -41
  10. infrahub/api/transformation.py +3 -3
  11. infrahub/auth.py +0 -2
  12. infrahub/computed_attribute/models.py +1 -1
  13. infrahub/computed_attribute/tasks.py +1 -1
  14. infrahub/config.py +4 -4
  15. infrahub/core/account.py +2 -10
  16. infrahub/core/branch/models.py +1 -1
  17. infrahub/core/branch/tasks.py +4 -3
  18. infrahub/core/diff/combiner.py +1 -0
  19. infrahub/core/diff/coordinator.py +286 -87
  20. infrahub/core/diff/data_check_synchronizer.py +33 -4
  21. infrahub/core/diff/enricher/hierarchy.py +2 -0
  22. infrahub/core/diff/merger/merger.py +1 -1
  23. infrahub/core/diff/model/path.py +85 -3
  24. infrahub/core/diff/query/field_specifiers.py +35 -0
  25. infrahub/core/diff/query/roots_metadata.py +48 -0
  26. infrahub/core/diff/query/save.py +1 -0
  27. infrahub/core/diff/query_parser.py +1 -0
  28. infrahub/core/diff/repository/deserializer.py +7 -3
  29. infrahub/core/diff/repository/repository.py +98 -7
  30. infrahub/core/diff/tasks.py +1 -1
  31. infrahub/core/graph/__init__.py +1 -1
  32. infrahub/core/integrity/object_conflict/conflict_recorder.py +6 -1
  33. infrahub/core/manager.py +8 -0
  34. infrahub/core/merge.py +1 -1
  35. infrahub/core/migrations/graph/__init__.py +2 -0
  36. infrahub/core/migrations/graph/m014_remove_index_attr_value.py +1 -1
  37. infrahub/core/migrations/graph/m015_diff_format_update.py +1 -1
  38. infrahub/core/migrations/graph/m016_diff_delete_bug_fix.py +1 -1
  39. infrahub/core/migrations/graph/m018_uniqueness_nulls.py +101 -0
  40. infrahub/core/migrations/schema/tasks.py +2 -2
  41. infrahub/core/migrations/shared.py +3 -3
  42. infrahub/core/node/__init__.py +8 -2
  43. infrahub/core/node/constraints/grouped_uniqueness.py +9 -2
  44. infrahub/core/query/__init__.py +5 -2
  45. infrahub/core/query/node.py +87 -40
  46. infrahub/core/schema/generated/attribute_schema.py +2 -2
  47. infrahub/core/schema/generated/base_node_schema.py +2 -2
  48. infrahub/core/schema/generated/relationship_schema.py +1 -1
  49. infrahub/core/schema/schema_branch_computed.py +1 -1
  50. infrahub/core/task/task_log.py +1 -1
  51. infrahub/core/validators/interface.py +1 -2
  52. infrahub/core/validators/shared.py +2 -2
  53. infrahub/core/validators/tasks.py +3 -3
  54. infrahub/core/validators/uniqueness/index.py +2 -4
  55. infrahub/database/index.py +1 -1
  56. infrahub/dependencies/builder/diff/data_check_synchronizer.py +2 -0
  57. infrahub/git/base.py +3 -3
  58. infrahub/git/integrator.py +1 -1
  59. infrahub/graphql/app.py +2 -2
  60. infrahub/graphql/auth/query_permission_checker/default_branch_checker.py +2 -17
  61. infrahub/graphql/auth/query_permission_checker/merge_operation_checker.py +1 -12
  62. infrahub/graphql/auth/query_permission_checker/object_permission_checker.py +6 -40
  63. infrahub/graphql/auth/query_permission_checker/super_admin_checker.py +5 -8
  64. infrahub/graphql/enums.py +2 -2
  65. infrahub/graphql/initialization.py +27 -8
  66. infrahub/graphql/manager.py +9 -3
  67. infrahub/graphql/models.py +6 -0
  68. infrahub/graphql/mutations/account.py +10 -6
  69. infrahub/graphql/mutations/computed_attribute.py +11 -22
  70. infrahub/graphql/mutations/diff.py +2 -0
  71. infrahub/graphql/mutations/proposed_change.py +11 -20
  72. infrahub/graphql/mutations/resource_manager.py +3 -0
  73. infrahub/graphql/mutations/schema.py +8 -7
  74. infrahub/graphql/mutations/tasks.py +1 -1
  75. infrahub/graphql/permissions.py +3 -4
  76. infrahub/graphql/queries/account.py +2 -11
  77. infrahub/graphql/query.py +3 -1
  78. infrahub/graphql/resolvers/resolver.py +5 -1
  79. infrahub/graphql/types/task.py +14 -2
  80. infrahub/menu/generator.py +6 -18
  81. infrahub/message_bus/messages/event_node_mutated.py +2 -2
  82. infrahub/message_bus/operations/check/repository.py +2 -4
  83. infrahub/message_bus/operations/event/branch.py +2 -4
  84. infrahub/message_bus/operations/requests/proposed_change.py +1 -1
  85. infrahub/message_bus/operations/requests/repository.py +3 -5
  86. infrahub/message_bus/types.py +1 -1
  87. infrahub/permissions/__init__.py +12 -3
  88. infrahub/permissions/backend.py +2 -17
  89. infrahub/permissions/constants.py +12 -8
  90. infrahub/permissions/local_backend.py +5 -102
  91. infrahub/permissions/manager.py +135 -0
  92. infrahub/permissions/report.py +14 -25
  93. infrahub/permissions/types.py +6 -0
  94. infrahub/proposed_change/tasks.py +1 -1
  95. infrahub/task_manager/models.py +34 -5
  96. infrahub/task_manager/task.py +9 -5
  97. infrahub/visuals.py +1 -3
  98. infrahub_sdk/client.py +204 -43
  99. infrahub_sdk/ctl/cli_commands.py +106 -6
  100. infrahub_sdk/data.py +3 -2
  101. infrahub_sdk/graphql.py +5 -0
  102. infrahub_sdk/node.py +21 -2
  103. infrahub_sdk/queries.py +69 -0
  104. infrahub_sdk/schema/main.py +1 -0
  105. infrahub_sdk/testing/schemas/animal.py +1 -0
  106. infrahub_sdk/types.py +6 -0
  107. infrahub_sdk/utils.py +17 -0
  108. {infrahub_server-1.1.1.dist-info → infrahub_server-1.1.2.dist-info}/METADATA +1 -1
  109. {infrahub_server-1.1.1.dist-info → infrahub_server-1.1.2.dist-info}/RECORD +112 -108
  110. infrahub/core/diff/query/empty_roots.py +0 -33
  111. {infrahub_server-1.1.1.dist-info → infrahub_server-1.1.2.dist-info}/LICENSE.txt +0 -0
  112. {infrahub_server-1.1.1.dist-info → infrahub_server-1.1.2.dist-info}/WHEEL +0 -0
  113. {infrahub_server-1.1.1.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
32
  menu_items = await registry.manager.query(db=db, schema=CoreMenuItem, branch=branch, prefetch_relationships=True)
33
- menu = await generate_restricted_menu(db=db, branch=branch, account=account_session, menu_items=menu_items)
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
@@ -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(
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"
@@ -4,7 +4,7 @@ from collections import defaultdict
4
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
 
@@ -4,7 +4,7 @@ from datetime import timedelta
4
4
  from typing import TYPE_CHECKING, Any
5
5
 
6
6
  import ujson
7
- from infrahub_sdk.protocols import CoreNode # noqa: TCH002
7
+ from infrahub_sdk.protocols import CoreNode # noqa: TC002
8
8
  from prefect import flow
9
9
  from prefect.automations import AutomationCore
10
10
  from prefect.client.orchestration import get_client
infrahub/config.py CHANGED
@@ -153,6 +153,10 @@ class MainSettings(BaseSettings):
153
153
  default=["infrahub.permissions.LocalPermissionBackend"],
154
154
  description="List of modules to handle permissions, they will be run in the given order",
155
155
  )
156
+ public_url: Optional[str] = Field(
157
+ default=None,
158
+ description="Define the public URL of the Infrahub, might be required for OAuth2 and OIDC depending on your infrastructure.",
159
+ )
156
160
 
157
161
  @field_validator("docs_index_path", mode="before")
158
162
  @classmethod
@@ -256,10 +260,6 @@ class DevelopmentSettings(BaseSettings):
256
260
 
257
261
  model_config = SettingsConfigDict(env_prefix="INFRAHUB_DEV_")
258
262
 
259
- frontend_url: Optional[str] = Field(
260
- default=None,
261
- description="Define the URL of the frontend, useful for OAuth2 development when the frontend and backend use different ports.",
262
- )
263
263
  frontend_redirect_sso: bool = Field(
264
264
  default=False,
265
265
  description="Indicates of the frontend should be responsible for the SSO redirection",
infrahub/core/account.py CHANGED
@@ -12,7 +12,7 @@ from infrahub.core.registry import registry
12
12
  if TYPE_CHECKING:
13
13
  from infrahub.core.branch import Branch
14
14
  from infrahub.database import InfrahubDatabase
15
- from infrahub.permissions.constants import AssignedPermissions
15
+ from infrahub.permissions import AssignedPermissions
16
16
 
17
17
 
18
18
  # pylint: disable=redefined-builtin
@@ -35,15 +35,7 @@ class GlobalPermission:
35
35
  if len(parts) != 3 and parts[0] != "global":
36
36
  raise ValueError(f"{input} is not a valid format for a Global permission")
37
37
 
38
- # FIXME there is probably a better way to convert the decision
39
- decision = PermissionDecision.DENY
40
- if parts[2] == "allow_default":
41
- decision = PermissionDecision.ALLOW_DEFAULT
42
- elif parts[2] == "allow_all":
43
- decision = PermissionDecision.ALLOW_ALL
44
- elif parts[2] == "allow_other":
45
- decision = PermissionDecision.ALLOW_OTHER
46
- return cls(action=str(parts[1]), decision=decision)
38
+ return cls(action=parts[1], decision=PermissionDecision[parts[2].upper()])
47
39
 
48
40
 
49
41
  @dataclass
@@ -8,7 +8,7 @@ from pydantic import Field, field_validator
8
8
  from infrahub.core.constants import (
9
9
  GLOBAL_BRANCH_NAME,
10
10
  )
11
- from infrahub.core.models import SchemaBranchHash # noqa: TCH001
11
+ from infrahub.core.models import SchemaBranchHash # noqa: TC001
12
12
  from infrahub.core.node.standard import StandardNode
13
13
  from infrahub.core.query import QueryType
14
14
  from infrahub.core.query.branch import (
@@ -8,7 +8,7 @@ from prefect import flow, get_run_logger
8
8
  from prefect.automations import AutomationCore
9
9
  from prefect.client.orchestration import get_client
10
10
  from prefect.client.schemas.filters import DeploymentFilter, DeploymentFilterName
11
- from prefect.client.schemas.objects import State # noqa: TCH002
11
+ from prefect.client.schemas.objects import State # noqa: TC002
12
12
  from prefect.events.actions import RunDeployment
13
13
  from prefect.events.schemas.automations import EventTrigger, Posture
14
14
  from prefect.states import Completed, Failed
@@ -30,7 +30,7 @@ from infrahub.core.validators.tasks import schema_validate_migrations
30
30
  from infrahub.dependencies.registry import get_component_registry
31
31
  from infrahub.events.branch_action import BranchCreateEvent, BranchDeleteEvent, BranchRebaseEvent
32
32
  from infrahub.exceptions import BranchNotFoundError, MergeFailedError, ValidationError
33
- from infrahub.graphql.mutations.models import BranchCreateModel # noqa: TCH001
33
+ from infrahub.graphql.mutations.models import BranchCreateModel # noqa: TC001
34
34
  from infrahub.log import get_log_data
35
35
  from infrahub.message_bus import Meta, messages
36
36
  from infrahub.services import services
@@ -70,7 +70,7 @@ async def rebase_branch(branch: str) -> None:
70
70
  service=service,
71
71
  )
72
72
  diff_repository = await component_registry.get_component(DiffRepository, db=db, branch=obj)
73
- enriched_diff = await diff_coordinator.update_branch_diff(base_branch=base_branch, diff_branch=obj)
73
+ enriched_diff = await diff_coordinator.update_branch_diff_and_return(base_branch=base_branch, diff_branch=obj)
74
74
  if enriched_diff.get_all_conflicts():
75
75
  raise ValidationError(
76
76
  f"Branch {obj.name} contains conflicts with the default branch that must be addressed."
@@ -185,6 +185,7 @@ async def merge_branch(branch: str) -> None:
185
185
  try:
186
186
  await merger.merge()
187
187
  except Exception as exc:
188
+ log.exception("Merge failed, beginning rollback")
188
189
  await merger.rollback()
189
190
  raise MergeFailedError(branch_name=branch) from exc
190
191
  await merger.update_schema()
@@ -320,6 +320,7 @@ class DiffCombiner:
320
320
  combined_relationship = EnrichedDiffRelationship(
321
321
  name=later_relationship.name,
322
322
  label=later_relationship.label,
323
+ identifier=later_relationship.identifier,
323
324
  cardinality=later_relationship.cardinality,
324
325
  changed_at=later_relationship.changed_at or earlier_relationship.changed_at,
325
326
  action=combined_action,