blueprints: Support nested custom tags in !Find and !Format tags (#4127)
				
					
				
			* Added support for nested tags to !Find and !Format * Added tests * Fix variable names * Added docs * Fixed small mistake in tests * Fixed variable names * Broke example into multiple lines
This commit is contained in:
		
							
								
								
									
										13
									
								
								authentik/blueprints/tests/fixtures/tags.yaml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										13
									
								
								authentik/blueprints/tests/fixtures/tags.yaml
									
									
									
									
										vendored
									
									
								
							| @ -1,10 +1,19 @@ | ||||
| version: 1 | ||||
| context: | ||||
|     foo: bar | ||||
|     policy_property: name | ||||
|     policy_property_value: foo-bar-baz-qux | ||||
| entries: | ||||
| - attrs: | ||||
|     expression: return True | ||||
|   identifiers: | ||||
|     name: !Format [foo-%s-%s, !Context foo, !Context bar] | ||||
|   id: default-source-enrollment-if-username | ||||
|     name: !Format [foo-%s-%s-%s, !Context foo, !Context bar, qux] | ||||
|   id: policy | ||||
|   model: authentik_policies_expression.expressionpolicy | ||||
| - attrs: | ||||
|     attributes: | ||||
|       policy_pk1: !Format ["%s-%s", !Find [authentik_policies_expression.expressionpolicy, [!Context policy_property, !Context policy_property_value], [expression, return True]], suffix] | ||||
|       policy_pk2: !Format ["%s-%s", !KeyOf policy, suffix] | ||||
|   identifiers: | ||||
|     name: test | ||||
|   model: authentik_core.group | ||||
|  | ||||
| @ -4,6 +4,7 @@ from django.test import TransactionTestCase | ||||
| from authentik.blueprints.tests import load_yaml_fixture | ||||
| from authentik.blueprints.v1.exporter import FlowExporter | ||||
| from authentik.blueprints.v1.importer import Importer, transaction_rollback | ||||
| from authentik.core.models import Group | ||||
| from authentik.flows.models import Flow, FlowDesignation, FlowStageBinding | ||||
| from authentik.lib.generators import generate_id | ||||
| from authentik.policies.expression.models import ExpressionPolicy | ||||
| @ -74,11 +75,21 @@ class TestBlueprintsV1(TransactionTestCase): | ||||
|  | ||||
|     def test_import_yaml_tags(self): | ||||
|         """Test some yaml tags""" | ||||
|         ExpressionPolicy.objects.filter(name="foo-foo-bar").delete() | ||||
|         ExpressionPolicy.objects.filter(name="foo-bar-baz-qux").delete() | ||||
|         Group.objects.filter(name="test").delete() | ||||
|         importer = Importer(load_yaml_fixture("fixtures/tags.yaml"), {"bar": "baz"}) | ||||
|         self.assertTrue(importer.validate()[0]) | ||||
|         self.assertTrue(importer.apply()) | ||||
|         self.assertTrue(ExpressionPolicy.objects.filter(name="foo-foo-bar")) | ||||
|         policy = ExpressionPolicy.objects.filter(name="foo-bar-baz-qux").first() | ||||
|         self.assertTrue(policy) | ||||
|         self.assertTrue( | ||||
|             Group.objects.filter( | ||||
|                 attributes__contains={ | ||||
|                     "policy_pk1": str(policy.pk) + "-suffix", | ||||
|                     "policy_pk2": str(policy.pk) + "-suffix", | ||||
|                 } | ||||
|             ) | ||||
|         ) | ||||
|  | ||||
|     def test_export_validate_import_policies(self): | ||||
|         """Test export and validate it""" | ||||
|  | ||||
| @ -188,11 +188,18 @@ class Format(YAMLTag): | ||||
|         self.format_string = node.value[0].value | ||||
|         self.args = [] | ||||
|         for raw_node in node.value[1:]: | ||||
|             self.args.append(raw_node.value) | ||||
|             self.args.append(loader.construct_object(raw_node)) | ||||
|  | ||||
|     def resolve(self, entry: BlueprintEntry, blueprint: Blueprint) -> Any: | ||||
|         args = [] | ||||
|         for arg in self.args: | ||||
|             if isinstance(arg, YAMLTag): | ||||
|                 args.append(arg.resolve(entry, blueprint)) | ||||
|             else: | ||||
|                 args.append(arg) | ||||
|  | ||||
|         try: | ||||
|             return self.format_string % tuple(self.args) | ||||
|             return self.format_string % tuple(args) | ||||
|         except TypeError as exc: | ||||
|             raise EntryInvalidError(exc) | ||||
|  | ||||
| @ -219,7 +226,15 @@ class Find(YAMLTag): | ||||
|     def resolve(self, entry: BlueprintEntry, blueprint: Blueprint) -> Any: | ||||
|         query = Q() | ||||
|         for cond in self.conditions: | ||||
|             query &= Q(**{cond[0]: cond[1]}) | ||||
|             if isinstance(cond[0], YAMLTag): | ||||
|                 query_key = cond[0].resolve(entry, blueprint) | ||||
|             else: | ||||
|                 query_key = cond[0] | ||||
|             if isinstance(cond[1], YAMLTag): | ||||
|                 query_value = cond[1].resolve(entry, blueprint) | ||||
|             else: | ||||
|                 query_value = cond[1] | ||||
|             query &= Q(**{query_key: query_value}) | ||||
|         instance = self.model_class.objects.filter(query).first() | ||||
|         if instance: | ||||
|             return instance.pk | ||||
|  | ||||
| @ -10,7 +10,19 @@ If no matching entry can be found, an error is raised and the blueprint is inval | ||||
|  | ||||
| #### `!Find` | ||||
|  | ||||
| Example: `configure_flow: !Find [authentik_flows.flow, [slug, default-password-change]]` | ||||
| Examples: | ||||
|  | ||||
| `configure_flow: !Find [authentik_flows.flow, [slug, default-password-change]]` | ||||
|  | ||||
| ``` | ||||
| configure_flow: !Find [ | ||||
|   authentik_flows.flow, | ||||
|   [ | ||||
|     !Context property_name, | ||||
|     !Context property_value | ||||
|   ] | ||||
| ] | ||||
| ``` | ||||
|  | ||||
| Looks up any model and resolves to the the matches' primary key. | ||||
| First argument is the model to be queried, remaining arguments are expected to be pairs of key=value pairs to query for. | ||||
|  | ||||
		Reference in New Issue
	
	Block a user
	 sdimovv
					sdimovv