mirror of https://github.com/Squidex/squidex.git
81 changed files with 1488 additions and 533 deletions
@ -0,0 +1,50 @@ |
|||
// ==========================================================================
|
|||
// AppClientsConverter.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using Newtonsoft.Json; |
|||
|
|||
namespace Squidex.Domain.Apps.Core.Apps.Json |
|||
{ |
|||
public sealed class AppClientsConverter : JsonConverter |
|||
{ |
|||
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) |
|||
{ |
|||
var clients = (AppClients)value; |
|||
|
|||
var json = new Dictionary<string, JsonAppClient>(clients.Count); |
|||
|
|||
foreach (var client in clients) |
|||
{ |
|||
json.Add(client.Key, new JsonAppClient(client.Value)); |
|||
} |
|||
|
|||
serializer.Serialize(writer, json); |
|||
} |
|||
|
|||
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) |
|||
{ |
|||
var json = serializer.Deserialize<Dictionary<string, JsonAppClient>>(reader); |
|||
|
|||
var clients = new AppClients(); |
|||
|
|||
foreach (var client in json) |
|||
{ |
|||
clients.Add(client.Key, client.Value.ToClient()); |
|||
} |
|||
|
|||
return clients; |
|||
} |
|||
|
|||
public override bool CanConvert(Type objectType) |
|||
{ |
|||
return objectType == typeof(AppClients); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,50 @@ |
|||
// ==========================================================================
|
|||
// AppContributorsConverter.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using Newtonsoft.Json; |
|||
|
|||
namespace Squidex.Domain.Apps.Core.Apps.Json |
|||
{ |
|||
public sealed class AppContributorsConverter : JsonConverter |
|||
{ |
|||
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) |
|||
{ |
|||
var contributors = (AppContributors)value; |
|||
|
|||
var json = new Dictionary<string, AppContributorPermission>(contributors.Count); |
|||
|
|||
foreach (var contributor in contributors) |
|||
{ |
|||
json.Add(contributor.Key, contributor.Value); |
|||
} |
|||
|
|||
serializer.Serialize(writer, json); |
|||
} |
|||
|
|||
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) |
|||
{ |
|||
var json = serializer.Deserialize<Dictionary<string, AppContributorPermission>>(reader); |
|||
|
|||
var contributors = new AppContributors(); |
|||
|
|||
foreach (var contributor in json) |
|||
{ |
|||
contributors.Assign(contributor.Key, contributor.Value); |
|||
} |
|||
|
|||
return contributors; |
|||
} |
|||
|
|||
public override bool CanConvert(Type objectType) |
|||
{ |
|||
return objectType == typeof(AppContributors); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,39 @@ |
|||
// ==========================================================================
|
|||
// JsonAppClient.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using Newtonsoft.Json; |
|||
using Squidex.Infrastructure.Reflection; |
|||
|
|||
namespace Squidex.Domain.Apps.Core.Apps.Json |
|||
{ |
|||
public class JsonAppClient |
|||
{ |
|||
[JsonProperty] |
|||
public string Name { get; set; } |
|||
|
|||
[JsonProperty] |
|||
public string Secret { get; set; } |
|||
|
|||
[JsonProperty] |
|||
public AppClientPermission Permission { get; set; } |
|||
|
|||
public JsonAppClient() |
|||
{ |
|||
} |
|||
|
|||
public JsonAppClient(AppClient client) |
|||
{ |
|||
SimpleMapper.Map(client, this); |
|||
} |
|||
|
|||
public AppClient ToClient() |
|||
{ |
|||
return new AppClient(Name, Secret, Permission); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,40 @@ |
|||
// ==========================================================================
|
|||
// JsonLanguageConfig.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System.Linq; |
|||
using Newtonsoft.Json; |
|||
using Squidex.Infrastructure; |
|||
using Squidex.Infrastructure.Reflection; |
|||
|
|||
namespace Squidex.Domain.Apps.Core.Apps.Json |
|||
{ |
|||
public class JsonLanguageConfig |
|||
{ |
|||
[JsonProperty] |
|||
public Language[] Fallback { get; set; } |
|||
|
|||
[JsonProperty] |
|||
public bool IsOptional { get; set; } |
|||
|
|||
public JsonLanguageConfig() |
|||
{ |
|||
} |
|||
|
|||
public JsonLanguageConfig(LanguageConfig config) |
|||
{ |
|||
SimpleMapper.Map(config, this); |
|||
|
|||
Fallback = config.LanguageFallbacks.ToArray(); |
|||
} |
|||
|
|||
public LanguageConfig ToConfig(string language) |
|||
{ |
|||
return new LanguageConfig(language, IsOptional, Fallback); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,52 @@ |
|||
// ==========================================================================
|
|||
// AppClientsConverter.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using Newtonsoft.Json; |
|||
|
|||
namespace Squidex.Domain.Apps.Core.Apps.Json |
|||
{ |
|||
public sealed class LanguagesConfigConverter : JsonConverter |
|||
{ |
|||
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) |
|||
{ |
|||
var languagesConfig = (LanguagesConfig)value; |
|||
|
|||
var json = new Dictionary<string, JsonLanguageConfig>(languagesConfig.Count); |
|||
|
|||
foreach (var config in languagesConfig.Configs) |
|||
{ |
|||
json.Add(config.Language, new JsonLanguageConfig(config)); |
|||
} |
|||
|
|||
serializer.Serialize(writer, json); |
|||
} |
|||
|
|||
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) |
|||
{ |
|||
var json = serializer.Deserialize<Dictionary<string, JsonLanguageConfig>>(reader); |
|||
|
|||
var languagesConfig = new LanguageConfig[json.Count]; |
|||
|
|||
var i = 0; |
|||
|
|||
foreach (var config in json) |
|||
{ |
|||
languagesConfig[i++] = config.Value.ToConfig(config.Key); |
|||
} |
|||
|
|||
return LanguagesConfig.Build(languagesConfig); |
|||
} |
|||
|
|||
public override bool CanConvert(Type objectType) |
|||
{ |
|||
return objectType == typeof(LanguagesConfig); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,63 @@ |
|||
// ==========================================================================
|
|||
// DictionaryBase.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System.Collections; |
|||
using System.Collections.Generic; |
|||
|
|||
namespace Squidex.Domain.Apps.Core |
|||
{ |
|||
public abstract class DictionaryBase<TKey, TValue> : IReadOnlyDictionary<TKey, TValue> |
|||
{ |
|||
private readonly Dictionary<TKey, TValue> inner = new Dictionary<TKey, TValue>(); |
|||
|
|||
public TValue this[TKey key] |
|||
{ |
|||
get { return inner[key]; } |
|||
} |
|||
|
|||
public IEnumerable<TKey> Keys |
|||
{ |
|||
get { return inner.Keys; } |
|||
} |
|||
|
|||
public IEnumerable<TValue> Values |
|||
{ |
|||
get { return inner.Values; } |
|||
} |
|||
|
|||
public int Count |
|||
{ |
|||
get { return inner.Count; } |
|||
} |
|||
|
|||
protected Dictionary<TKey, TValue> Inner |
|||
{ |
|||
get { return inner; } |
|||
} |
|||
|
|||
public bool ContainsKey(TKey key) |
|||
{ |
|||
return inner.ContainsKey(key); |
|||
} |
|||
|
|||
public bool TryGetValue(TKey key, out TValue value) |
|||
{ |
|||
return inner.TryGetValue(key, out value); |
|||
} |
|||
|
|||
IEnumerator<KeyValuePair<TKey, TValue>> IEnumerable<KeyValuePair<TKey, TValue>>.GetEnumerator() |
|||
{ |
|||
return inner.GetEnumerator(); |
|||
} |
|||
|
|||
IEnumerator IEnumerable.GetEnumerator() |
|||
{ |
|||
return inner.GetEnumerator(); |
|||
} |
|||
} |
|||
} |
|||
@ -1,21 +0,0 @@ |
|||
// ==========================================================================
|
|||
// IAppClientEntity.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using Squidex.Domain.Apps.Core.Apps; |
|||
|
|||
namespace Squidex.Domain.Apps.Read.Apps |
|||
{ |
|||
public interface IAppClientEntity |
|||
{ |
|||
string Name { get; } |
|||
|
|||
string Secret { get; } |
|||
|
|||
AppClientPermission Permission { get; } |
|||
} |
|||
} |
|||
@ -0,0 +1,102 @@ |
|||
// ==========================================================================
|
|||
// GuardAppClients.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using Squidex.Domain.Apps.Core.Apps; |
|||
using Squidex.Domain.Apps.Write.Apps.Commands; |
|||
using Squidex.Infrastructure; |
|||
|
|||
namespace Squidex.Domain.Apps.Write.Apps.Guards |
|||
{ |
|||
public static class GuardAppClients |
|||
{ |
|||
public static void CanAttach(AppClients clients, AttachClient command) |
|||
{ |
|||
Guard.NotNull(command, nameof(command)); |
|||
|
|||
Validate.It(() => "Cannot attach client.", error => |
|||
{ |
|||
if (string.IsNullOrWhiteSpace(command.Id)) |
|||
{ |
|||
error(new ValidationError("Client id must be defined.", nameof(command.Id))); |
|||
} |
|||
else if (clients.ContainsKey(command.Id)) |
|||
{ |
|||
error(new ValidationError("Client id already added.", nameof(command.Id))); |
|||
} |
|||
}); |
|||
} |
|||
|
|||
public static void CanRevoke(AppClients clients, RevokeClient command) |
|||
{ |
|||
Guard.NotNull(command, nameof(command)); |
|||
|
|||
GetClientOrThrow(clients, command.Id); |
|||
|
|||
Validate.It(() => "Cannot revoke client.", error => |
|||
{ |
|||
if (string.IsNullOrWhiteSpace(command.Id)) |
|||
{ |
|||
error(new ValidationError("Client id must be defined.", nameof(command.Id))); |
|||
} |
|||
}); |
|||
} |
|||
|
|||
public static void CanUpdate(AppClients clients, UpdateClient command) |
|||
{ |
|||
Guard.NotNull(command, nameof(command)); |
|||
|
|||
var client = GetClientOrThrow(clients, command.Id); |
|||
|
|||
Validate.It(() => "Cannot revoke client.", error => |
|||
{ |
|||
if (string.IsNullOrWhiteSpace(command.Id)) |
|||
{ |
|||
error(new ValidationError("Client id must be defined.", nameof(command.Id))); |
|||
} |
|||
|
|||
if (string.IsNullOrWhiteSpace(command.Name) && command.Permission == null) |
|||
{ |
|||
error(new ValidationError("Either name or permission must be defined.", nameof(command.Name), nameof(command.Permission))); |
|||
} |
|||
|
|||
if (command.Permission.HasValue && !command.Permission.Value.IsEnumValue()) |
|||
{ |
|||
error(new ValidationError("Permission is not valid.", nameof(command.Permission))); |
|||
} |
|||
|
|||
if (client != null) |
|||
{ |
|||
if (!string.IsNullOrWhiteSpace(command.Name) && string.Equals(client.Name, command.Name)) |
|||
{ |
|||
error(new ValidationError("Client already has this name.", nameof(command.Permission))); |
|||
} |
|||
|
|||
if (command.Permission == client.Permission) |
|||
{ |
|||
error(new ValidationError("Client already has this permission.", nameof(command.Permission))); |
|||
} |
|||
} |
|||
}); |
|||
} |
|||
|
|||
private static AppClient GetClientOrThrow(AppClients clients, string id) |
|||
{ |
|||
if (id == null) |
|||
{ |
|||
return null; |
|||
} |
|||
|
|||
if (!clients.TryGetValue(id, out var client)) |
|||
{ |
|||
throw new DomainObjectNotFoundException(id, "Clients", typeof(AppDomainObject)); |
|||
} |
|||
|
|||
return client; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,134 @@ |
|||
// ==========================================================================
|
|||
// ContentOperationContext.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Threading.Tasks; |
|||
using Squidex.Domain.Apps.Core.EnrichContent; |
|||
using Squidex.Domain.Apps.Core.Scripting; |
|||
using Squidex.Domain.Apps.Core.ValidateContent; |
|||
using Squidex.Domain.Apps.Read.Apps; |
|||
using Squidex.Domain.Apps.Read.Apps.Services; |
|||
using Squidex.Domain.Apps.Read.Assets.Repositories; |
|||
using Squidex.Domain.Apps.Read.Contents.Repositories; |
|||
using Squidex.Domain.Apps.Read.Schemas; |
|||
using Squidex.Domain.Apps.Read.Schemas.Services; |
|||
using Squidex.Domain.Apps.Write.Contents.Commands; |
|||
using Squidex.Infrastructure; |
|||
using Squidex.Infrastructure.Tasks; |
|||
|
|||
namespace Squidex.Domain.Apps.Write.Contents |
|||
{ |
|||
public sealed class ContentOperationContext |
|||
{ |
|||
private ContentDomainObject content; |
|||
private ContentCommand command; |
|||
private IContentRepository contentRepository; |
|||
private IAssetRepository assetRepository; |
|||
private IScriptEngine scriptEngine; |
|||
private ISchemaEntity schemaEntity; |
|||
private IAppEntity appEntity; |
|||
private Func<string> message; |
|||
|
|||
public static async Task<ContentOperationContext> CreateAsync( |
|||
IContentRepository contentRepository, |
|||
ContentDomainObject content, |
|||
ContentCommand command, |
|||
IAppProvider appProvider, |
|||
ISchemaProvider schemas, |
|||
IScriptEngine scriptEngine, |
|||
IAssetRepository assetRepository, |
|||
Func<string> message) |
|||
{ |
|||
var taskForApp = appProvider.FindAppByIdAsync(command.AppId.Id); |
|||
var taskForSchema = schemas.FindSchemaByIdAsync(command.SchemaId.Id); |
|||
|
|||
await Task.WhenAll(taskForApp, taskForSchema); |
|||
|
|||
var context = new ContentOperationContext(); |
|||
|
|||
context.appEntity = taskForApp.Result; |
|||
context.assetRepository = assetRepository; |
|||
context.contentRepository = contentRepository; |
|||
context.content = content; |
|||
context.command = command; |
|||
context.message = message; |
|||
context.schemaEntity = taskForSchema.Result; |
|||
context.scriptEngine = scriptEngine; |
|||
|
|||
return context; |
|||
} |
|||
|
|||
public Task EnrichAsync() |
|||
{ |
|||
if (command is ContentDataCommand dataCommand) |
|||
{ |
|||
dataCommand.Data.Enrich(schemaEntity.SchemaDef, appEntity.PartitionResolver); |
|||
} |
|||
|
|||
return TaskHelper.Done; |
|||
} |
|||
|
|||
public async Task ValidateAsync(bool partial) |
|||
{ |
|||
if (command is ContentDataCommand dataCommand) |
|||
{ |
|||
var errors = new List<ValidationError>(); |
|||
|
|||
var appId = command.AppId.Id; |
|||
|
|||
var ctx = |
|||
new ValidationContext( |
|||
(contentIds, schemaId) => |
|||
{ |
|||
return contentRepository.QueryNotFoundAsync(appId, schemaId, contentIds.ToList()); |
|||
}, |
|||
assetIds => |
|||
{ |
|||
return assetRepository.QueryNotFoundAsync(appId, assetIds.ToList()); |
|||
}); |
|||
|
|||
if (partial) |
|||
{ |
|||
await dataCommand.Data.ValidatePartialAsync(ctx, schemaEntity.SchemaDef, appEntity.PartitionResolver, errors); |
|||
} |
|||
else |
|||
{ |
|||
await dataCommand.Data.ValidateAsync(ctx, schemaEntity.SchemaDef, appEntity.PartitionResolver, errors); |
|||
} |
|||
|
|||
if (errors.Count > 0) |
|||
{ |
|||
throw new ValidationException(message(), errors.ToArray()); |
|||
} |
|||
} |
|||
} |
|||
|
|||
public Task ExecuteScriptAndTransformAsync(Func<ISchemaEntity, string> script, object operation) |
|||
{ |
|||
if (command is ContentDataCommand dataCommand) |
|||
{ |
|||
var ctx = new ScriptContext { ContentId = content.Id, OldData = content.Data, User = command.User, Operation = operation.ToString(), Data = dataCommand.Data }; |
|||
|
|||
dataCommand.Data = scriptEngine.ExecuteAndTransform(ctx, script(schemaEntity)); |
|||
} |
|||
|
|||
return TaskHelper.Done; |
|||
} |
|||
|
|||
public Task ExecuteScriptAsync(Func<ISchemaEntity, string> script, object operation) |
|||
{ |
|||
var ctx = new ScriptContext { ContentId = content.Id, OldData = content.Data, User = command.User, Operation = operation.ToString() }; |
|||
|
|||
scriptEngine.Execute(ctx, script(schemaEntity)); |
|||
|
|||
return TaskHelper.Done; |
|||
} |
|||
} |
|||
} |
|||
@ -1,17 +1,16 @@ |
|||
// ==========================================================================
|
|||
// IAppContributorEntity.cs
|
|||
// BsonJsonAttribute.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using Squidex.Domain.Apps.Core.Apps; |
|||
using System; |
|||
|
|||
namespace Squidex.Domain.Apps.Read.Apps |
|||
namespace Squidex.Infrastructure.MongoDb |
|||
{ |
|||
public interface IAppContributorEntity |
|||
public sealed class BsonJsonAttribute : Attribute |
|||
{ |
|||
AppContributorPermission Permission { get; } |
|||
} |
|||
} |
|||
@ -0,0 +1,35 @@ |
|||
// ==========================================================================
|
|||
// BsonJsonConvention.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System.Linq; |
|||
using System.Reflection; |
|||
using MongoDB.Bson.Serialization.Conventions; |
|||
using Newtonsoft.Json; |
|||
|
|||
namespace Squidex.Infrastructure.MongoDb |
|||
{ |
|||
public static class BsonJsonConvention |
|||
{ |
|||
public static void Register(JsonSerializer serializer) |
|||
{ |
|||
var pack = new ConventionPack(); |
|||
|
|||
var bsonSerializer = new JsonBsonSerializer(serializer); |
|||
|
|||
pack.AddMemberMapConvention("JsonBson", memberMap => |
|||
{ |
|||
if (memberMap.MemberType.GetCustomAttributes().OfType<BsonJsonAttribute>().Any()) |
|||
{ |
|||
memberMap.SetSerializer(bsonSerializer); |
|||
} |
|||
}); |
|||
|
|||
ConventionRegistry.Register("json", pack, t => true); |
|||
} |
|||
} |
|||
} |
|||
@ -1,84 +0,0 @@ |
|||
// ==========================================================================
|
|||
// DictionaryWrapper.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Collections; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
|
|||
namespace Squidex.Infrastructure |
|||
{ |
|||
public sealed class DictionaryWrapper<TKey, TValue, TSuper> : IReadOnlyDictionary<TKey, TValue> where TSuper : class, TValue where TValue : class |
|||
{ |
|||
private readonly Func<Dictionary<TKey, TSuper>> inner; |
|||
|
|||
public DictionaryWrapper(Func<Dictionary<TKey, TSuper>> inner) |
|||
{ |
|||
Guard.NotNull(inner, nameof(inner)); |
|||
|
|||
this.inner = inner; |
|||
} |
|||
|
|||
public IEnumerable<TKey> Keys |
|||
{ |
|||
get { return inner().Keys; } |
|||
} |
|||
|
|||
public IEnumerable<TValue> Values |
|||
{ |
|||
get { return inner().Values.OfType<TValue>(); } |
|||
} |
|||
|
|||
public int Count |
|||
{ |
|||
get { return inner().Count; } |
|||
} |
|||
|
|||
public TValue this[TKey key] |
|||
{ |
|||
get { return inner()[key]; } |
|||
} |
|||
|
|||
public bool ContainsKey(TKey key) |
|||
{ |
|||
return inner().ContainsKey(key); |
|||
} |
|||
|
|||
public bool TryGetValue(TKey key, out TValue value) |
|||
{ |
|||
if (inner().TryGetValue(key, out var temp)) |
|||
{ |
|||
value = temp as TValue; |
|||
|
|||
return value != null; |
|||
} |
|||
|
|||
value = null; |
|||
|
|||
return false; |
|||
} |
|||
|
|||
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator() |
|||
{ |
|||
return Enumerate().GetEnumerator(); |
|||
} |
|||
|
|||
IEnumerator IEnumerable.GetEnumerator() |
|||
{ |
|||
return GetEnumerator(); |
|||
} |
|||
|
|||
private IEnumerable<KeyValuePair<TKey, TValue>> Enumerate() |
|||
{ |
|||
foreach (var kvp in inner()) |
|||
{ |
|||
yield return new KeyValuePair<TKey, TValue>(kvp.Key, (TValue)kvp.Value); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,103 @@ |
|||
// ==========================================================================
|
|||
// AppClientsTests.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using FluentAssertions; |
|||
using Newtonsoft.Json; |
|||
using Newtonsoft.Json.Linq; |
|||
using Squidex.Domain.Apps.Core.Apps; |
|||
using Xunit; |
|||
|
|||
namespace Squidex.Domain.Apps.Core.Model.Apps |
|||
{ |
|||
public class AppClientsTests |
|||
{ |
|||
private readonly JsonSerializer serializer = TestData.DefaultSerializer(); |
|||
private readonly AppClients sut = new AppClients(); |
|||
|
|||
public AppClientsTests() |
|||
{ |
|||
sut.Add("1", "my-secret"); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_assign_client() |
|||
{ |
|||
sut.Add("2", "my-secret"); |
|||
|
|||
sut["2"].ShouldBeEquivalentTo(new AppClient("2", "my-secret", AppClientPermission.Editor)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_assign_client_with_permission() |
|||
{ |
|||
sut.Add("2", new AppClient("my-name", "my-secret", AppClientPermission.Reader)); |
|||
|
|||
sut["2"].ShouldBeEquivalentTo(new AppClient("my-name", "my-secret", AppClientPermission.Reader)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_throw_exception_if_assigning_client_with_same_id() |
|||
{ |
|||
sut.Add("2", "my-secret"); |
|||
|
|||
Assert.Throws<ArgumentException>(() => sut.Add("2", "my-secret")); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_rename_client() |
|||
{ |
|||
sut["1"].Rename("my-name"); |
|||
|
|||
sut["1"].ShouldBeEquivalentTo(new AppClient("my-name", "my-secret", AppClientPermission.Editor)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_update_client() |
|||
{ |
|||
sut["1"].Update(AppClientPermission.Reader); |
|||
|
|||
sut["1"].ShouldBeEquivalentTo(new AppClient("1", "my-secret", AppClientPermission.Reader)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_revoke_client() |
|||
{ |
|||
sut.Revoke("1"); |
|||
|
|||
Assert.Empty(sut); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_do_nothing_if_client_to_revoke_not_found() |
|||
{ |
|||
sut.Revoke("2"); |
|||
|
|||
Assert.Single(sut); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_serialize_and_deserialize() |
|||
{ |
|||
sut.Add("2", "my-secret"); |
|||
sut.Add("3", "my-secret"); |
|||
sut.Add("4", "my-secret"); |
|||
|
|||
sut["3"].Update(AppClientPermission.Editor); |
|||
|
|||
sut["3"].Rename("My Client 3"); |
|||
sut["2"].Rename("My Client 2"); |
|||
|
|||
sut.Revoke("4"); |
|||
|
|||
var appClients = JToken.FromObject(sut, serializer).ToObject<AppClients>(serializer); |
|||
|
|||
appClients.ShouldBeEquivalentTo(sut); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,70 @@ |
|||
// ==========================================================================
|
|||
// AppContributorsTests.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using FluentAssertions; |
|||
using Newtonsoft.Json; |
|||
using Newtonsoft.Json.Linq; |
|||
using Squidex.Domain.Apps.Core.Apps; |
|||
using Xunit; |
|||
|
|||
namespace Squidex.Domain.Apps.Core.Model.Apps |
|||
{ |
|||
public class AppContributorsTests |
|||
{ |
|||
private readonly JsonSerializer serializer = TestData.DefaultSerializer(); |
|||
private readonly AppContributors sut = new AppContributors(); |
|||
|
|||
[Fact] |
|||
public void Should_assign_new_contributor() |
|||
{ |
|||
sut.Assign("1", AppContributorPermission.Developer); |
|||
sut.Assign("2", AppContributorPermission.Editor); |
|||
|
|||
Assert.Equal(AppContributorPermission.Developer, sut["1"]); |
|||
Assert.Equal(AppContributorPermission.Editor, sut["2"]); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_replace_contributor_if_already_exists() |
|||
{ |
|||
sut.Assign("1", AppContributorPermission.Developer); |
|||
sut.Assign("1", AppContributorPermission.Owner); |
|||
|
|||
Assert.Equal(AppContributorPermission.Owner, sut["1"]); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_remove_contributor() |
|||
{ |
|||
sut.Assign("1", AppContributorPermission.Developer); |
|||
sut.Remove("1"); |
|||
|
|||
Assert.Empty(sut); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_do_nothing_if_contributor_to_remove_not_found() |
|||
{ |
|||
sut.Remove("2"); |
|||
|
|||
Assert.Empty(sut); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_serialize_and_deserialize() |
|||
{ |
|||
sut.Assign("1", AppContributorPermission.Developer); |
|||
sut.Assign("2", AppContributorPermission.Editor); |
|||
sut.Assign("3", AppContributorPermission.Owner); |
|||
|
|||
var serialized = JToken.FromObject(sut, serializer).ToObject<AppContributors>(serializer); |
|||
|
|||
serialized.ShouldBeEquivalentTo(sut); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,32 @@ |
|||
// ==========================================================================
|
|||
// AppPlanTests.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using FluentAssertions; |
|||
using Newtonsoft.Json; |
|||
using Newtonsoft.Json.Linq; |
|||
using Squidex.Domain.Apps.Core.Apps; |
|||
using Squidex.Infrastructure; |
|||
using Xunit; |
|||
|
|||
namespace Squidex.Domain.Apps.Core.Model.Apps |
|||
{ |
|||
public class AppPlanTests |
|||
{ |
|||
private readonly JsonSerializer serializer = TestData.DefaultSerializer(); |
|||
|
|||
[Fact] |
|||
public void Should_serialize_and_deserialize() |
|||
{ |
|||
var sut = new AppPlan(new RefToken("user", "Me"), "free"); |
|||
|
|||
var serialized = JToken.FromObject(sut, serializer).ToObject<AppPlan>(serializer); |
|||
|
|||
serialized.ShouldBeEquivalentTo(sut); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,35 @@ |
|||
// ==========================================================================
|
|||
// LanguagesConfigJsonTests.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using FluentAssertions; |
|||
using Newtonsoft.Json; |
|||
using Newtonsoft.Json.Linq; |
|||
using Squidex.Domain.Apps.Core.Apps; |
|||
using Squidex.Infrastructure; |
|||
using Xunit; |
|||
|
|||
namespace Squidex.Domain.Apps.Core.Model.Apps |
|||
{ |
|||
public class LanguagesConfigJsonTests |
|||
{ |
|||
private readonly JsonSerializer serializer = TestData.DefaultSerializer(); |
|||
|
|||
[Fact] |
|||
public void Should_serialize_and_deserialize() |
|||
{ |
|||
var sut = LanguagesConfig.Build( |
|||
new LanguageConfig(Language.EN), |
|||
new LanguageConfig(Language.DE, true, Language.EN), |
|||
new LanguageConfig(Language.IT, false, Language.DE)); |
|||
|
|||
var serialized = JToken.FromObject(sut, serializer).ToObject<LanguagesConfig>(serializer); |
|||
|
|||
serialized.ShouldBeEquivalentTo(sut); |
|||
} |
|||
} |
|||
} |
|||
@ -1,55 +0,0 @@ |
|||
// ==========================================================================
|
|||
// JsonSerializerTests.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using FluentAssertions; |
|||
using Newtonsoft.Json; |
|||
using Newtonsoft.Json.Converters; |
|||
using Newtonsoft.Json.Linq; |
|||
using Squidex.Domain.Apps.Core.Schemas; |
|||
using Squidex.Domain.Apps.Core.Schemas.Json; |
|||
using Squidex.Infrastructure; |
|||
using Squidex.Infrastructure.Json; |
|||
using Xunit; |
|||
|
|||
namespace Squidex.Domain.Apps.Core.Model.Schemas.Json |
|||
{ |
|||
public class JsonSerializerTests |
|||
{ |
|||
private readonly JsonSerializerSettings serializerSettings = new JsonSerializerSettings(); |
|||
private readonly JsonSerializer serializer; |
|||
private readonly TypeNameRegistry typeNameRegistry = new TypeNameRegistry(); |
|||
|
|||
public JsonSerializerTests() |
|||
{ |
|||
serializerSettings.SerializationBinder = new TypeNameSerializationBinder(typeNameRegistry); |
|||
|
|||
serializerSettings.ContractResolver = new ConverterContractResolver( |
|||
new InstantConverter(), |
|||
new LanguageConverter(), |
|||
new NamedGuidIdConverter(), |
|||
new NamedLongIdConverter(), |
|||
new NamedStringIdConverter(), |
|||
new RefTokenConverter(), |
|||
new SchemaConverter(new FieldRegistry(typeNameRegistry)), |
|||
new StringEnumConverter()); |
|||
|
|||
serializerSettings.TypeNameHandling = TypeNameHandling.Auto; |
|||
|
|||
serializer = JsonSerializer.Create(serializerSettings); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_serialize_and_deserialize_schema() |
|||
{ |
|||
var schemaSource = TestData.MixedSchema(); |
|||
var schemaTarget = JToken.FromObject(schemaSource, serializer).ToObject<Schema>(serializer); |
|||
|
|||
schemaTarget.ShouldBeEquivalentTo(schemaSource); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,91 @@ |
|||
// ==========================================================================
|
|||
// SchemaFieldTests.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using Squidex.Domain.Apps.Core.Schemas; |
|||
using Xunit; |
|||
|
|||
namespace Squidex.Domain.Apps.Core.Model.Schemas |
|||
{ |
|||
public class SchemaFieldTests |
|||
{ |
|||
private readonly NumberField sut = new NumberField(1, "my-field", Partitioning.Invariant); |
|||
|
|||
[Fact] |
|||
public void Should_instantiate_field() |
|||
{ |
|||
Assert.Equal("my-field", sut.Name); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_throw_exception_if_creating_field_with_invalid_name() |
|||
{ |
|||
Assert.Throws<ArgumentException>(() => new NumberField(1, string.Empty, Partitioning.Invariant)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_hide_field() |
|||
{ |
|||
sut.Hide(); |
|||
sut.Hide(); |
|||
|
|||
Assert.True(sut.IsHidden); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_show_field() |
|||
{ |
|||
sut.Hide(); |
|||
sut.Show(); |
|||
sut.Show(); |
|||
|
|||
Assert.False(sut.IsHidden); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_disable_field() |
|||
{ |
|||
sut.Disable(); |
|||
sut.Disable(); |
|||
|
|||
Assert.True(sut.IsDisabled); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_enable_field() |
|||
{ |
|||
sut.Disable(); |
|||
sut.Enable(); |
|||
sut.Enable(); |
|||
|
|||
Assert.False(sut.IsDisabled); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_lock_field() |
|||
{ |
|||
sut.Lock(); |
|||
|
|||
Assert.True(sut.IsLocked); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_update_field() |
|||
{ |
|||
sut.Update(new NumberFieldProperties { Hints = "my-hints" }); |
|||
|
|||
Assert.Equal("my-hints", sut.RawProperties.Hints); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Should_throw_exception_if_updating_with_invalid_properties_type() |
|||
{ |
|||
Assert.Throws<ArgumentException>(() => sut.Update(new StringFieldProperties())); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,140 @@ |
|||
// ==========================================================================
|
|||
// GuardAppClientsTests.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using Squidex.Domain.Apps.Core.Apps; |
|||
using Squidex.Domain.Apps.Write.Apps.Commands; |
|||
using Squidex.Infrastructure; |
|||
using Xunit; |
|||
|
|||
namespace Squidex.Domain.Apps.Write.Apps.Guards |
|||
{ |
|||
public class GuardAppClientsTests |
|||
{ |
|||
private readonly AppClients clients = new AppClients(); |
|||
|
|||
[Fact] |
|||
public void CanAttach_should_throw_execption_if_client_id_is_null() |
|||
{ |
|||
var command = new AttachClient(); |
|||
|
|||
Assert.Throws<ValidationException>(() => GuardAppClients.CanAttach(clients, command)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanAttach_should_throw_exception_if_client_already_exists() |
|||
{ |
|||
var command = new AttachClient { Id = "android" }; |
|||
|
|||
clients.Add("android", "secret"); |
|||
|
|||
Assert.Throws<ValidationException>(() => GuardAppClients.CanAttach(clients, command)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanAttach_should_not_throw_exception_if_client_is_free() |
|||
{ |
|||
var command = new AttachClient { Id = "ios" }; |
|||
|
|||
clients.Add("android", "secret"); |
|||
|
|||
GuardAppClients.CanAttach(clients, command); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanRevoke_should_throw_execption_if_client_id_is_null() |
|||
{ |
|||
var command = new RevokeClient(); |
|||
|
|||
Assert.Throws<ValidationException>(() => GuardAppClients.CanRevoke(clients, command)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanRevoke_should_throw_exception_if_client_is_not_found() |
|||
{ |
|||
var command = new RevokeClient { Id = "ios" }; |
|||
|
|||
Assert.Throws<DomainObjectNotFoundException>(() => GuardAppClients.CanRevoke(clients, command)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanRevoke_should_not_throw_exception_if_client_is_found() |
|||
{ |
|||
var command = new RevokeClient { Id = "ios" }; |
|||
|
|||
clients.Add("ios", "secret"); |
|||
|
|||
GuardAppClients.CanRevoke(clients, command); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanUpdate_should_throw_execption_if_client_id_is_null() |
|||
{ |
|||
var command = new UpdateClient(); |
|||
|
|||
Assert.Throws<ValidationException>(() => GuardAppClients.CanUpdate(clients, command)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void UpdateClient_should_throw_exception_if_client_is_not_found() |
|||
{ |
|||
var command = new UpdateClient { Id = "ios", Name = "iOS" }; |
|||
|
|||
Assert.Throws<DomainObjectNotFoundException>(() => GuardAppClients.CanUpdate(clients, command)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void UpdateClient_should_throw_exception_if_client_has_no_name_and_permission() |
|||
{ |
|||
var command = new UpdateClient { Id = "ios" }; |
|||
|
|||
clients.Add("ios", "secret"); |
|||
|
|||
Assert.Throws<ValidationException>(() => GuardAppClients.CanUpdate(clients, command)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void UpdateClient_should_throw_exception_if_client_has_invalid_permission() |
|||
{ |
|||
var command = new UpdateClient { Id = "ios", Permission = (AppClientPermission)10 }; |
|||
|
|||
clients.Add("ios", "secret"); |
|||
|
|||
Assert.Throws<ValidationException>(() => GuardAppClients.CanUpdate(clients, command)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void UpdateClient_should_throw_exception_if_client_has_same_name() |
|||
{ |
|||
var command = new UpdateClient { Id = "ios", Name = "ios" }; |
|||
|
|||
clients.Add("ios", "secret"); |
|||
|
|||
Assert.Throws<ValidationException>(() => GuardAppClients.CanUpdate(clients, command)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void UpdateClient_should_throw_exception_if_client_has_same_permission() |
|||
{ |
|||
var command = new UpdateClient { Id = "ios", Permission = AppClientPermission.Editor }; |
|||
|
|||
clients.Add("ios", "secret"); |
|||
|
|||
Assert.Throws<ValidationException>(() => GuardAppClients.CanUpdate(clients, command)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void UpdateClient_should_not_throw_exception_if_command_is_valid() |
|||
{ |
|||
var command = new UpdateClient { Id = "ios", Name = "iOS", Permission = AppClientPermission.Reader }; |
|||
|
|||
clients.Add("ios", "secret"); |
|||
|
|||
GuardAppClients.CanUpdate(clients, command); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,99 @@ |
|||
// ==========================================================================
|
|||
// GuardContentTests.cs
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex Group
|
|||
// All rights reserved.
|
|||
// ==========================================================================
|
|||
|
|||
using Squidex.Domain.Apps.Core.Contents; |
|||
using Squidex.Domain.Apps.Write.Contents.Commands; |
|||
using Squidex.Domain.Apps.Write.Contents.Guards; |
|||
using Squidex.Infrastructure; |
|||
using Xunit; |
|||
|
|||
namespace Squidex.Domain.Apps.Write.Contents.Guard |
|||
{ |
|||
public class GuardContentTests |
|||
{ |
|||
[Fact] |
|||
public void CanCreate_should_throw_exception_if_data_is_null() |
|||
{ |
|||
var command = new CreateContent(); |
|||
|
|||
Assert.Throws<ValidationException>(() => GuardContent.CanCreate(command)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanCreate_should_not_throw_exception_if_data_is_not_null() |
|||
{ |
|||
var command = new CreateContent { Data = new NamedContentData() }; |
|||
|
|||
GuardContent.CanCreate(command); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanUpdate_should_throw_exception_if_data_is_null() |
|||
{ |
|||
var command = new UpdateContent(); |
|||
|
|||
Assert.Throws<ValidationException>(() => GuardContent.CanUpdate(command)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanUpdate_should_not_throw_exception_if_data_is_not_null() |
|||
{ |
|||
var command = new UpdateContent { Data = new NamedContentData() }; |
|||
|
|||
GuardContent.CanUpdate(command); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanPatch_should_throw_exception_if_data_is_null() |
|||
{ |
|||
var command = new PatchContent(); |
|||
|
|||
Assert.Throws<ValidationException>(() => GuardContent.CanPatch(command)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanPatch_should_not_throw_exception_if_data_is_not_null() |
|||
{ |
|||
var command = new PatchContent { Data = new NamedContentData() }; |
|||
|
|||
GuardContent.CanPatch(command); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanChangeContentStatus_should_throw_exception_if_status_not_valid() |
|||
{ |
|||
var command = new ChangeContentStatus { Status = (Status)10 }; |
|||
|
|||
Assert.Throws<ValidationException>(() => GuardContent.CanChangeContentStatus(Status.Archived, command)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanChangeContentStatus_should_throw_exception_if_status_flow_not_valid() |
|||
{ |
|||
var command = new ChangeContentStatus { Status = Status.Published }; |
|||
|
|||
Assert.Throws<ValidationException>(() => GuardContent.CanChangeContentStatus(Status.Archived, command)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanChangeContentStatus_not_should_throw_exception_if_status_flow_valid() |
|||
{ |
|||
var command = new ChangeContentStatus { Status = Status.Published }; |
|||
|
|||
GuardContent.CanChangeContentStatus(Status.Draft, command); |
|||
} |
|||
|
|||
[Fact] |
|||
public void CanPatch_should_not_throw_exception() |
|||
{ |
|||
var command = new DeleteContent(); |
|||
|
|||
GuardContent.CanDelete(command); |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue