Esempio n. 1
0
        public async Task <IActionResult> GetContents(string app, string name, [FromQuery] bool archived = false, [FromQuery] string ids = null)
        {
            HashSet <Guid> idsList = null;

            if (!string.IsNullOrWhiteSpace(ids))
            {
                idsList = new HashSet <Guid>();

                foreach (var id in ids.Split(','))
                {
                    if (Guid.TryParse(id, out var guid))
                    {
                        idsList.Add(guid);
                    }
                }
            }

            var isFrontendClient = User.IsFrontendClient();

            var result =
                idsList?.Count > 0 ?
                await contentQuery.QueryAsync(App, name, User, archived, idsList) :
                await contentQuery.QueryAsync(App, name, User, archived, Request.QueryString.ToString());

            var response = new ContentsDto
            {
                Total = result.Total,
                Items = result.Take(200).Select(ContentDto.FromContent).ToArray()
            };

            Response.Headers["Surrogate-Key"] = string.Join(" ", response.Items.Select(x => x.Id));

            return(Ok(response));
        }
Esempio n. 2
0
        public async Task Should_upsert_content_with_custom_id()
        {
            var(id, data, query) = CreateTestData(true);

            A.CallTo(() => contentQuery.QueryAsync(requestContext, A <string> ._, A <Q> .That.Matches(x => x.JsonQuery == query)))
            .Returns(ResultList.CreateFrom(1, CreateContent(id)));

            var command = new BulkUpdateContents
            {
                Jobs = new[]
                {
                    new BulkUpdateJob
                    {
                        Type  = BulkUpdateType.Upsert,
                        Data  = data,
                        Query = query
                    }
                },
                SchemaId = schemaId
            };

            var context = new CommandContext(command, commandBus);

            await sut.HandleAsync(context);

            var result = context.Result <BulkUpdateResult>();

            Assert.Single(result);
            Assert.Equal(1, result.Count(x => x.ContentId != default && x.Exception == null));

            A.CallTo(() => commandBus.PublishAsync(
                         A <UpsertContent> .That.Matches(x => x.Data == data && x.ContentId == id)))
            .MustHaveHappenedOnceExactly();
        }
Esempio n. 3
0
        public async Task Should_add_referenced_id_as_dependency()
        {
            var ref1_1 = CreateRefContent(Guid.NewGuid(), "ref1_1", 13);
            var ref1_2 = CreateRefContent(Guid.NewGuid(), "ref1_2", 17);
            var ref2_1 = CreateRefContent(Guid.NewGuid(), "ref2_1", 23);
            var ref2_2 = CreateRefContent(Guid.NewGuid(), "ref2_2", 29);

            var source = new IContentEntity[]
            {
                CreateContent(new[] { ref1_1.Id }, new[] { ref2_1.Id }),
                CreateContent(new[] { ref1_2.Id }, new[] { ref2_2.Id })
            };

            A.CallTo(() => contentQuery.QueryAsync(A <Context> .Ignored, A <IReadOnlyList <Guid> > .That.Matches(x => x.Count == 4)))
            .Returns(ResultList.CreateFrom(4, ref1_1, ref1_2, ref2_1, ref2_2));

            var enriched = await sut.EnrichAsync(source, requestContext);

            var enriched1 = enriched.ElementAt(0);
            var enriched2 = enriched.ElementAt(1);

            Assert.Contains(refSchemaId1.Id.ToString(), enriched1.CacheDependencies);
            Assert.Contains(refSchemaId2.Id.ToString(), enriched1.CacheDependencies);

            Assert.Contains(refSchemaId1.Id.ToString(), enriched2.CacheDependencies);
            Assert.Contains(refSchemaId2.Id.ToString(), enriched2.CacheDependencies);
        }
Esempio n. 4
0
        public async Task <IResultList <IContentEntity> > QueryContentsAsync(string schemaIdOrName, string query)
        {
            var result = await contentQuery.QueryAsync(context.WithSchemaName(schemaIdOrName), query);

            foreach (var content in result)
            {
                cachedContents[content.Id] = content;
            }

            return(result);
        }
Esempio n. 5
0
        public virtual async Task <IResultList <IContentEntity> > QueryContentsAsync(string schemaIdOrName, string query)
        {
            var result = await contentQuery.QueryAsync(context, schemaIdOrName, Q.Empty.WithODataQuery(query));

            foreach (var content in result)
            {
                cachedContents[content.Id] = content;
            }

            return(result);
        }
