Browse Source

API extended.

pull/104/head
Sebastian Stehle 8 years ago
parent
commit
cb5d127d9c
  1. 4
      src/Squidex.Domain.Apps.Write/Contents/ContentCommandMiddleware.cs
  2. 8
      src/Squidex.Domain.Apps.Write/Contents/ContentDataChangedResult.cs
  3. 43
      src/Squidex/Controllers/Api/Schemas/Models/ConfigureScriptsDto.cs
  4. 24
      src/Squidex/Controllers/Api/Schemas/SchemasController.cs
  5. 63
      src/Squidex/Controllers/ContentApi/ContentsController.cs
  6. 6
      src/Squidex/Controllers/ContentApi/Generator/SchemaSwaggerGenerator.cs
  7. 24
      src/Squidex/Controllers/ContentApi/Models/ContentDto.cs
  8. 4
      tests/Squidex.Domain.Apps.Write.Tests/Contents/ContentCommandHandlerTests.cs

4
src/Squidex.Domain.Apps.Write/Contents/ContentCommandMiddleware.cs

@ -92,7 +92,7 @@ namespace Squidex.Domain.Apps.Write.Contents
content.Update(command); content.Update(command);
context.Complete(new ContentChangedResult(content.Data, content.Version)); context.Complete(new ContentDataChangedResult(content.Data, content.Version));
}); });
} }
@ -109,7 +109,7 @@ namespace Squidex.Domain.Apps.Write.Contents
content.Patch(command); content.Patch(command);
context.Complete(new ContentChangedResult(content.Data, content.Version)); context.Complete(new ContentDataChangedResult(content.Data, content.Version));
}); });
} }

8
src/Squidex.Domain.Apps.Write/Contents/ContentChangedResult.cs → src/Squidex.Domain.Apps.Write/Contents/ContentDataChangedResult.cs

@ -11,14 +11,14 @@ using Squidex.Infrastructure.CQRS.Commands;
namespace Squidex.Domain.Apps.Write.Contents namespace Squidex.Domain.Apps.Write.Contents
{ {
public sealed class ContentChangedResult : EntitySavedResult public sealed class ContentDataChangedResult : EntitySavedResult
{ {
public NamedContentData Content { get; } public NamedContentData Data { get; }
public ContentChangedResult(NamedContentData content, long version) public ContentDataChangedResult(NamedContentData data, long version)
: base(version) : base(version)
{ {
Content = content; Data = data;
} }
} }
} }

43
src/Squidex/Controllers/Api/Schemas/Models/ConfigureScriptsDto.cs

@ -0,0 +1,43 @@
// ==========================================================================
// ConfigureScriptsDto.cs
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex Group
// All rights reserved.
// ==========================================================================
namespace Squidex.Controllers.Api.Schemas.Models
{
public sealed class ConfigureScriptsDto
{
/// <summary>
/// The script that is executed for each query when querying contents.
/// </summary>
public string ScriptQuery { get; set; }
/// <summary>
/// The script that is executed when creating a content.
/// </summary>
public string ScriptCreate { get; set; }
/// <summary>
/// The script that is executed when updating a content.
/// </summary>
public string ScriptUpdate { get; set; }
/// <summary>
/// The script that is executed when deleting a content.
/// </summary>
public string ScriptDelete { get; set; }
/// <summary>
/// The script that is executed when publishing a content.
/// </summary>
public string ScriptPublish { get; set; }
/// <summary>
/// The script that is executed when unpublishing a content.
/// </summary>
public string ScriptUnpublish { get; set; }
}
}

24
src/Squidex/Controllers/Api/Schemas/SchemasController.cs

