private async Task <NamedId <Guid> > GetSchemaIdAsync(CommandContext context)
        {
            NamedId <Guid> appId = null;

            if (context.Command is IAppCommand appCommand)
            {
                appId = appCommand.AppId;
            }

            if (appId == null)
            {
                var appFeature = actionContextAccessor.ActionContext.HttpContext.Features.Get <IAppFeature>();

                if (appFeature != null && appFeature.App != null)
                {
                    appId = NamedId.Of(appFeature.App.Id, appFeature.App.Name);
                }
            }

            if (appId != null)
            {
                var routeValues = actionContextAccessor.ActionContext.RouteData.Values;

                if (routeValues.ContainsKey("name"))
                {
                    var schemaName = routeValues["name"].ToString();

                    ISchemaEntity schema;

                    if (Guid.TryParse(schemaName, out var id))
                    {
                        schema = await appProvider.GetSchemaAsync(appId.Id, id);
                    }
                    else
                    {
                        schema = await appProvider.GetSchemaAsync(appId.Id, schemaName);
                    }

                    if (schema == null)
                    {
                        throw new DomainObjectNotFoundException(schemaName, typeof(ISchemaEntity));
                    }

                    return(NamedId.Of(schema.Id, schema.Name));
                }
            }

            return(null);
        }
示例#2
0
        private Task <ISchemaEntity?> GetSchemaAsync(DomainId appId, string schemaIdOrName, ClaimsPrincipal user)
        {
            var canCache = !user.IsInClient(DefaultClients.Frontend);

            if (Guid.TryParse(schemaIdOrName, out var guid))
            {
                var schemaId = DomainId.Create(guid);

                return(appProvider.GetSchemaAsync(appId, schemaId, canCache));
            }
            else
            {
                return(appProvider.GetSchemaAsync(appId, schemaIdOrName, canCache));
            }
        }
示例#3
0
        public async Task Should_throw_exception_if_app_not_found()
        {
            SetupApp(out var appId, out _);
            SetupSchema(appId, out _, out _);

            A.CallTo(() => appProvider.GetSchemaAsync(appId, "other-schema"))
            .Returns(Task.FromResult <ISchemaEntity>(null));

            actionContext.RouteData.Values["name"] = "other-schema";

            var command = new CreateContent();
            var context = new CommandContext(command, commandBus);

            await Assert.ThrowsAsync <DomainObjectNotFoundException>(() => sut.HandleAsync(context));
        }
示例#4
0
        public DefaultWorkflowsValidatorTests()
        {
            var schema = A.Fake <ISchemaEntity>();

            A.CallTo(() => schema.Id).Returns(schemaId.Id);
            A.CallTo(() => schema.SchemaDef).Returns(new Schema(schemaId.Name));

            A.CallTo(() => appProvider.GetSchemaAsync(appId.Id, A <Guid> .Ignored, false))
            .Returns(Task.FromResult <ISchemaEntity>(null));

            A.CallTo(() => appProvider.GetSchemaAsync(appId.Id, schemaId.Id, false))
            .Returns(schema);

            sut = new DefaultWorkflowsValidator(appProvider);
        }
示例#5
0
        private async Task <IDictionary <DomainId, ISchemaEntity> > GetSchemasAsync(DomainId appId, ISchemaEntity?schema, List <MongoContentEntity> contentItems, bool canCache)
        {
            var schemas = new Dictionary <DomainId, ISchemaEntity>();

            if (schema != null)
            {
                schemas[schema.Id] = schema;
            }

            var schemaIds = contentItems.Select(x => x.IndexedSchemaId).Distinct();

            foreach (var schemaId in schemaIds)
            {
                if (!schemas.ContainsKey(schemaId))
                {
                    var found = await appProvider.GetSchemaAsync(appId, schemaId, false, canCache);

                    if (found != null)
                    {
                        schemas[schemaId] = found;
                    }
                }
            }

            return(schemas);
        }
        public RuleCommandMiddlewareTests()
        {
            A.CallTo(() => appProvider.GetSchemaAsync(A <Guid> .Ignored, A <Guid> .Ignored))
            .Returns(A.Fake <ISchemaEntity>());

            sut = new RuleCommandMiddleware(Handler, appProvider);
        }
        public async Task Should_add_error_if_schemas_ids_are_not_valid()
        {
            A.CallTo(() => appProvider.GetSchemaAsync(appId, A <Guid> .Ignored, false))
            .Returns(Task.FromResult <ISchemaEntity>(null));

            var trigger = new ContentChangedTrigger
            {
                Schemas = ImmutableList.Create(
                    new ContentChangedTriggerSchema()
                    )
            };

            var errors = await RuleTriggerValidator.ValidateAsync(appId, trigger, appProvider);

            Assert.NotEmpty(errors);
        }
示例#8
0
        public async Task <List <(IContentEntity Content, ISchemaEntity Schema)> > QueryAsync(IAppEntity app, HashSet <Guid> ids, Status[] status, bool useDraft)
        {
            var find = Collection.Find(FilterFactory.IdsByApp(app.Id, ids, status));

            var contentItems = await find.WithoutDraft(useDraft).ToListAsync();

            var schemaIds = contentItems.Select(x => x.IndexedSchemaId).ToList();
            var schemas   = await Task.WhenAll(schemaIds.Select(x => appProvider.GetSchemaAsync(app.Id, x)));

            var result = new List <(IContentEntity Content, ISchemaEntity Schema)>();

            foreach (var entity in contentItems)
            {
                var schema = schemas.FirstOrDefault(x => x.Id == entity.IndexedSchemaId);

                if (schema != null)
                {
                    entity.ParseData(schema.SchemaDef, serializer);

                    result.Add((entity, schema));
                }
            }

            return(result);
        }
示例#9
0
        public async IAsyncEnumerable <IContentEntity> StreamAll(DomainId appId, HashSet <DomainId>?schemaIds)
        {
            var find =
                schemaIds != null?
                Collection.Find(x => x.IndexedAppId == appId && schemaIds.Contains(x.IndexedSchemaId) && !x.IsDeleted) :
                    Collection.Find(x => x.IndexedAppId == appId && !x.IsDeleted);

            using (var cursor = await find.ToCursorAsync())
            {
                while (await cursor.MoveNextAsync())
                {
                    foreach (var entity in cursor.Current)
                    {
                        var schema = await appProvider.GetSchemaAsync(appId, entity.SchemaId.Id, false);

                        if (schema != null)
                        {
                            entity.ParseData(schema.SchemaDef, converter);

                            yield return(entity);
                        }
                    }
                }
            }
        }
        protected override async Task <(string Description, Command Data)> CreateJobAsync(EnrichedEvent @event, CreateContentAction action)
        {
            var ruleJob = new Command
            {
                AppId = @event.AppId,
            };

            var schema = await appProvider.GetSchemaAsync(@event.AppId.Id, action.Schema, true);

            if (schema == null)
            {
                throw new InvalidOperationException($"Cannot find schema '{action.Schema}'");
            }

            ruleJob.SchemaId = schema.NamedId();

            var json = await FormatAsync(action.Data, @event);

            ruleJob.Data = jsonSerializer.Deserialize <NamedContentData>(json);

            if (!string.IsNullOrEmpty(action.Client))
            {
                ruleJob.Actor = new RefToken(RefTokenType.Client, action.Client);
            }
            else if (@event is EnrichedUserEventBase userEvent)
            {
                ruleJob.Actor = userEvent.Actor;
            }

            ruleJob.Publish = action.Publish;

            return(Description, ruleJob);
        }
示例#11
0
        public async Task <IReadOnlyList <string> > ValidateAsync(DomainId appId, Workflows workflows)
        {
            Guard.NotNull(workflows);

            var errors = new List <string>();

            if (workflows.Values.Count(x => x.SchemaIds.Count == 0) > 1)
            {
                errors.Add(T.Get("workflows.overlap"));
            }

            var uniqueSchemaIds = workflows.Values.SelectMany(x => x.SchemaIds).Distinct().ToList();

            foreach (var schemaId in uniqueSchemaIds)
            {
                if (workflows.Values.Count(x => x.SchemaIds.Contains(schemaId)) > 1)
                {
                    var schema = await appProvider.GetSchemaAsync(appId, schemaId);

                    if (schema != null)
                    {
                        errors.Add(T.Get("workflows.schemaOverlap", new { schema = schema.SchemaDef.Name }));
                    }
                }
            }

            return(errors);
        }
示例#12
0
        public async Task <IReadOnlyList <string> > ValidateAsync(Guid appId, Workflows workflows)
        {
            Guard.NotNull(workflows, nameof(workflows));

            var errors = new List <string>();

            if (workflows.Values.Count(x => x.SchemaIds.Count == 0) > 1)
            {
                errors.Add("Multiple workflows cover all schemas.");
            }

            var uniqueSchemaIds = workflows.Values.SelectMany(x => x.SchemaIds).Distinct().ToList();

            foreach (var schemaId in uniqueSchemaIds)
            {
                if (workflows.Values.Count(x => x.SchemaIds.Contains(schemaId)) > 1)
                {
                    var schema = await appProvider.GetSchemaAsync(appId, schemaId);

                    if (schema != null)
                    {
                        errors.Add($"The schema `{schema.SchemaDef.Name}` is covered by multiple workflows.");
                    }
                }
            }

            return(errors);
        }
示例#13
0
        public async Task <List <(IContentEntity Content, ISchemaEntity Schema)> > QueryAsync(IAppEntity app, HashSet <Guid> ids, Status[] status = null)
        {
            var find =
                status != null && status.Length > 0 ?
                Collection.Find(x => x.IndexedAppId == app.Id && ids.Contains(x.Id) && x.IsDeleted != true && status.Contains(x.Status)) :
                Collection.Find(x => x.IndexedAppId == app.Id && ids.Contains(x.Id));

            var contentItems = await find.Not(x => x.DataText).ToListAsync();

            var schemaIds = contentItems.Select(x => x.IndexedSchemaId).ToList();
            var schemas   = await Task.WhenAll(schemaIds.Select(x => appProvider.GetSchemaAsync(app.Id, x)));

            var result = new List <(IContentEntity Content, ISchemaEntity Schema)>();

            foreach (var entity in contentItems)
            {
                var schema = schemas.FirstOrDefault(x => x.Id == entity.IndexedSchemaId);

                if (schema != null)
                {
                    entity.ParseData(schema.SchemaDef, Serializer);

                    result.Add((entity, schema));
                }
            }

            return(result);
        }
示例#14
0
 public async Task <IReadOnlyList <Guid> > QueryIdsAsync(Guid appId, Guid schemaId, FilterNode filterNode)
 {
     using (Profiler.TraceMethod <MongoContentRepository>())
     {
         return(await contents.QueryIdsAsync(await appProvider.GetSchemaAsync(appId, schemaId), filterNode));
     }
 }
示例#15
0
        public async Task <IReadOnlyList <(DomainId SchemaId, DomainId Id, Status Status)> > QueryIdsAsync(DomainId appId, DomainId schemaId, FilterNode <ClrValue> filterNode)
        {
            Guard.NotNull(filterNode, nameof(filterNode));

            try
            {
                var schema = await appProvider.GetSchemaAsync(appId, schemaId, false);

                if (schema == null)
                {
                    return(new List <(DomainId SchemaId, DomainId Id, Status Status)>());
                }

                var filter = BuildFilter(appId, schemaId, filterNode.AdjustToModel(appId));

                var contentItems = await Collection.FindStatusAsync(filter);

                return(contentItems.Select(x => (x.IndexedSchemaId, x.Id, x.Status)).ToList());
            }
            catch (MongoCommandException ex) when(ex.Code == 96)
            {
                throw new DomainException(T.Get("common.resultTooLarge"));
            }
            catch (MongoQueryException ex) when(ex.Message.Contains("17406"))
            {
                throw new DomainException(T.Get("common.resultTooLarge"));
            }
        }
        public async Task Should_return_schema_from_id_if_string_is_guid()
        {
            A.CallTo(() => appProvider.GetSchemaAsync(appId, schemaId, false))
            .Returns(schema);

            var result = await sut.GetSchemaAsync(app, schemaId.ToString());

            Assert.Equal(schema, result);
        }
示例#17
0
        public SchemaGrainTests()
        {
            A.CallTo(() => appProvider.GetSchemaAsync(AppId, SchemaName))
            .Returns((ISchemaEntity)null);

            sut = new SchemaGrain(Store, A.Dummy <ISemanticLog>(), appProvider, registry);
            sut.OnActivateAsync(Id).Wait();
        }
示例#18
0
        public SchemaGrainTests()
        {
            A.CallTo(() => appProvider.GetSchemaAsync(AppId, SchemaName))
            .Returns((ISchemaEntity)null);

            sut = new SchemaGrain(Store, A.Dummy <ISemanticLog>(), appProvider, TestUtils.DefaultSerializer);
            sut.ActivateAsync(Id).Wait();
        }
示例#19
0
        public static Task <IEnumerable <ValidationError> > ValidateAsync(DomainId appId, RuleTrigger trigger, IAppProvider appProvider)
        {
            Guard.NotNull(trigger, nameof(trigger));
            Guard.NotNull(appProvider, nameof(appProvider));

            var visitor = new RuleTriggerValidator(x => appProvider.GetSchemaAsync(appId, x));

            return(trigger.Accept(visitor));
        }
示例#20
0
        public static Task <IEnumerable <ValidationError> > ValidateAsync(Guid appId, RuleTrigger action, IAppProvider appProvider)
        {
            Guard.NotNull(action);
            Guard.NotNull(appProvider);

            var visitor = new RuleTriggerValidator(x => appProvider.GetSchemaAsync(appId, x));

            return(action.Accept(visitor));
        }
示例#21
0
        public RuleCommandMiddlewareTests()
        {
            A.CallTo(() => appProvider.GetSchemaAsync(A <string> .Ignored, A <Guid> .Ignored, false))
            .Returns(A.Fake <ISchemaEntity>());

            rule = new RuleDomainObject(ruleId, -1);

            sut = new RuleCommandMiddleware(Handler, appProvider);
        }
        public async Task Should_add_error_if_schema_id_is_not_defined()
        {
            var trigger = new ContentChangedTriggerV2
            {
                Schemas = ReadOnlyCollection.Create(new ContentChangedTriggerSchemaV2())
            };

            var errors = await RuleTriggerValidator.ValidateAsync(appId.Id, trigger, appProvider);

            errors.Should().BeEquivalentTo(
                new List <ValidationError>
            {
                new ValidationError("Schema id is required.", "Schemas")
            });

            A.CallTo(() => appProvider.GetSchemaAsync(appId.Id, A <DomainId> ._, false, false))
            .MustNotHaveHappened();
        }
示例#23
0
        public async Task Should_return_not_found_if_schema_name_is_null(string?schema)
        {
            actionContext.RouteData.Values["schema"] = schema;

            await sut.OnActionExecutionAsync(actionExecutingContext, next);

            AssertNotFound();

            A.CallTo(() => appProvider.GetSchemaAsync(appId.Id, A <DomainId> ._, true, httpContext.RequestAborted))
            .MustNotHaveHappened();
        }
示例#24
0
        public async Task Should_do_nothing_if_no_component_found()
        {
            var schema = Mocks.Schema(appId, schemaId);

            var components = await appProvider.GetComponentsAsync(schema);

            Assert.Empty(components);

            A.CallTo(() => appProvider.GetSchemaAsync(A <DomainId> ._, A <DomainId> ._, false, A <CancellationToken> ._))
            .MustNotHaveHappened();
        }
示例#25
0
        public SchemaGrainTests()
        {
            A.CallTo(() => appProvider.GetSchemaAsync(AppId, SchemaName))
            .Returns((ISchemaEntity)null);

            fieldId = new NamedId <long>(1, fieldName);

            sut = new SchemaGrain(Store, appProvider, registry);
            sut.OnActivateAsync(Id).Wait();
        }
示例#26
0
        public static Task CanCreate(CreateSchema command, IAppProvider appProvider)
        {
            Guard.NotNull(command, nameof(command));

            return(Validate.It(() => "Cannot create schema.", async error =>
            {
                if (!command.Name.IsSlug())
                {
                    error(new ValidationError("Name must be a valid slug.", nameof(command.Name)));
                }

                if (await appProvider.GetSchemaAsync(command.AppId.Id, command.Name) != null)
                {
                    error(new ValidationError($"A schema with name '{command.Name}' already exists", nameof(command.Name)));
                }

                if (command.Fields != null && command.Fields.Any())
                {
                    var index = 0;

                    foreach (var field in command.Fields)
                    {
                        var prefix = $"Fields.{index}";

                        if (!field.Partitioning.IsValidPartitioning())
                        {
                            error(new ValidationError("Partitioning is not valid.", $"{prefix}.{nameof(field.Partitioning)}"));
                        }

                        if (!field.Name.IsPropertyName())
                        {
                            error(new ValidationError("Name must be a valid property name.", $"{prefix}.{nameof(field.Name)}"));
                        }

                        if (field.Properties == null)
                        {
                            error(new ValidationError("Properties is required.", $"{prefix}.{nameof(field.Properties)}"));
                        }

                        var propertyErrors = FieldPropertiesValidator.Validate(field.Properties);

                        foreach (var propertyError in propertyErrors)
                        {
                            error(propertyError);
                        }
                    }

                    if (command.Fields.Select(x => x.Name).Distinct().Count() != command.Fields.Count)
                    {
                        error(new ValidationError("Fields cannot have duplicate names.", nameof(command.Fields)));
                    }
                }
            }));
        }
        public async Task <ISchemaEntity> GetSchemaOrThrowAsync(Context context, string schemaIdOrName)
        {
            ISchemaEntity?schema = null;

            if (Guid.TryParse(schemaIdOrName, out var id))
            {
                schema = await appProvider.GetSchemaAsync(context.App.Id, id);
            }

            if (schema == null)
            {
                schema = await appProvider.GetSchemaAsync(context.App.Id, schemaIdOrName);
            }

            if (schema == null)
            {
                throw new DomainObjectNotFoundException(schemaIdOrName, typeof(ISchemaEntity));
            }

            return(schema);
        }
示例#28
0
        public async Task<ISchemaEntity> GetSchemaAsync(QueryContext context)
        {
            ISchemaEntity schema = null;

            if (Guid.TryParse(context.SchemaIdOrName, out var id))
            {
                schema = await appProvider.GetSchemaAsync(context.App.Id, id);
            }

            if (schema == null)
            {
                schema = await appProvider.GetSchemaAsync(context.App.Id, context.SchemaIdOrName);
            }

            if (schema == null)
            {
                throw new DomainObjectNotFoundException(context.SchemaIdOrName, typeof(ISchemaEntity));
            }

            return schema;
        }
示例#29
0
        private async Task ForSchemaAsync(NamedId <Guid> appId, Guid schemaId, Func <IMongoCollection <MongoContentEntity>, ISchemaEntity, Task> action)
        {
            var collection = GetCollection(appId.Id);

            var schema = await appProvider.GetSchemaAsync(appId.Name, schemaId, true);

            if (schema == null)
            {
                return;
            }

            await action(collection, schema);
        }
        public async Task <ISchemaEntity> FindSchemaAsync(IAppEntity app, string schemaIdOrName)
        {
            Guard.NotNull(app, nameof(app));

            ISchemaEntity schema = null;

            if (Guid.TryParse(schemaIdOrName, out var id))
            {
                schema = await appProvider.GetSchemaAsync(app.Id, id);
            }

            if (schema == null)
            {
                schema = await appProvider.GetSchemaAsync(app.Id, schemaIdOrName);
            }

            if (schema == null)
            {
                throw new DomainObjectNotFoundException(schemaIdOrName, typeof(ISchemaEntity));
            }

            return(schema);
        }