Esempio n. 6
0
        public async Task <IResultList <IContentEntity> > QueryContentsAsync(string schemaIdOrName, string query)
        {
            var result = await contentQuery.QueryAsync(app, schemaIdOrName, user, false, query);

            foreach (var content in result.Contents)
            {
                cachedContents[content.Id] = content;
            }

            return(result.Contents);
        }
Esempio n. 7
0
        public async Task <IActionResult> GetAllContents(string app, [FromQuery] string ids)
        {
            var contents = await contentQuery.QueryAsync(Context, Q.Empty.WithIds(ids).Ids);

            var response = Deferred.AsyncResponse(() =>
            {
                return(ContentsDto.FromContentsAsync(contents, Context, this, null, contentWorkflow));
            });

            return(Ok(response));
        }
Esempio n. 8
0
        public async Task Should_not_invoke_context_query_if_no_id_found()
        {
            var ctx = ContextWithPermissions(schemaId1, schemaId2);

            A.CallTo(() => contentIndex.SearchAsync(ctx.App, A <TextQuery> .That.Matches(x => x.Text == "query~"), ctx.Scope()))
            .Returns(new List <DomainId>());

            var result = await sut.SearchAsync("query", ctx, default);

            Assert.Empty(result);

            A.CallTo(() => contentQuery.QueryAsync(ctx, A <Q> ._, A <CancellationToken> ._))
            .MustNotHaveHappened();
        }
Esempio n. 9
0
        public async Task Should_enrich_with_reference_data()
        {
            var ref1_1 = CreateRefContent(Guid.NewGuid(), "ref1_1", 13);
            var ref1_2 = CreateRefContent(Guid.NewGuid(), "ref1_2", 17);
            var ref2_1 = CreateRefContent(Guid.NewGuid(), "ref2_1", 23);
            var ref2_2 = CreateRefContent(Guid.NewGuid(), "ref2_2", 29);

            var source = new IContentEntity[]
            {
                CreateContent(new Guid[] { ref1_1.Id }, new Guid[] { ref2_1.Id }),
                CreateContent(new Guid[] { ref1_2.Id }, new Guid[] { ref2_2.Id })
            };

            A.CallTo(() => contentQuery.QueryAsync(A <Context> .Ignored, A <IReadOnlyList <Guid> > .That.Matches(x => x.Count == 4)))
            .Returns(ResultList.CreateFrom(4, ref1_1, ref1_2, ref2_1, ref2_2));

            var enriched = await sut.EnrichAsync(source, requestContext);

            Assert.Equal(
                new NamedContentData()
                .AddField("ref1",
                          new ContentFieldData()
                          .AddJsonValue("iv",
                                        JsonValue.Object()
                                        .Add("en", "ref1_1, 13")
                                        .Add("de", "ref1_1, 13")))
                .AddField("ref2",
                          new ContentFieldData()
                          .AddJsonValue("iv",
                                        JsonValue.Object()
                                        .Add("en", "ref2_1, 23")
                                        .Add("de", "ref2_1, 23"))),
                enriched.ElementAt(0).ReferenceData);

            Assert.Equal(
                new NamedContentData()
                .AddField("ref1",
                          new ContentFieldData()
                          .AddJsonValue("iv",
                                        JsonValue.Object()
                                        .Add("en", "ref1_2, 17")
                                        .Add("de", "ref1_2, 17")))
                .AddField("ref2",
                          new ContentFieldData()
                          .AddJsonValue("iv",
                                        JsonValue.Object()
                                        .Add("en", "ref2_2, 29")
                                        .Add("de", "ref2_2, 29"))),
                enriched.ElementAt(1).ReferenceData);
        }
Esempio n. 10
0
        public async Task Should_not_invoke_context_query_if_no_id_found()
        {
            var ctx = ContextWithPermissions(schemaId1, schemaId2);

            A.CallTo(() => contentIndex.SearchAsync("query~", ctx.App, A <SearchFilter> ._, ctx.Scope()))
            .Returns(new List <Guid>());

            var result = await sut.SearchAsync("query", ctx);

            Assert.Empty(result);

            A.CallTo(() => contentQuery.QueryAsync(ctx, A <IReadOnlyList <Guid> > ._))
            .MustNotHaveHappened();
        }
Esempio n. 11
0
        private (ScriptVars, IContentEntity[]) SetupReferenceVars(int count)
        {
            var references   = Enumerable.Range(0, count).Select((x, i) => CreateReference(i + 1)).ToArray();
            var referenceIds = references.Select(x => x.Id);

            var user = new ClaimsPrincipal();

            var data =
                new ContentData()
                .AddField("references",
                          new ContentFieldData()
                          .AddInvariant(JsonValue.Array(referenceIds)));

            A.CallTo(() => contentQuery.QueryAsync(
                         A <Context> .That.Matches(x => x.App.Id == appId.Id && x.User == user), A <Q> .That.HasIds(referenceIds), A <CancellationToken> ._))
            .Returns(ResultList.CreateFrom(2, references));

            var vars = new ScriptVars
            {
                ["appId"]   = appId.Id,
                ["data"]    = data,
                ["dataOld"] = null,
                ["user"]    = user
            };

            return(vars, references);
        }
Esempio n. 12
0
        public async Task <IActionResult> GetAllContents(string app, [FromQuery] string ids)
        {
            var context  = Context();
            var contents = await contentQuery.QueryAsync(context, Q.Empty.WithIds(ids).Ids);

            var response = await ContentsDto.FromContentsAsync(contents, context, this, null, contentWorkflow);

            if (controllerOptions.Value.EnableSurrogateKeys && response.Items.Length <= controllerOptions.Value.MaxItemsForSurrogateKeys)
            {
                Response.Headers["Surrogate-Key"] = response.ToSurrogateKeys();
            }

            Response.Headers[HeaderNames.ETag] = response.ToEtag();

            return(Ok(response));
        }
Esempio n. 13
0
        public async Task <SearchResults> SearchAsync(string query, Context context)
        {
            var result = new SearchResults();

            var searchFilter = await CreateSearchFilterAsync(context);

            if (searchFilter == null)
            {
                return(result);
            }

            var ids = await contentTextIndexer.SearchAsync($"{query}~", context.App, searchFilter, context.Scope());

            if (ids == null || ids.Count == 0)
            {
                return(result);
            }

            var appId = context.App.NamedId();

            var contents = await contentQuery.QueryAsync(context, ids);

            foreach (var content in contents)
            {
                var url = urlGenerator.ContentUI(appId, content.SchemaId, content.Id);

                var name = FormatName(content, context.App.LanguagesConfig.Master);

                result.Add(name, SearchResultType.Content, url, content.SchemaDisplayName);
            }

            return(result);
        }
Esempio n. 14
0
        private static async Task <IContentEntity?> ResolveContentAsync(IAppProvider appProvider, IContentQueryService contentQuery, DomainId appId, FluidValue id)
        {
            var app = await appProvider.GetAppAsync(appId);

            if (app == null)
            {
                return(null);
            }

            var domainId  = DomainId.Create(id.ToStringValue());
            var domainIds = new List <DomainId> {
                domainId
            };

            var requestContext =
                Context.Admin(app).Clone(b => b
                                         .WithUnpublished()
                                         .WithoutTotal());

            var contents = await contentQuery.QueryAsync(requestContext, Q.Empty.WithIds(domainIds));

            var content = contents.FirstOrDefault();

            return(content);
        }
Esempio n. 15
0
        private async Task <DomainId[]> FindIdAsync(BulkTask task)
        {
            var id = task.CommandJob.Id;

            if (id != null)
            {
                return(new[] { id.Value });
            }

            if (task.CommandJob.Query != null)
            {
                task.CommandJob.Query.Take = task.CommandJob.ExpectedCount;

                var existing = await contentQuery.QueryAsync(contextProvider.Context, task.Schema, Q.Empty.WithJsonQuery(task.CommandJob.Query));

                if (existing.Total > task.CommandJob.ExpectedCount)
                {
                    throw new DomainException(T.Get("contents.bulkInsertQueryNotUnique"));
                }

                if (existing.Count == 0 && task.CommandJob.Type == BulkUpdateContentType.Upsert)
                {
                    return(new[] { DomainId.NewGuid() });
                }

                return(existing.Select(x => x.Id).ToArray());
            }

            if (task.CommandJob.Type == BulkUpdateContentType.Create || task.CommandJob.Type == BulkUpdateContentType.Upsert)
            {
                return(new[] { DomainId.NewGuid() });
            }

            return(Array.Empty <DomainId>());
        }
Esempio n. 16
0
        public async Task <IActionResult> GetAllContents(string app, [FromQuery] string ids)
        {
            var contents = await contentQuery.QueryAsync(Context, Q.Empty.WithIds(ids).Ids);

            var response = Deferred.AsyncResponse(() =>
            {
                return(ContentsDto.FromContentsAsync(contents, Context, this, null, contentWorkflow));
            });

            if (ShouldProvideSurrogateKeys(contents))
            {
                Response.Headers["Surrogate-Key"] = contents.ToSurrogateKeys();
            }

            Response.Headers[HeaderNames.ETag] = contents.ToEtag();

            return(Ok(response));
        }
        public async Task Should_throw_exception_when_query_resolves_multiple_contents()
        {
            var requestContext = SetupContext(Permissions.AppContentsUpdateOwn);

            var(id, _, query) = CreateTestData(true);

            A.CallTo(() => contentQuery.QueryAsync(requestContext, A <string> ._, A <Q> .That.Matches(x => x.JsonQuery == query)))
            .Returns(ResultList.CreateFrom(2, CreateContent(id), CreateContent(id)));

            var command = BulkCommand(BulkUpdateType.ChangeStatus, query);

            var result = await PublishAsync(command);

            Assert.Single(result, x => x.JobIndex == 0 && x.ContentId == null && x.Exception is DomainException);

            A.CallTo(() => commandBus.PublishAsync(A <ICommand> ._))
            .MustNotHaveHappened();
        }
Esempio n. 18
0
        public async Task <IActionResult> GetContents(string app, string name, [FromQuery] bool archived = false, [FromQuery] string ids = null)
        {
            HashSet <Guid> idsList = null;

            if (!string.IsNullOrWhiteSpace(ids))
            {
                idsList = new HashSet <Guid>();

                foreach (var id in ids.Split(','))
                {
                    if (Guid.TryParse(id, out var guid))
                    {
                        idsList.Add(guid);
                    }
                }
            }

            var isFrontendClient = User.IsFrontendClient();

            var result =
                idsList?.Count > 0 ?
                await contentQuery.QueryAsync(App, name, User, archived, idsList) :
                await contentQuery.QueryAsync(App, name, User, archived, Request.QueryString.ToString());

            var response = new ContentsDto
            {
                Total = result.Contents.Total,
                Items = result.Contents.Take(200).Select(item =>
                {
                    var itemModel = SimpleMapper.Map(item, new ContentDto());

                    if (item.Data != null)
                    {
                        itemModel.Data = item.Data.ToApiModel(result.Schema.SchemaDef, App.LanguagesConfig, !isFrontendClient);
                    }

                    return(itemModel);
                }).ToArray()
            };

            Response.Headers["Surrogate-Key"] = string.Join(" ", response.Items.Select(x => x.Id));

            return(Ok(response));
        }
Esempio n. 19
0
        public async Task Should_resolve_references_in_loop()
        {
            var referenceId1 = DomainId.NewGuid();
            var reference1   = CreateReference(referenceId1, 1);
            var referenceId2 = DomainId.NewGuid();
            var reference2   = CreateReference(referenceId1, 2);

            var @event = new EnrichedContentEvent
            {
                Data =
                    new NamedContentData()
                    .AddField("references",
                              new ContentFieldData()
                              .AddJsonValue(JsonValue.Array(referenceId1, referenceId2))),
                AppId = appId
            };

            A.CallTo(() => contentQuery.QueryAsync(A <Context> ._, A <IReadOnlyList <DomainId> > .That.Contains(referenceId1)))
            .Returns(ResultList.CreateFrom(1, reference1));

            A.CallTo(() => contentQuery.QueryAsync(A <Context> ._, A <IReadOnlyList <DomainId> > .That.Contains(referenceId2)))
            .Returns(ResultList.CreateFrom(1, reference2));

            var vars = new TemplateVars
            {
                ["event"] = @event
            };

            var template = @"
{% for id in event.data.references.iv %}
    {% reference 'ref', id %}
    Text: {{ ref.data.field1.iv }} {{ ref.data.field2.iv }}
{% endfor %}
";

            var expected = @"
    Text: Hello 1 World 1
    Text: Hello 2 World 2
";

            var result = await sut.RenderAsync(template, vars);

            Assert.Equal(expected, result);
        }
Esempio n. 20
0
        public async Task <IActionResult> GetAllContents(string app, [FromQuery] string ids, [FromQuery] string status = null)
        {
            var context = Context().WithFrontendStatus(status);

            var result = await contentQuery.QueryAsync(context, Q.Empty.WithIds(ids).Ids);

            var response = new ContentsDto
            {
                Total = result.Count,
                Items = result.Take(200).Select(x => ContentDto.FromContent(x, context)).ToArray()
            };

            if (controllerOptions.Value.EnableSurrogateKeys && response.Items.Length <= controllerOptions.Value.MaxItemsForSurrogateKeys)
            {
                Response.Headers["Surrogate-Key"] = response.Items.ToSurrogateKeys();
            }

            Response.Headers[HeaderNames.ETag] = response.Items.ToManyEtag();

            return(Ok(response));
        }
Esempio n. 21
0
        public async Task Should_resolve_reference()
        {
            var referenceId1 = DomainId.NewGuid();
            var reference1 = CreateReference(referenceId1, 1);

            var user = new ClaimsPrincipal();

            var data =
                new ContentData()
                    .AddField("references",
                        new ContentFieldData()
                            .AddInvariant(JsonValue.Array(referenceId1)));

            A.CallTo(() => contentQuery.QueryAsync(
                    A<Context>.That.Matches(x => x.App.Id == appId.Id && x.User == user), A<Q>.That.HasIds(referenceId1), A<CancellationToken>._))
                .Returns(ResultList.CreateFrom(1, reference1));

            var vars = new ScriptVars
            {
                ["appId"] = appId.Id,
                ["data"] = data,
                ["dataOld"] = null,
                ["user"] = user
            };

            var expected = @"
                Text: Hello 1 World 1
            ";

            var script = @"
                getReference(data.references.iv[0], function (references) {
                    var result1 = `Text: ${references[0].data.field1.iv} ${references[0].data.field2.iv}`;

                    complete(`${result1}`);
                })";

            var result = (await sut.ExecuteAsync(vars, script)).ToString();

            Assert.Equal(Cleanup(expected), Cleanup(result));
        }
Esempio n. 22
0
        public async Task <IActionResult> GetContents(string app, string name, [FromQuery] bool archived = false, [FromQuery] string ids = null)
        {
            HashSet <Guid> idsList = null;

            if (!string.IsNullOrWhiteSpace(ids))
            {
                idsList = new HashSet <Guid>();

                foreach (var id in ids.Split(','))
                {
                    if (Guid.TryParse(id, out var guid))
                    {
                        idsList.Add(guid);
                    }
                }
            }

            var context = Context().WithSchemaName(name).WithArchived(archived);

            var result =
                idsList?.Count > 0 ?
                await contentQuery.QueryAsync(context, idsList) :
                await contentQuery.QueryAsync(context, Request.QueryString.ToString());

            var response = new ContentsDto
            {
                Total = result.Total,
                Items = result.Take(200).Select(x => ContentDto.FromContent(x, context)).ToArray()
            };

            var options = controllerOptions.Value;

            if (options.EnableSurrogateKeys && response.Items.Length <= options.MaxItemsForSurrogateKeys)
            {
                Response.Headers["Surrogate-Key"] = string.Join(" ", response.Items.Select(x => x.Id));
            }

            return(Ok(response));
        }
Esempio n. 23
0
        public virtual async Task <IResultList <IEnrichedContentEntity> > QueryContentsAsync(string schemaIdOrName, Q q)
        {
            IResultList <IEnrichedContentEntity> contents;

            await maxRequests.WaitAsync();

            try
            {
                contents = await contentQuery.QueryAsync(Context, schemaIdOrName, q);
            }
            finally
            {
                maxRequests.Release();
            }

            foreach (var content in contents)
            {
                cachedContents[content.Id] = content;
            }

            return(contents);
        }
Esempio n. 24
0
        public async Task Should_throw_exception_if_query_resolves_multiple_contents()
        {
            var requestContext = SetupContext(Permissions.AppContentsUpdateOwn);

            var(id, _, query) = CreateTestData(true);

            A.CallTo(() => contentQuery.QueryAsync(
                         A <Context> .That.Matches(x =>
                                                   x.ShouldSkipCleanup() &&
                                                   x.ShouldSkipContentEnrichment() &&
                                                   x.ShouldSkipTotal()),
                         schemaId.Name, A <Q> .That.Matches(x => x.JsonQuery == query), A <CancellationToken> ._))
            .Returns(ResultList.CreateFrom(2, CreateContent(id), CreateContent(id)));

            var command = BulkCommand(BulkUpdateContentType.ChangeStatus, query);

            var result = await PublishAsync(command);

            Assert.Single(result);
            Assert.Single(result, x => x.JobIndex == 0 && x.Id == null && x.Exception is DomainException);

            A.CallTo(() => commandBus.PublishAsync(A <ICommand> ._))
            .MustNotHaveHappened();
        }
Esempio n. 25
0
        public async Task <IActionResult> GetAllContents(string app, AllContentsByGetDto query)
        {
            var contents = await contentQuery.QueryAsync(Context, query?.ToQuery() ?? Q.Empty, HttpContext.RequestAborted);

            var response = Deferred.AsyncResponse(() =>
            {
                return(ContentsDto.FromContentsAsync(contents, Resources, null, contentWorkflow));
            });

            return(Ok(response));
        }
Esempio n. 26
0
        private async Task <Guid?> FindIdAsync(Context context, string schema, BulkUpdateJob job)
        {
            var id = job.Id;

            if (id == null && job.Query != null)
            {
                job.Query.Take = 1;

                var existing = await contentQuery.QueryAsync(context, schema, Q.Empty.WithJsonQuery(job.Query));

                if (existing.Total > 1)
                {
                    throw new DomainException("More than one content matches to the query.");
                }

                id = existing.FirstOrDefault()?.Id;
            }

            return(id);
        }
        private async Task <DomainId?> FindIdAsync(Context context, string schema, BulkUpdateJob job)
        {
            var id = job.Id;

            if (id == null && job.Query != null)
            {
                job.Query.Take = 1;

                var existing = await contentQuery.QueryAsync(context, schema, Q.Empty.WithJsonQuery(job.Query));

                if (existing.Total > 1)
                {
                    throw new DomainException(T.Get("contents.bulkInsertQueryNotUnique"));
                }

                id = existing.FirstOrDefault()?.Id;
            }

            return(id);
        }
Esempio n. 28
0
        public async Task <IActionResult> GetContents(string app, string name, [FromQuery] bool archived = false, [FromQuery] string ids = null)
        {
            var context = Context().WithArchived(archived);

            var result = await contentQuery.QueryAsync(context, name, Q.Empty.WithIds(ids).WithODataQuery(Request.QueryString.ToString()));

            var response = new ContentsDto
            {
                Total = result.Total,
                Items = result.Take(200).Select(x => ContentDto.FromContent(x, context)).ToArray()
            };

            if (controllerOptions.Value.EnableSurrogateKeys && response.Items.Length <= controllerOptions.Value.MaxItemsForSurrogateKeys)
            {
                Response.Headers["Surrogate-Key"] = response.Items.ToSurrogateKeys();
            }

            Response.Headers["ETag"] = response.Items.ToManyEtag(response.Total);

            return(Ok(response));
        }
Esempio n. 29
0
        public async Task <IActionResult> GetContents(string app, string name, [FromQuery] bool archived = false, [FromQuery] string ids = null)
        {
            var context = Context().WithArchived(archived).WithSchemaName(name);

            var result = await contentQuery.QueryAsync(context, Query.Empty.WithIds(ids).WithODataQuery(Request.QueryString.ToString()));

            var response = new ContentsDto
            {
                Total = result.Total,
                Items = result.Take(200).Select(x => ContentDto.FromContent(x, context.Base)).ToArray()
            };

            var options = controllerOptions.Value;

            if (options.EnableSurrogateKeys && response.Items.Length <= options.MaxItemsForSurrogateKeys)
            {
                Response.Headers["Surrogate-Key"] = string.Join(" ", response.Items.Select(x => x.Id));
            }

            return(Ok(response));
        }
            public override async ValueTask <Completion> WriteToAsync(TextWriter writer, TextEncoder encoder, TemplateContext context, FilterArgument[] arguments)
            {
                if (arguments.Length == 2 && context.GetValue("event")?.ToObjectValue() is EnrichedEvent enrichedEvent)
                {
                    var app = await appProvider.GetAppAsync(enrichedEvent.AppId.Id);

                    if (app == null)
                    {
                        return(Completion.Normal);
                    }

                    var appContext =
                        Context.Admin()
                        .WithoutContentEnrichment()
                        .WithoutCleanup()
                        .WithUnpublished();

                    appContext.App = app;

                    var id = (await arguments[1].Expression.EvaluateAsync(context)).ToStringValue();

                    if (Guid.TryParse(id, out var guid))
                    {
                        var references = await contentQueryService.QueryAsync(appContext, new List <Guid> {
                            guid
                        });

                        var reference = references.FirstOrDefault();

                        if (reference != null)
                        {
                            var name = (await arguments[0].Expression.EvaluateAsync(context)).ToStringValue();

                            context.SetValue(name, reference);
                        }
                    }
                }

                return(Completion.Normal);
            }