@ -154,6 +154,30 @@ namespace Squidex.Controllers.Api.Schemas
return NoContent(); return NoContent();
} }
/// <summary>
/// Update the scripts of a schema.
/// </summary>
/// <param name="app">The name of the app.</param>
/// <param name="name">The name of the schema.</param>
/// <param name="request">The schema scripts object that needs to updated.</param>
/// <returns>
/// 204 => Schema has been updated.
/// 400 => Schema properties are not valid.
/// 404 => Schema or app not found.
/// </returns>
[MustBeAppDeveloper]
[HttpPut]
[Route("apps/{app}/schemas/{name}/scripts/")]
[ApiCosts(1)]
public async Task<IActionResult> PutSchemaScripts(string app, string name, [FromBody] ConfigureScriptsDto request)
{
var command = SimpleMapper.Map(request, new ConfigureScripts());
await CommandBus.PublishAsync(command);
return NoContent();
}
/// <summary> /// <summary>
/// Publish a schema. /// Publish a schema.
/// </summary> /// </summary>

63
src/Squidex/Controllers/ContentApi/ContentsController.cs

@ -15,15 +15,18 @@ using Microsoft.Extensions.Primitives;
using NSwag.Annotations; using NSwag.Annotations;
using Squidex.Controllers.ContentApi.Models; using Squidex.Controllers.ContentApi.Models;
using Squidex.Domain.Apps.Core.Contents; using Squidex.Domain.Apps.Core.Contents;
using Squidex.Domain.Apps.Core.Scripting;
using Squidex.Domain.Apps.Read.Contents.GraphQL; using Squidex.Domain.Apps.Read.Contents.GraphQL;
using Squidex.Domain.Apps.Read.Contents.Repositories; using Squidex.Domain.Apps.Read.Contents.Repositories;
using Squidex.Domain.Apps.Read.Schemas; using Squidex.Domain.Apps.Read.Schemas;
using Squidex.Domain.Apps.Read.Schemas.Services; using Squidex.Domain.Apps.Read.Schemas.Services;
using Squidex.Domain.Apps.Write.Contents;
using Squidex.Domain.Apps.Write.Contents.Commands; using Squidex.Domain.Apps.Write.Contents.Commands;
using Squidex.Infrastructure.CQRS.Commands; using Squidex.Infrastructure.CQRS.Commands;
using Squidex.Infrastructure.Reflection; using Squidex.Infrastructure.Reflection;
using Squidex.Pipeline; using Squidex.Pipeline;
// ReSharper disable InvertIf
// ReSharper disable PossibleNullReferenceException // ReSharper disable PossibleNullReferenceException
// ReSharper disable RedundantIfElseBlock // ReSharper disable RedundantIfElseBlock
@ -35,17 +38,20 @@ namespace Squidex.Controllers.ContentApi
public sealed class ContentsController : ControllerBase public sealed class ContentsController : ControllerBase
{ {
private readonly ISchemaProvider schemas; private readonly ISchemaProvider schemas;
private readonly IScriptEngine scriptEngine;
private readonly IContentRepository contentRepository; private readonly IContentRepository contentRepository;
private readonly IGraphQLService graphQL; private readonly IGraphQLService graphQL;
public ContentsController( public ContentsController(
ICommandBus commandBus, ICommandBus commandBus,
ISchemaProvider schemas, ISchemaProvider schemas,
IScriptEngine scriptEngine,
IContentRepository contentRepository, IContentRepository contentRepository,
IGraphQLService graphQL) IGraphQLService graphQL)
: base(commandBus) : base(commandBus)
{ {
this.graphQL = graphQL; this.graphQL = graphQL;
this.scriptEngine = scriptEngine;
this.schemas = schemas; this.schemas = schemas;
this.contentRepository = contentRepository; this.contentRepository = contentRepository;
} }
@ -99,16 +105,28 @@ namespace Squidex.Controllers.ContentApi
await Task.WhenAll(taskForItems, taskForCount); await Task.WhenAll(taskForItems, taskForCount);
var scriptUser = ScriptUser.Create(User);
var scriptText = schemaEntity.ScriptQuery;
var hasScript = !string.IsNullOrWhiteSpace(scriptText);
var response = new AssetsDto var response = new AssetsDto
{ {
Total = taskForCount.Result, Total = taskForCount.Result,
Items = taskForItems.Result.Take(200).Select(x => Items = taskForItems.Result.Take(200).Select(item =>
{ {
var itemModel = SimpleMapper.Map(x, new ContentDto()); var itemModel = SimpleMapper.Map(item, new ContentDto());
if (x.Data != null) if (item.Data != null)
{ {
itemModel.Data = x.Data.ToApiModel(schemaEntity.Schema, App.LanguagesConfig, null, !isFrontendClient); var data = item.Data.ToApiModel(schemaEntity.Schema, App.LanguagesConfig, null, !isFrontendClient);
if (hasScript && !isFrontendClient)
{
data = scriptEngine.ExecuteAndTransform(new ScriptContext { Data = data, ContentId = item.Id, User = scriptUser }, scriptText, "transform item");
}
itemModel.Data = data;
} }
return itemModel; return itemModel;
@ -144,7 +162,22 @@ namespace Squidex.Controllers.ContentApi
{ {
var isFrontendClient = User.IsFrontendClient(); var isFrontendClient = User.IsFrontendClient();
response.Data = entity.Data.ToApiModel(schemaEntity.Schema, App.LanguagesConfig, null, !isFrontendClient); var data = entity.Data.ToApiModel(schemaEntity.Schema, App.LanguagesConfig, null, !isFrontendClient);
if (!isFrontendClient)
{
var scriptUser = ScriptUser.Create(User);
var scriptText = schemaEntity.ScriptQuery;
var hasScript = !string.IsNullOrWhiteSpace(scriptText);
if (hasScript)
{
data = scriptEngine.ExecuteAndTransform(new ScriptContext { Data = data, ContentId = entity.Id, User = scriptUser }, scriptText, "transform item");
}
}
response.Data = data;
} }
Response.Headers["ETag"] = new StringValues(entity.Version.ToString()); Response.Headers["ETag"] = new StringValues(entity.Version.ToString());
@ -163,9 +196,9 @@ namespace Squidex.Controllers.ContentApi
var context = await CommandBus.PublishAsync(command); var context = await CommandBus.PublishAsync(command);
var result = context.Result<EntityCreatedResult<NamedContentData>>(); var result = context.Result<EntityCreatedResult<NamedContentData>>();
var response = ContentDto.Create(command, result); var response = result.IdOrValue;
return CreatedAtAction(nameof(GetContent), new { id = response.Id }, response); return CreatedAtAction(nameof(GetContent), new { id = command.ContentId }, response);
} }
[MustBeAppEditor] [MustBeAppEditor]
@ -176,9 +209,12 @@ namespace Squidex.Controllers.ContentApi
{ {
var command = new UpdateContent { ContentId = id, Data = request.ToCleaned() }; var command = new UpdateContent { ContentId = id, Data = request.ToCleaned() };
await CommandBus.PublishAsync(command); var context = await CommandBus.PublishAsync(command);
return NoContent(); var result = context.Result<ContentDataChangedResult>();
var response = result.Data;
return Ok(response);
} }
[MustBeAppEditor] [MustBeAppEditor]
@ -189,9 +225,12 @@ namespace Squidex.Controllers.ContentApi
{ {
var command = new PatchContent { ContentId = id, Data = request.ToCleaned() }; var command = new PatchContent { ContentId = id, Data = request.ToCleaned() };
await CommandBus.PublishAsync(command); var context = await CommandBus.PublishAsync(command);
return NoContent(); var result = context.Result<ContentDataChangedResult>();
var response = result.Data;
return Ok(response);
} }
[MustBeAppEditor] [MustBeAppEditor]

6
src/Squidex/Controllers/ContentApi/Generator/SchemaSwaggerGenerator.cs

@ -150,7 +150,7 @@ namespace Squidex.Controllers.ContentApi.Generator
operation.AddBodyParameter("data", dataSchema, SchemaBodyDescription); operation.AddBodyParameter("data", dataSchema, SchemaBodyDescription);
operation.AddQueryParameter("publish", JsonObjectType.Boolean, "Set to true to autopublish content."); operation.AddQueryParameter("publish", JsonObjectType.Boolean, "Set to true to autopublish content.");
operation.AddResponse("201", $"{schemaName} created.", contentSchema); operation.AddResponse("201", $"{schemaName} created.", dataSchema);
operation.Security = EditorSecurity; operation.Security = EditorSecurity;
}); });
@ -165,7 +165,7 @@ namespace Squidex.Controllers.ContentApi.Generator
operation.AddBodyParameter("data", dataSchema, SchemaBodyDescription); operation.AddBodyParameter("data", dataSchema, SchemaBodyDescription);
operation.AddResponse("204", $"{schemaName} element updated."); operation.AddResponse("201", $"{schemaName} element updated.", dataSchema);
operation.Security = EditorSecurity; operation.Security = EditorSecurity;
}); });
@ -180,7 +180,7 @@ namespace Squidex.Controllers.ContentApi.Generator
operation.AddBodyParameter("data", contentSchema, SchemaBodyDescription); operation.AddBodyParameter("data", contentSchema, SchemaBodyDescription);
operation.AddResponse("204", $"{schemaName} element updated."); operation.AddResponse("201", $"{schemaName} element patched.", dataSchema);
operation.Security = EditorSecurity; operation.Security = EditorSecurity;
}); });

24
src/Squidex/Controllers/ContentApi/Models/ContentDto.cs

@ -9,10 +9,7 @@
using System; using System;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using NodaTime; using NodaTime;
using Squidex.Domain.Apps.Core.Contents;
using Squidex.Domain.Apps.Write.Contents.Commands;
using Squidex.Infrastructure; using Squidex.Infrastructure;
using Squidex.Infrastructure.CQRS.Commands;
namespace Squidex.Controllers.ContentApi.Models namespace Squidex.Controllers.ContentApi.Models
{ {
@ -54,30 +51,11 @@ namespace Squidex.Controllers.ContentApi.Models
/// <summary> /// <summary>
/// Indicates if the content element is publihed. /// Indicates if the content element is publihed.
/// </summary> /// </summary>
public bool IsPublished { get; set; } public bool? IsPublished { get; set; }
/// <summary> /// <summary>
/// The version of the content. /// The version of the content.
/// </summary> /// </summary>
public long Version { get; set; } public long Version { get; set; }
public static ContentDto Create(CreateContent command, EntityCreatedResult<NamedContentData> result)
{
var now = SystemClock.Instance.GetCurrentInstant();
var response = new ContentDto
{
Id = command.ContentId,
Data = result.IdOrValue,
Version = result.Version,
Created = now,
CreatedBy = command.Actor,
LastModified = now,
LastModifiedBy = command.Actor,
IsPublished = command.Publish
};
return response;
}
} }
} }

4
tests/Squidex.Domain.Apps.Write.Tests/Contents/ContentCommandHandlerTests.cs

@ -123,7 +123,7 @@ namespace Squidex.Domain.Apps.Write.Contents
await sut.HandleAsync(context); await sut.HandleAsync(context);
}); });
Assert.Equal(data, context.Result<ContentChangedResult>().Content); Assert.Equal(data, context.Result<ContentDataChangedResult>().Data);
A.CallTo(() => scriptEngine.ExecuteAndTransform(A<ScriptContext>.Ignored, "<update-script>", "update content", true)).MustHaveHappened(); A.CallTo(() => scriptEngine.ExecuteAndTransform(A<ScriptContext>.Ignored, "<update-script>", "update content", true)).MustHaveHappened();
} }
@ -162,7 +162,7 @@ namespace Squidex.Domain.Apps.Write.Contents
await sut.HandleAsync(context); await sut.HandleAsync(context);
}); });
Assert.NotNull(context.Result<ContentChangedResult>().Content); Assert.NotNull(context.Result<ContentDataChangedResult>().Data);
A.CallTo(() => scriptEngine.ExecuteAndTransform(A<ScriptContext>.Ignored, "<update-script>", "patch content", true)).MustHaveHappened(); A.CallTo(() => scriptEngine.ExecuteAndTransform(A<ScriptContext>.Ignored, "<update-script>", "patch content", true)).MustHaveHappened();
} }

Loading…
Cancel
Save