mirror of https://github.com/Squidex/squidex.git
Browse Source
* First settings. * Migrations. * Angular update. * Type safe templates * Type safe templates * Backend Tests and minor fixes. * Some tests. * Cleanup and tests. * Fix tests for title component. * Remove patterns test. * Tests for settings.pull/687/head
committed by
GitHub
355 changed files with 6012 additions and 6328 deletions
@ -0,0 +1,112 @@ |
|||||
|
// ==========================================================================
|
||||
|
// Squidex Headless CMS
|
||||
|
// ==========================================================================
|
||||
|
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
||||
|
// All rights reserved. Licensed under the MIT license.
|
||||
|
// ==========================================================================
|
||||
|
|
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using System.Threading.Tasks; |
||||
|
using Migrations.OldEvents; |
||||
|
using Squidex.Domain.Apps.Core.Apps; |
||||
|
using Squidex.Domain.Apps.Entities.Apps.Commands; |
||||
|
using Squidex.Domain.Apps.Events.Apps; |
||||
|
using Squidex.Infrastructure; |
||||
|
using Squidex.Infrastructure.Collections; |
||||
|
using Squidex.Infrastructure.Commands; |
||||
|
using Squidex.Infrastructure.EventSourcing; |
||||
|
using Squidex.Infrastructure.Migrations; |
||||
|
|
||||
|
#pragma warning disable CS0618 // Type or member is obsolete
|
||||
|
|
||||
|
namespace Migrations.Migrations |
||||
|
{ |
||||
|
public sealed class CreateAppSettings : IMigration |
||||
|
{ |
||||
|
private readonly ICommandBus commandBus; |
||||
|
private readonly IEventDataFormatter eventDataFormatter; |
||||
|
private readonly IEventStore eventStore; |
||||
|
|
||||
|
public CreateAppSettings(ICommandBus commandBus, |
||||
|
IEventDataFormatter eventDataFormatter, |
||||
|
IEventStore eventStore) |
||||
|
{ |
||||
|
this.commandBus = commandBus; |
||||
|
this.eventDataFormatter = eventDataFormatter; |
||||
|
this.eventStore = eventStore; |
||||
|
} |
||||
|
|
||||
|
public async Task UpdateAsync() |
||||
|
{ |
||||
|
var apps = new Dictionary<NamedId<DomainId>, Dictionary<DomainId, (string Name, string Pattern, string? Message)>>(); |
||||
|
|
||||
|
await eventStore.QueryAsync(storedEvent => |
||||
|
{ |
||||
|
var @event = eventDataFormatter.ParseIfKnown(storedEvent); |
||||
|
|
||||
|
if (@event != null) |
||||
|
{ |
||||
|
switch (@event.Payload) |
||||
|
{ |
||||
|
case AppPatternAdded patternAdded: |
||||
|
{ |
||||
|
var patterns = apps.GetOrAddNew(patternAdded.AppId); |
||||
|
|
||||
|
patterns[patternAdded.PatternId] = (patternAdded.Name, patternAdded.Pattern, patternAdded.Message); |
||||
|
break; |
||||
|
} |
||||
|
|
||||
|
case AppPatternUpdated patternUpdated: |
||||
|
{ |
||||
|
var patterns = apps.GetOrAddNew(patternUpdated.AppId); |
||||
|
|
||||
|
patterns[patternUpdated.PatternId] = (patternUpdated.Name, patternUpdated.Pattern, patternUpdated.Message); |
||||
|
break; |
||||
|
} |
||||
|
|
||||
|
case AppPatternDeleted patternDeleted: |
||||
|
{ |
||||
|
var patterns = apps.GetOrAddNew(patternDeleted.AppId); |
||||
|
|
||||
|
patterns.Remove(patternDeleted.PatternId); |
||||
|
break; |
||||
|
} |
||||
|
|
||||
|
case AppArchived appArchived: |
||||
|
{ |
||||
|
apps.Remove(appArchived.AppId); |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return Task.CompletedTask; |
||||
|
}, "^app\\-"); |
||||
|
|
||||
|
var actor = RefToken.Client("Migrator"); |
||||
|
|
||||
|
foreach (var (appId, patterns) in apps) |
||||
|
{ |
||||
|
if (patterns.Count > 0) |
||||
|
{ |
||||
|
var settings = new AppSettings |
||||
|
{ |
||||
|
Patterns = patterns.Values.Select(x => new Pattern(x.Name, x.Pattern) |
||||
|
{ |
||||
|
Message = x.Message |
||||
|
}).ToReadOnlyCollection() |
||||
|
}; |
||||
|
|
||||
|
await commandBus.PublishAsync(new UpdateAppSettings |
||||
|
{ |
||||
|
AppId = appId, |
||||
|
Settings = settings, |
||||
|
FromRule = true, |
||||
|
Actor = actor |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -1,71 +0,0 @@ |
|||||
// ==========================================================================
|
|
||||
// Squidex Headless CMS
|
|
||||
// ==========================================================================
|
|
||||
// Copyright (c) Squidex UG (haftungsbeschränkt)
|
|
||||
// All rights reserved. Licensed under the MIT license.
|
|
||||
// ==========================================================================
|
|
||||
|
|
||||
using System.Collections.Generic; |
|
||||
using System.Diagnostics.Contracts; |
|
||||
using Squidex.Infrastructure; |
|
||||
using Squidex.Infrastructure.Collections; |
|
||||
|
|
||||
namespace Squidex.Domain.Apps.Core.Apps |
|
||||
{ |
|
||||
public sealed class AppPatterns : ImmutableDictionary<DomainId, AppPattern> |
|
||||
{ |
|
||||
public static readonly AppPatterns Empty = new AppPatterns(); |
|
||||
|
|
||||
private AppPatterns() |
|
||||
{ |
|
||||
} |
|
||||
|
|
||||
public AppPatterns(Dictionary<DomainId, AppPattern> inner) |
|
||||
: base(inner) |
|
||||
{ |
|
||||
} |
|
||||
|
|
||||
[Pure] |
|
||||
public AppPatterns Remove(DomainId id) |
|
||||
{ |
|
||||
return Without<AppPatterns>(id); |
|
||||
} |
|
||||
|
|
||||
[Pure] |
|
||||
public AppPatterns Add(DomainId id, string name, string pattern, string? message = null) |
|
||||
{ |
|
||||
Guard.NotNullOrEmpty(name, nameof(name)); |
|
||||
Guard.NotNullOrEmpty(pattern, nameof(pattern)); |
|
||||
|
|
||||
var newPattern = new AppPattern(name, pattern) { Message = message }; |
|
||||
|
|
||||
return With<AppPatterns>(id, newPattern); |
|
||||
} |
|
||||
|
|
||||
[Pure] |
|
||||
public AppPatterns Update(DomainId id, string? name = null, string? pattern = null, string? message = null) |
|
||||
{ |
|
||||
if (!TryGetValue(id, out var appPattern)) |
|
||||
{ |
|
||||
return this; |
|
||||
} |
|
||||
|
|
||||
var newPattern = appPattern with |
|
||||
{ |
|
||||
Message = message |
|
||||
}; |
|
||||
|
|
||||
if (!string.IsNullOrWhiteSpace(name)) |
|
||||
{ |
|
||||
newPattern = newPattern with { Name = name }; |
|
||||
} |
|
||||
|
|
||||
if (!string.IsNullOrWhiteSpace(pattern)) |
|
||||
{ |
|
||||
newPattern = newPattern with { Pattern = pattern }; |
|
||||
} |
|
||||
|
|
||||
return With<AppPatterns>(id, newPattern); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -0,0 +1,28 @@ |
|||||
|
// ==========================================================================
|
||||
|
// Squidex Headless CMS
|
||||
|
// ==========================================================================
|
||||
|
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
||||
|
// All rights reserved. Licensed under the MIT license.
|
||||
|
// ==========================================================================
|
||||
|
|
||||
|
using System.Collections.ObjectModel; |
||||
|
using Squidex.Infrastructure.Collections; |
||||
|
|
||||
|
namespace Squidex.Domain.Apps.Core.Apps |
||||
|
{ |
||||
|
[Equals(DoNotAddEqualityOperators = true)] |
||||
|
public sealed class AppSettings |
||||
|
{ |
||||
|
public static readonly AppSettings Empty = new AppSettings(); |
||||
|
|
||||
|
public ReadOnlyCollection<Pattern> Patterns { get; init; } = ReadOnlyCollection.Empty<Pattern>(); |
||||
|
|
||||
|
public ReadOnlyCollection<Editor> Editors { get; init; } = ReadOnlyCollection.Empty<Editor>(); |
||||
|
|
||||
|
public bool HideScheduler { get; init; } |
||||
|
|
||||
|
public bool HideDateTimeModeButton { get; init; } |
||||
|
|
||||
|
public bool HideDateTimeQuickButtons { get; init; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,15 @@ |
|||||
|
// ==========================================================================
|
||||
|
// Squidex Headless CMS
|
||||
|
// ==========================================================================
|
||||
|
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
||||
|
// All rights reserved. Licensed under the MIT license.
|
||||
|
// ==========================================================================
|
||||
|
|
||||
|
#pragma warning disable SA1313 // Parameter names should begin with lower-case letter
|
||||
|
|
||||
|
namespace Squidex.Domain.Apps.Core.Apps |
||||
|
{ |
||||
|
public sealed record Editor(string Name, string Url) |
||||
|
{ |
||||
|
} |
||||
|
} |
||||
@ -1,33 +0,0 @@ |
|||||
// ==========================================================================
|
|
||||
// Squidex Headless CMS
|
|
||||
// ==========================================================================
|
|
||||
// Copyright (c) Squidex UG (haftungsbeschränkt)
|
|
||||
// All rights reserved. Licensed under the MIT license.
|
|
||||
// ==========================================================================
|
|
||||
|
|
||||
using System.Collections.Generic; |
|
||||
using Squidex.Infrastructure; |
|
||||
|
|
||||
namespace Squidex.Domain.Apps.Core.Apps.Json |
|
||||
{ |
|
||||
public sealed class AppPatternsSurrogate : Dictionary<DomainId, AppPattern>, ISurrogate<AppPatterns> |
|
||||
{ |
|
||||
public void FromSource(AppPatterns source) |
|
||||
{ |
|
||||
foreach (var (key, pattern) in source) |
|
||||
{ |
|
||||
Add(key, pattern); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
public AppPatterns ToSource() |
|
||||
{ |
|
||||
if (Count == 0) |
|
||||
{ |
|
||||
return AppPatterns.Empty; |
|
||||
} |
|
||||
|
|
||||
return new AppPatterns(this); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,27 +0,0 @@ |
|||||
// ==========================================================================
|
|
||||
// Squidex Headless CMS
|
|
||||
// ==========================================================================
|
|
||||
// Copyright (c) Squidex UG (haftungsbeschränkt)
|
|
||||
// All rights reserved. Licensed under the MIT license.
|
|
||||
// ==========================================================================
|
|
||||
|
|
||||
using Squidex.Infrastructure; |
|
||||
|
|
||||
namespace Squidex.Domain.Apps.Entities.Apps.Commands |
|
||||
{ |
|
||||
public sealed class AddPattern : AppUpdateCommand |
|
||||
{ |
|
||||
public DomainId PatternId { get; set; } |
|
||||
|
|
||||
public string Name { get; set; } |
|
||||
|
|
||||
public string Pattern { get; set; } |
|
||||
|
|
||||
public string? Message { get; set; } |
|
||||
|
|
||||
public AddPattern() |
|
||||
{ |
|
||||
PatternId = DomainId.NewGuid(); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,22 +1,16 @@ |
|||||
// ==========================================================================
|
// ==========================================================================
|
||||
// Squidex Headless CMS
|
// Squidex Headless CMS
|
||||
// ==========================================================================
|
// ==========================================================================
|
||||
// Copyright (c) Squidex UG (haftungsbeschränkt)
|
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
||||
// All rights reserved. Licensed under the MIT license.
|
// All rights reserved. Licensed under the MIT license.
|
||||
// ==========================================================================
|
// ==========================================================================
|
||||
|
|
||||
using Squidex.Infrastructure; |
using Squidex.Domain.Apps.Core.Apps; |
||||
|
|
||||
namespace Squidex.Domain.Apps.Entities.Apps.Commands |
namespace Squidex.Domain.Apps.Entities.Apps.Commands |
||||
{ |
{ |
||||
public sealed class UpdatePattern : AppUpdateCommand |
public sealed class UpdateAppSettings : AppUpdateCommand |
||||
{ |
{ |
||||
public DomainId PatternId { get; set; } |
public AppSettings Settings { get; set; } |
||||
|
|
||||
public string Name { get; set; } |
|
||||
|
|
||||
public string Pattern { get; set; } |
|
||||
|
|
||||
public string? Message { get; set; } |
|
||||
} |
} |
||||
} |
} |
||||
@ -1,109 +0,0 @@ |
|||||
// ==========================================================================
|
|
||||
// Squidex Headless CMS
|
|
||||
// ==========================================================================
|
|
||||
// Copyright (c) Squidex UG (haftungsbeschränkt)
|
|
||||
// All rights reserved. Licensed under the MIT license.
|
|
||||
// ==========================================================================
|
|
||||
|
|
||||
using System; |
|
||||
using System.Linq; |
|
||||
using Squidex.Domain.Apps.Entities.Apps.Commands; |
|
||||
using Squidex.Infrastructure; |
|
||||
using Squidex.Infrastructure.Translations; |
|
||||
using Squidex.Infrastructure.Validation; |
|
||||
|
|
||||
namespace Squidex.Domain.Apps.Entities.Apps.DomainObject.Guards |
|
||||
{ |
|
||||
public static class GuardAppPatterns |
|
||||
{ |
|
||||
public static void CanAdd(AddPattern command, IAppEntity app) |
|
||||
{ |
|
||||
Guard.NotNull(command, nameof(command)); |
|
||||
|
|
||||
var patterns = app.Patterns; |
|
||||
|
|
||||
Validate.It(e => |
|
||||
{ |
|
||||
if (command.PatternId == DomainId.Empty) |
|
||||
{ |
|
||||
e(Not.Defined(nameof(command.PatternId)), nameof(command.PatternId)); |
|
||||
} |
|
||||
|
|
||||
if (string.IsNullOrWhiteSpace(command.Name)) |
|
||||
{ |
|
||||
e(Not.Defined(nameof(command.Name)), nameof(command.Name)); |
|
||||
} |
|
||||
|
|
||||
if (patterns.Values.Any(x => x.Name.Equals(command.Name, StringComparison.OrdinalIgnoreCase))) |
|
||||
{ |
|
||||
e(T.Get("apps.patterns.nameAlreadyExists")); |
|
||||
} |
|
||||
|
|
||||
if (string.IsNullOrWhiteSpace(command.Pattern)) |
|
||||
{ |
|
||||
e(Not.Defined(nameof(command.Pattern)), nameof(command.Pattern)); |
|
||||
} |
|
||||
else if (!command.Pattern.IsValidRegex()) |
|
||||
{ |
|
||||
e(Not.Valid(nameof(command.Pattern)), nameof(command.Pattern)); |
|
||||
} |
|
||||
|
|
||||
if (patterns.Values.Any(x => x.Pattern == command.Pattern)) |
|
||||
{ |
|
||||
e(T.Get("apps.patterns.patternAlreadyExists")); |
|
||||
} |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
public static void CanDelete(DeletePattern command, IAppEntity app) |
|
||||
{ |
|
||||
Guard.NotNull(command, nameof(command)); |
|
||||
|
|
||||
var patterns = app.Patterns; |
|
||||
|
|
||||
if (!patterns.ContainsKey(command.PatternId)) |
|
||||
{ |
|
||||
throw new DomainObjectNotFoundException(command.PatternId.ToString()); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
public static void CanUpdate(UpdatePattern command, IAppEntity app) |
|
||||
{ |
|
||||
Guard.NotNull(command, nameof(command)); |
|
||||
|
|
||||
var patterns = app.Patterns; |
|
||||
|
|
||||
if (!patterns.ContainsKey(command.PatternId)) |
|
||||
{ |
|
||||
throw new DomainObjectNotFoundException(command.PatternId.ToString()); |
|
||||
} |
|
||||
|
|
||||
Validate.It(e => |
|
||||
{ |
|
||||
if (string.IsNullOrWhiteSpace(command.Name)) |
|
||||
{ |
|
||||
e(Not.Defined(nameof(command.Name)), nameof(command.Name)); |
|
||||
} |
|
||||
|
|
||||
if (patterns.Any(x => x.Key != command.PatternId && x.Value.Name.Equals(command.Name, StringComparison.OrdinalIgnoreCase))) |
|
||||
{ |
|
||||
e(T.Get("apps.patterns.nameAlreadyExists")); |
|
||||
} |
|
||||
|
|
||||
if (string.IsNullOrWhiteSpace(command.Pattern)) |
|
||||
{ |
|
||||
e(Not.Defined(nameof(command.Pattern)), nameof(command.Pattern)); |
|
||||
} |
|
||||
else if (!command.Pattern.IsValidRegex()) |
|
||||
{ |
|
||||
e(Not.Valid(nameof(command.Pattern)), nameof(command.Pattern)); |
|
||||
} |
|
||||
|
|
||||
if (patterns.Any(x => x.Key != command.PatternId && x.Value.Pattern == command.Pattern)) |
|
||||
{ |
|
||||
e(T.Get("apps.patterns.patternAlreadyExists")); |
|
||||
} |
|
||||
}); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,25 +0,0 @@ |
|||||
// ==========================================================================
|
|
||||
// Squidex Headless CMS
|
|
||||
// ==========================================================================
|
|
||||
// Copyright (c) Squidex UG (haftungsbeschränkt)
|
|
||||
// All rights reserved. Licensed under the MIT license.
|
|
||||
// ==========================================================================
|
|
||||
|
|
||||
using System.Collections.Generic; |
|
||||
using Squidex.Domain.Apps.Core.Apps; |
|
||||
using Squidex.Infrastructure; |
|
||||
|
|
||||
namespace Squidex.Domain.Apps.Entities.Apps |
|
||||
{ |
|
||||
public sealed class InitialPatterns : Dictionary<DomainId, AppPattern> |
|
||||
{ |
|
||||
public InitialPatterns() |
|
||||
{ |
|
||||
} |
|
||||
|
|
||||
public InitialPatterns(Dictionary<DomainId, AppPattern> patterns) |
|
||||
: base(patterns) |
|
||||
{ |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -0,0 +1,18 @@ |
|||||
|
// ==========================================================================
|
||||
|
// Squidex Headless CMS
|
||||
|
// ==========================================================================
|
||||
|
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
||||
|
// All rights reserved. Licensed under the MIT license.
|
||||
|
// ==========================================================================
|
||||
|
|
||||
|
using Squidex.Domain.Apps.Core.Apps; |
||||
|
using Squidex.Infrastructure.EventSourcing; |
||||
|
|
||||
|
namespace Squidex.Domain.Apps.Events.Apps |
||||
|
{ |
||||
|
[EventType(nameof(AppSettingsUpdated))] |
||||
|
public sealed class AppSettingsUpdated : AppEvent |
||||
|
{ |
||||
|
public AppSettings Settings { get; set; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,36 @@ |
|||||
|
// ==========================================================================
|
||||
|
// Squidex Headless CMS
|
||||
|
// ==========================================================================
|
||||
|
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
||||
|
// All rights reserved. Licensed under the MIT license.
|
||||
|
// ==========================================================================
|
||||
|
|
||||
|
using System.Linq; |
||||
|
using Squidex.Infrastructure.Security; |
||||
|
|
||||
|
namespace Squidex.Shared |
||||
|
{ |
||||
|
public static class PermissionExtensions |
||||
|
{ |
||||
|
public static bool Allows(this PermissionSet permissions, string id, string app = Permission.Any, string schema = Permission.Any) |
||||
|
{ |
||||
|
var permission = Permissions.ForApp(id, app, schema); |
||||
|
|
||||
|
return permissions.Allows(permission); |
||||
|
} |
||||
|
|
||||
|
public static string[] ToAppNames(this PermissionSet permissions) |
||||
|
{ |
||||
|
var matching = permissions.Where(x => x.StartsWith("squidex.apps.")); |
||||
|
|
||||
|
var result = |
||||
|
matching |
||||
|
.Select(x => x.Id.Split('.')).Where(x => x.Length > 2) |
||||
|
.Select(x => x[2]) |
||||
|
.Distinct() |
||||
|
.ToArray(); |
||||
|
|
||||
|
return result; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -1,151 +0,0 @@ |
|||||
// ==========================================================================
|
|
||||
// Squidex Headless CMS
|
|
||||
// ==========================================================================
|
|
||||
// Copyright (c) Squidex UG (haftungsbeschränkt)
|
|
||||
// All rights reserved. Licensed under the MIT license.
|
|
||||
// ==========================================================================
|
|
||||
|
|
||||
using System.Threading.Tasks; |
|
||||
using Microsoft.AspNetCore.Http; |
|
||||
using Microsoft.AspNetCore.Mvc; |
|
||||
using Microsoft.Net.Http.Headers; |
|
||||
using Squidex.Areas.Api.Controllers.Apps.Models; |
|
||||
using Squidex.Domain.Apps.Entities.Apps; |
|
||||
using Squidex.Domain.Apps.Entities.Apps.Commands; |
|
||||
using Squidex.Infrastructure; |
|
||||
using Squidex.Infrastructure.Commands; |
|
||||
using Squidex.Shared; |
|
||||
using Squidex.Web; |
|
||||
|
|
||||
namespace Squidex.Areas.Api.Controllers.Apps |
|
||||
{ |
|
||||
/// <summary>
|
|
||||
/// Manages and configures app patterns.
|
|
||||
/// </summary>
|
|
||||
[ApiExplorerSettings(GroupName = nameof(Apps))] |
|
||||
public sealed class AppPatternsController : ApiController |
|
||||
{ |
|
||||
public AppPatternsController(ICommandBus commandBus) |
|
||||
: base(commandBus) |
|
||||
{ |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Get app patterns.
|
|
||||
/// </summary>
|
|
||||
/// <param name="app">The name of the app.</param>
|
|
||||
/// <returns>
|
|
||||
/// 200 => Patterns returned.
|
|
||||
/// 404 => App not found.
|
|
||||
/// </returns>
|
|
||||
/// <remarks>
|
|
||||
/// Gets all configured regex patterns for the app with the specified name.
|
|
||||
/// </remarks>
|
|
||||
[HttpGet] |
|
||||
[Route("apps/{app}/patterns/")] |
|
||||
[ProducesResponseType(typeof(PatternsDto), StatusCodes.Status200OK)] |
|
||||
[ApiPermissionOrAnonymous(Permissions.AppPatternsRead)] |
|
||||
[ApiCosts(0)] |
|
||||
public IActionResult GetPatterns(string app) |
|
||||
{ |
|
||||
var response = Deferred.Response(() => |
|
||||
{ |
|
||||
return GetResponse(App); |
|
||||
}); |
|
||||
|
|
||||
Response.Headers[HeaderNames.ETag] = App.ToEtag(); |
|
||||
|
|
||||
return Ok(response); |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Create a new app pattern.
|
|
||||
/// </summary>
|
|
||||
/// <param name="app">The name of the app.</param>
|
|
||||
/// <param name="request">Pattern to be added to the app.</param>
|
|
||||
/// <returns>
|
|
||||
/// 201 => Pattern created.
|
|
||||
/// 400 => Pattern request not valid.
|
|
||||
/// 404 => App not found.
|
|
||||
/// </returns>
|
|
||||
[HttpPost] |
|
||||
[Route("apps/{app}/patterns/")] |
|
||||
[ProducesResponseType(typeof(PatternsDto), 201)] |
|
||||
[ApiPermissionOrAnonymous(Permissions.AppPatternsCreate)] |
|
||||
[ApiCosts(1)] |
|
||||
public async Task<IActionResult> PostPattern(string app, [FromBody] UpdatePatternDto request) |
|
||||
{ |
|
||||
var command = request.ToAddCommand(); |
|
||||
|
|
||||
var response = await InvokeCommandAsync(command); |
|
||||
|
|
||||
return CreatedAtAction(nameof(GetPatterns), new { app }, response); |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Update an app pattern.
|
|
||||
/// </summary>
|
|
||||
/// <param name="app">The name of the app.</param>
|
|
||||
/// <param name="id">The id of the pattern to be updated.</param>
|
|
||||
/// <param name="request">Pattern to be updated for the app.</param>
|
|
||||
/// <returns>
|
|
||||
/// 200 => Pattern updated.
|
|
||||
/// 400 => Pattern request not valid.
|
|
||||
/// 404 => Pattern or app not found.
|
|
||||
/// </returns>
|
|
||||
[HttpPut] |
|
||||
[Route("apps/{app}/patterns/{id}/")] |
|
||||
[ProducesResponseType(typeof(PatternsDto), StatusCodes.Status200OK)] |
|
||||
[ApiPermissionOrAnonymous(Permissions.AppPatternsUpdate)] |
|
||||
[ApiCosts(1)] |
|
||||
public async Task<IActionResult> PutPattern(string app, DomainId id, [FromBody] UpdatePatternDto request) |
|
||||
{ |
|
||||
var command = request.ToUpdateCommand(id); |
|
||||
|
|
||||
var response = await InvokeCommandAsync(command); |
|
||||
|
|
||||
return Ok(response); |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Delete an app pattern.
|
|
||||
/// </summary>
|
|
||||
/// <param name="app">The name of the app.</param>
|
|
||||
/// <param name="id">The id of the pattern to be deleted.</param>
|
|
||||
/// <returns>
|
|
||||
/// 200 => Pattern deleted.
|
|
||||
/// 404 => Pattern or app not found.
|
|
||||
/// </returns>
|
|
||||
/// <remarks>
|
|
||||
/// Schemas using this pattern will still function using the same Regular Expression.
|
|
||||
/// </remarks>
|
|
||||
[HttpDelete] |
|
||||
[Route("apps/{app}/patterns/{id}/")] |
|
||||
[ProducesResponseType(typeof(PatternsDto), StatusCodes.Status200OK)] |
|
||||
[ApiPermissionOrAnonymous(Permissions.AppPatternsDelete)] |
|
||||
[ApiCosts(1)] |
|
||||
public async Task<IActionResult> DeletePattern(string app, DomainId id) |
|
||||
{ |
|
||||
var command = new DeletePattern { PatternId = id }; |
|
||||
|
|
||||
var response = await InvokeCommandAsync(command); |
|
||||
|
|
||||
return Ok(response); |
|
||||
} |
|
||||
|
|
||||
private async Task<PatternsDto> InvokeCommandAsync(ICommand command) |
|
||||
{ |
|
||||
var context = await CommandBus.PublishAsync(command); |
|
||||
|
|
||||
var result = context.Result<IAppEntity>(); |
|
||||
var response = GetResponse(result); |
|
||||
|
|
||||
return response; |
|
||||
} |
|
||||
|
|
||||
private PatternsDto GetResponse(IAppEntity result) |
|
||||
{ |
|
||||
return PatternsDto.FromApp(result, Resources); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -0,0 +1,74 @@ |
|||||
|
// ==========================================================================
|
||||
|
// Squidex Headless CMS
|
||||
|
// ==========================================================================
|
||||
|
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
||||
|
// All rights reserved. Licensed under the MIT license.
|
||||
|
// ==========================================================================
|
||||
|
|
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using Squidex.Domain.Apps.Entities.Apps; |
||||
|
using Squidex.Infrastructure.Reflection; |
||||
|
using Squidex.Infrastructure.Validation; |
||||
|
using Squidex.Web; |
||||
|
|
||||
|
namespace Squidex.Areas.Api.Controllers.Apps.Models |
||||
|
{ |
||||
|
public sealed class AppSettingsDto : Resource |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// The configured app patterns.
|
||||
|
/// </summary>
|
||||
|
[LocalizedRequired] |
||||
|
public List<PatternDto> Patterns { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// The configured UI editors.
|
||||
|
/// </summary>
|
||||
|
[LocalizedRequired] |
||||
|
public List<EditorDto> Editors { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Hide the scheduler for content items.
|
||||
|
/// </summary>
|
||||
|
public bool HideScheduler { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// The version of the app.
|
||||
|
/// </summary>
|
||||
|
public long Version { get; set; } |
||||
|
|
||||
|
public static AppSettingsDto FromApp(IAppEntity app, Resources resources) |
||||
|
{ |
||||
|
var settings = app.Settings; |
||||
|
|
||||
|
var result = new AppSettingsDto |
||||
|
{ |
||||
|
HideScheduler = settings.HideScheduler, |
||||
|
Patterns = |
||||
|
settings.Patterns |
||||
|
.Select(x => SimpleMapper.Map(x, new PatternDto())).ToList(), |
||||
|
Editors = |
||||
|
settings.Editors |
||||
|
.Select(x => SimpleMapper.Map(x, new EditorDto())).ToList(), |
||||
|
Version = app.Version |
||||
|
}; |
||||
|
|
||||
|
return result.CreateLinks(resources); |
||||
|
} |
||||
|
|
||||
|
private AppSettingsDto CreateLinks(Resources resources) |
||||
|
{ |
||||
|
var values = new { app = resources.App }; |
||||
|
|
||||
|
AddSelfLink(resources.Url<AppsController>(x => nameof(x.GetAppSettings), values)); |
||||
|
|
||||
|
if (resources.CanUpdateSettings) |
||||
|
{ |
||||
|
AddPutLink("update", resources.Url<AppsController>(x => nameof(x.PutAppSettings), values)); |
||||
|
} |
||||
|
|
||||
|
return this; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,26 @@ |
|||||
|
// ==========================================================================
|
||||
|
// Squidex Headless CMS
|
||||
|
// ==========================================================================
|
||||
|
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
||||
|
// All rights reserved. Licensed under the MIT license.
|
||||
|
// ==========================================================================
|
||||
|
|
||||
|
using Squidex.Infrastructure.Validation; |
||||
|
|
||||
|
namespace Squidex.Areas.Api.Controllers.Apps.Models |
||||
|
{ |
||||
|
public sealed class EditorDto |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// The name of the editor.
|
||||
|
/// </summary>
|
||||
|
[LocalizedRequired] |
||||
|
public string Name { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// The url to the editor.
|
||||
|
/// </summary>
|
||||
|
[LocalizedRequired] |
||||
|
public string Url { get; set; } |
||||
|
} |
||||
|
} |
||||
@ -1,47 +0,0 @@ |
|||||
// ==========================================================================
|
|
||||
// Squidex Headless CMS
|
|
||||
// ==========================================================================
|
|
||||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|
||||
// All rights reserved. Licensed under the MIT license.
|
|
||||
// ==========================================================================
|
|
||||
|
|
||||
using System.Linq; |
|
||||
using Squidex.Domain.Apps.Entities.Apps; |
|
||||
using Squidex.Infrastructure.Validation; |
|
||||
using Squidex.Web; |
|
||||
|
|
||||
namespace Squidex.Areas.Api.Controllers.Apps.Models |
|
||||
{ |
|
||||
public sealed class PatternsDto : Resource |
|
||||
{ |
|
||||
/// <summary>
|
|
||||
/// The patterns.
|
|
||||
/// </summary>
|
|
||||
[LocalizedRequired] |
|
||||
public PatternDto[] Items { get; set; } |
|
||||
|
|
||||
public static PatternsDto FromApp(IAppEntity app, Resources resources) |
|
||||
{ |
|
||||
var result = new PatternsDto |
|
||||
{ |
|
||||
Items = app.Patterns.Select(x => PatternDto.FromPattern(x.Key, x.Value, resources)).ToArray() |
|
||||
}; |
|
||||
|
|
||||
return result.CreateLinks(resources); |
|
||||
} |
|
||||
|
|
||||
private PatternsDto CreateLinks(Resources resources) |
|
||||
{ |
|
||||
var values = new { app = resources.App }; |
|
||||
|
|
||||
AddSelfLink(resources.Url<AppPatternsController>(x => nameof(x.GetPatterns), values)); |
|
||||
|
|
||||
if (resources.CanCreatePattern) |
|
||||
{ |
|
||||
AddPostLink("create", resources.Url<AppPatternsController>(x => nameof(x.PostPattern), values)); |
|
||||
} |
|
||||
|
|
||||
return this; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -0,0 +1,54 @@ |
|||||
|
// ==========================================================================
|
||||
|
// Squidex Headless CMS
|
||||
|
// ==========================================================================
|
||||
|
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
||||
|
// All rights reserved. Licensed under the MIT license.
|
||||
|
// ==========================================================================
|
||||
|
|
||||
|
using System.Collections.Generic; |
||||
|
using System.ComponentModel.DataAnnotations; |
||||
|
using System.Linq; |
||||
|
using Squidex.Domain.Apps.Core.Apps; |
||||
|
using Squidex.Domain.Apps.Entities.Apps.Commands; |
||||
|
using Squidex.Infrastructure.Collections; |
||||
|
|
||||
|
namespace Squidex.Areas.Api.Controllers.Apps.Models |
||||
|
{ |
||||
|
public sealed class UpdateAppSettingsDto |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// The configured app patterns.
|
||||
|
/// </summary>
|
||||
|
[Required] |
||||
|
public List<PatternDto> Patterns { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// The configured UI editors.
|
||||
|
/// </summary>
|
||||
|
[Required] |
||||
|
public List<EditorDto> Editors { get; set; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Hide the scheduler for content items.
|
||||
|
/// </summary>
|
||||
|
public bool HideScheduler { get; set; } |
||||
|
|
||||
|
public UpdateAppSettings ToCommand() |
||||
|
{ |
||||
|
return new UpdateAppSettings |
||||
|
{ |
||||
|
Settings = new AppSettings |
||||
|
{ |
||||
|
HideScheduler = HideScheduler, |
||||
|
Patterns = |
||||
|
Patterns?.Select(x => new Pattern(x.Name, x.Regex) |
||||
|
{ |
||||
|
Message = x.Message |
||||
|
}).ToReadOnlyCollection()!, |
||||
|
Editors = |
||||
|
Editors?.Select(x => new Editor(x.Name, x.Url)).ToReadOnlyCollection()! |
||||
|
} |
||||
|
}; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -1,44 +0,0 @@ |
|||||
// ==========================================================================
|
|
||||
// Squidex Headless CMS
|
|
||||
// ==========================================================================
|
|
||||
// Copyright (c) Squidex UG (haftungsbeschränkt)
|
|
||||
// All rights reserved. Licensed under the MIT license.
|
|
||||
// ==========================================================================
|
|
||||
|
|
||||
using Squidex.Domain.Apps.Entities.Apps.Commands; |
|
||||
using Squidex.Infrastructure; |
|
||||
using Squidex.Infrastructure.Reflection; |
|
||||
using Squidex.Infrastructure.Validation; |
|
||||
|
|
||||
namespace Squidex.Areas.Api.Controllers.Apps.Models |
|
||||
{ |
|
||||
public class UpdatePatternDto |
|
||||
{ |
|
||||
/// <summary>
|
|
||||
/// The name of the suggestion.
|
|
||||
/// </summary>
|
|
||||
[LocalizedRequired] |
|
||||
public string Name { get; set; } |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// The regex pattern.
|
|
||||
/// </summary>
|
|
||||
[LocalizedRequired] |
|
||||
public string Pattern { get; set; } |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// The regex message.
|
|
||||
/// </summary>
|
|
||||
public string? Message { get; set; } |
|
||||
|
|
||||
public AddPattern ToAddCommand() |
|
||||
{ |
|
||||
return SimpleMapper.Map(this, new AddPattern()); |
|
||||
} |
|
||||
|
|
||||
public UpdatePattern ToUpdateCommand(DomainId id) |
|
||||
{ |
|
||||
return SimpleMapper.Map(this, new UpdatePattern { PatternId = id }); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,39 +0,0 @@ |
|||||
// ==========================================================================
|
|
||||
// Squidex Headless CMS
|
|
||||
// ==========================================================================
|
|
||||
// Copyright (c) Squidex UG (haftungsbeschränkt)
|
|
||||
// All rights reserved. Licensed under the MIT license.
|
|
||||
// ==========================================================================
|
|
||||
|
|
||||
using FluentAssertions; |
|
||||
using Squidex.Domain.Apps.Core.Apps; |
|
||||
using Squidex.Domain.Apps.Core.TestHelpers; |
|
||||
using Squidex.Infrastructure; |
|
||||
using Xunit; |
|
||||
|
|
||||
namespace Squidex.Domain.Apps.Core.Model.Apps |
|
||||
{ |
|
||||
public class AppPatternJsonTests |
|
||||
{ |
|
||||
[Fact] |
|
||||
public void Should_serialize_and_deserialize() |
|
||||
{ |
|
||||
var patterns = AppPatterns.Empty; |
|
||||
|
|
||||
var guid1 = DomainId.NewGuid(); |
|
||||
var guid2 = DomainId.NewGuid(); |
|
||||
var guid3 = DomainId.NewGuid(); |
|
||||
|
|
||||
patterns = patterns.Add(guid1, "Name1", "Pattern1", "Default"); |
|
||||
patterns = patterns.Add(guid2, "Name2", "Pattern2", "Default"); |
|
||||
patterns = patterns.Add(guid3, "Name3", "Pattern3", "Default"); |
|
||||
patterns = patterns.Update(guid2, "Name2 Update", "Pattern2 Update", "Default2"); |
|
||||
patterns = patterns.Update(guid3, "Name3 Update", "Pattern3 Update", "Default3"); |
|
||||
patterns = patterns.Remove(guid1); |
|
||||
|
|
||||
var serialized = patterns.SerializeAndDeserialize(); |
|
||||
|
|
||||
serialized.Should().BeEquivalentTo(patterns); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,86 +0,0 @@ |
|||||
// ==========================================================================
|
|
||||
// Squidex Headless CMS
|
|
||||
// ==========================================================================
|
|
||||
// Copyright (c) Squidex UG (haftungsbeschränkt)
|
|
||||
// All rights reserved. Licensed under the MIT license.
|
|
||||
// ==========================================================================
|
|
||||
|
|
||||
using System.Linq; |
|
||||
using FluentAssertions; |
|
||||
using Squidex.Domain.Apps.Core.Apps; |
|
||||
using Squidex.Infrastructure; |
|
||||
using Xunit; |
|
||||
|
|
||||
#pragma warning disable SA1310 // Field names must not contain underscore
|
|
||||
|
|
||||
namespace Squidex.Domain.Apps.Core.Model.Apps |
|
||||
{ |
|
||||
public class AppPatternsTests |
|
||||
{ |
|
||||
private readonly AppPatterns patterns_0; |
|
||||
private readonly DomainId firstId = DomainId.NewGuid(); |
|
||||
private readonly DomainId id = DomainId.NewGuid(); |
|
||||
|
|
||||
public AppPatternsTests() |
|
||||
{ |
|
||||
patterns_0 = AppPatterns.Empty.Add(firstId, "Default", "Default Pattern", "Message"); |
|
||||
} |
|
||||
|
|
||||
[Fact] |
|
||||
public void Should_add_pattern() |
|
||||
{ |
|
||||
var patterns_1 = patterns_0.Add(id, "NewPattern", "New Pattern", "Message"); |
|
||||
|
|
||||
patterns_1[id].Should().BeEquivalentTo(new AppPattern("NewPattern", "New Pattern") with { Message = "Message" }); |
|
||||
} |
|
||||
|
|
||||
[Fact] |
|
||||
public void Should_do_nothing_if_adding_pattern_with_same_id() |
|
||||
{ |
|
||||
var patterns_1 = patterns_0.Add(firstId, "Default", "Default Pattern", "Message"); |
|
||||
|
|
||||
Assert.Same(patterns_1, patterns_0); |
|
||||
} |
|
||||
|
|
||||
[Fact] |
|
||||
public void Should_update_pattern() |
|
||||
{ |
|
||||
var patterns_1 = patterns_0.Update(firstId, "UpdatePattern", "Update Pattern"); |
|
||||
|
|
||||
patterns_1[firstId].Should().BeEquivalentTo(new AppPattern("UpdatePattern", "Update Pattern")); |
|
||||
} |
|
||||
|
|
||||
[Fact] |
|
||||
public void Should_return_same_patterns_if_pattern_is_updated_with_same_values() |
|
||||
{ |
|
||||
var patterns_1 = patterns_0.Update(firstId, "Default", "Default Pattern", "Message"); |
|
||||
|
|
||||
Assert.Same(patterns_0, patterns_1); |
|
||||
} |
|
||||
|
|
||||
[Fact] |
|
||||
public void Should_return_same_patterns_if_pattern_to_update_not_found() |
|
||||
{ |
|
||||
var patterns_1 = patterns_0.Update(id, "NewPattern", "NewPattern", "Message"); |
|
||||
|
|
||||
Assert.Same(patterns_0, patterns_1); |
|
||||
} |
|
||||
|
|
||||
[Fact] |
|
||||
public void Should_remove_pattern() |
|
||||
{ |
|
||||
var patterns_1 = patterns_0.Add(id, "Name1", "Pattern1"); |
|
||||
var patterns_2 = patterns_1.Remove(firstId); |
|
||||
|
|
||||
Assert.Equal(id, patterns_2.Keys.Single()); |
|
||||
} |
|
||||
|
|
||||
[Fact] |
|
||||
public void Should_do_nothing_if_remove_pattern_not_found() |
|
||||
{ |
|
||||
var patterns_1 = patterns_0.Remove(id); |
|
||||
|
|
||||
Assert.Same(patterns_0, patterns_1); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,192 +0,0 @@ |
|||||
// ==========================================================================
|
|
||||
// Squidex Headless CMS
|
|
||||
// ==========================================================================
|
|
||||
// Copyright (c) Squidex UG (haftungsbeschränkt)
|
|
||||
// All rights reserved. Licensed under the MIT license.
|
|
||||
// ==========================================================================
|
|
||||
|
|
||||
using FakeItEasy; |
|
||||
using Squidex.Domain.Apps.Core.Apps; |
|
||||
using Squidex.Domain.Apps.Core.TestHelpers; |
|
||||
using Squidex.Domain.Apps.Entities.Apps.Commands; |
|
||||
using Squidex.Domain.Apps.Entities.TestHelpers; |
|
||||
using Squidex.Infrastructure; |
|
||||
using Squidex.Infrastructure.Validation; |
|
||||
using Xunit; |
|
||||
|
|
||||
#pragma warning disable SA1310 // Field names must not contain underscore
|
|
||||
|
|
||||
namespace Squidex.Domain.Apps.Entities.Apps.DomainObject.Guards |
|
||||
{ |
|
||||
public class GuardAppPatternsTests : IClassFixture<TranslationsFixture> |
|
||||
{ |
|
||||
private readonly DomainId patternId = DomainId.NewGuid(); |
|
||||
private readonly AppPatterns patterns_0 = AppPatterns.Empty; |
|
||||
|
|
||||
[Fact] |
|
||||
public void CanAdd_should_throw_exception_if_name_empty() |
|
||||
{ |
|
||||
var command = new AddPattern { PatternId = patternId, Name = string.Empty, Pattern = ".*" }; |
|
||||
|
|
||||
ValidationAssert.Throws(() => GuardAppPatterns.CanAdd(command, App(patterns_0)), |
|
||||
new ValidationError("Name is required.", "Name")); |
|
||||
} |
|
||||
|
|
||||
[Fact] |
|
||||
public void CanAdd_should_throw_exception_if_pattern_empty() |
|
||||
{ |
|
||||
var command = new AddPattern { PatternId = patternId, Name = "any", Pattern = string.Empty }; |
|
||||
|
|
||||
ValidationAssert.Throws(() => GuardAppPatterns.CanAdd(command, App(patterns_0)), |
|
||||
new ValidationError("Pattern is required.", "Pattern")); |
|
||||
} |
|
||||
|
|
||||
[Fact] |
|
||||
public void CanAdd_should_throw_exception_if_pattern_not_valid() |
|
||||
{ |
|
||||
var command = new AddPattern { PatternId = patternId, Name = "any", Pattern = "[0-9{1}" }; |
|
||||
|
|
||||
ValidationAssert.Throws(() => GuardAppPatterns.CanAdd(command, App(patterns_0)), |
|
||||
new ValidationError("Pattern is not a valid value.", "Pattern")); |
|
||||
} |
|
||||
|
|
||||
[Fact] |
|
||||
public void CanAdd_should_throw_exception_if_name_exists() |
|
||||
{ |
|
||||
var patterns_1 = patterns_0.Add(DomainId.NewGuid(), "any", "[a-z]", "Message"); |
|
||||
|
|
||||
var command = new AddPattern { PatternId = patternId, Name = "any", Pattern = ".*" }; |
|
||||
|
|
||||
ValidationAssert.Throws(() => GuardAppPatterns.CanAdd(command, App(patterns_1)), |
|
||||
new ValidationError("A pattern with the same name already exists.")); |
|
||||
} |
|
||||
|
|
||||
[Fact] |
|
||||
public void CanAdd_should_throw_exception_if_pattern_exists() |
|
||||
{ |
|
||||
var patterns_1 = patterns_0.Add(DomainId.NewGuid(), "any", "[a-z]", "Message"); |
|
||||
|
|
||||
var command = new AddPattern { PatternId = patternId, Name = "other", Pattern = "[a-z]" }; |
|
||||
|
|
||||
ValidationAssert.Throws(() => GuardAppPatterns.CanAdd(command, App(patterns_1)), |
|
||||
new ValidationError("This pattern already exists but with another name.")); |
|
||||
} |
|
||||
|
|
||||
[Fact] |
|
||||
public void CanAdd_should_not_throw_exception_if_command_is_valid() |
|
||||
{ |
|
||||
var command = new AddPattern { PatternId = patternId, Name = "any", Pattern = ".*" }; |
|
||||
|
|
||||
GuardAppPatterns.CanAdd(command, App(patterns_0)); |
|
||||
} |
|
||||
|
|
||||
[Fact] |
|
||||
public void CanDelete_should_throw_exception_if_pattern_not_found() |
|
||||
{ |
|
||||
var command = new DeletePattern { PatternId = patternId }; |
|
||||
|
|
||||
Assert.Throws<DomainObjectNotFoundException>(() => GuardAppPatterns.CanDelete(command, App(patterns_0))); |
|
||||
} |
|
||||
|
|
||||
[Fact] |
|
||||
public void CanDelete_should_not_throw_exception_if_command_is_valid() |
|
||||
{ |
|
||||
var patterns_1 = patterns_0.Add(patternId, "any", ".*", "Message"); |
|
||||
|
|
||||
var command = new DeletePattern { PatternId = patternId }; |
|
||||
|
|
||||
GuardAppPatterns.CanDelete(command, App(patterns_1)); |
|
||||
} |
|
||||
|
|
||||
[Fact] |
|
||||
public void CanUpdate_should_throw_exception_if_name_empty() |
|
||||
{ |
|
||||
var patterns_1 = patterns_0.Add(patternId, "any", ".*", "Message"); |
|
||||
|
|
||||
var command = new UpdatePattern { PatternId = patternId, Name = string.Empty, Pattern = ".*" }; |
|
||||
|
|
||||
ValidationAssert.Throws(() => GuardAppPatterns.CanUpdate(command, App(patterns_1)), |
|
||||
new ValidationError("Name is required.", "Name")); |
|
||||
} |
|
||||
|
|
||||
[Fact] |
|
||||
public void CanUpdate_should_throw_exception_if_pattern_empty() |
|
||||
{ |
|
||||
var patterns_1 = patterns_0.Add(patternId, "any", ".*", "Message"); |
|
||||
|
|
||||
var command = new UpdatePattern { PatternId = patternId, Name = "any", Pattern = string.Empty }; |
|
||||
|
|
||||
ValidationAssert.Throws(() => GuardAppPatterns.CanUpdate(command, App(patterns_1)), |
|
||||
new ValidationError("Pattern is required.", "Pattern")); |
|
||||
} |
|
||||
|
|
||||
[Fact] |
|
||||
public void CanUpdate_should_throw_exception_if_pattern_not_valid() |
|
||||
{ |
|
||||
var patterns_1 = patterns_0.Add(patternId, "any", ".*", "Message"); |
|
||||
|
|
||||
var command = new UpdatePattern { PatternId = patternId, Name = "any", Pattern = "[0-9{1}" }; |
|
||||
|
|
||||
ValidationAssert.Throws(() => GuardAppPatterns.CanUpdate(command, App(patterns_1)), |
|
||||
new ValidationError("Pattern is not a valid value.", "Pattern")); |
|
||||
} |
|
||||
|
|
||||
[Fact] |
|
||||
public void CanUpdate_should_throw_exception_if_name_exists() |
|
||||
{ |
|
||||
var id1 = DomainId.NewGuid(); |
|
||||
var id2 = DomainId.NewGuid(); |
|
||||
|
|
||||
var patterns_1 = patterns_0.Add(id1, "Pattern1", "[0-5]", "Message"); |
|
||||
var patterns_2 = patterns_1.Add(id2, "Pattern2", "[0-4]", "Message"); |
|
||||
|
|
||||
var command = new UpdatePattern { PatternId = id2, Name = "Pattern1", Pattern = "[0-4]" }; |
|
||||
|
|
||||
ValidationAssert.Throws(() => GuardAppPatterns.CanUpdate(command, App(patterns_2)), |
|
||||
new ValidationError("A pattern with the same name already exists.")); |
|
||||
} |
|
||||
|
|
||||
[Fact] |
|
||||
public void CanUpdate_should_throw_exception_if_pattern_exists() |
|
||||
{ |
|
||||
var id1 = DomainId.NewGuid(); |
|
||||
var id2 = DomainId.NewGuid(); |
|
||||
|
|
||||
var patterns_1 = patterns_0.Add(id1, "Pattern1", "[0-5]", "Message"); |
|
||||
var patterns_2 = patterns_1.Add(id2, "Pattern2", "[0-4]", "Message"); |
|
||||
|
|
||||
var command = new UpdatePattern { PatternId = id2, Name = "Pattern2", Pattern = "[0-5]" }; |
|
||||
|
|
||||
ValidationAssert.Throws(() => GuardAppPatterns.CanUpdate(command, App(patterns_2)), |
|
||||
new ValidationError("This pattern already exists but with another name.")); |
|
||||
} |
|
||||
|
|
||||
[Fact] |
|
||||
public void CanUpdate_should_throw_exception_if_pattern_does_not_exists() |
|
||||
{ |
|
||||
var command = new UpdatePattern { PatternId = patternId, Name = "Pattern1", Pattern = ".*" }; |
|
||||
|
|
||||
Assert.Throws<DomainObjectNotFoundException>(() => GuardAppPatterns.CanUpdate(command, App(patterns_0))); |
|
||||
} |
|
||||
|
|
||||
[Fact] |
|
||||
public void CanUpdate_should_not_throw_exception_if_pattern_exist_with_valid_command() |
|
||||
{ |
|
||||
var patterns_1 = patterns_0.Add(patternId, "any", ".*", "Message"); |
|
||||
|
|
||||
var command = new UpdatePattern { PatternId = patternId, Name = "Pattern1", Pattern = ".*" }; |
|
||||
|
|
||||
GuardAppPatterns.CanUpdate(command, App(patterns_1)); |
|
||||
} |
|
||||
|
|
||||
private static IAppEntity App(AppPatterns patterns) |
|
||||
{ |
|
||||
var app = A.Fake<IAppEntity>(); |
|
||||
|
|
||||
A.CallTo(() => app.Patterns) |
|
||||
.Returns(patterns); |
|
||||
|
|
||||
return app; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,6 +1,6 @@ |
|||||
<sqx-title message="i18n:common.clusterPageTitle"></sqx-title> |
<sqx-title message="i18n:common.clusterPageTitle"></sqx-title> |
||||
|
|
||||
<sqx-panel desiredWidth="*" minWidth="50rem" isFullSize="true"> |
<sqx-panel desiredWidth="*" minWidth="50rem" [isFullSize]="true"> |
||||
<div inner> |
<div inner> |
||||
<iframe src="./orleans"></iframe> |
<iframe src="./orleans"></iframe> |
||||
</div> |
</div> |
||||
|
|||||
@ -1,5 +1,5 @@ |
|||||
<sqx-title message="i18n:api.graphqlPageTitle"></sqx-title> |
<sqx-title message="i18n:api.graphqlPageTitle"></sqx-title> |
||||
|
|
||||
<sqx-panel desiredWidth="*" minWidth="50rem" isFullSize="true"> |
<sqx-panel desiredWidth="*" minWidth="50rem" [isFullSize]="true"> |
||||
<div inner #graphiQLContainer></div> |
<div inner #graphiQLContainer></div> |
||||
</sqx-panel> |
</sqx-panel> |
||||
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue