diff --git a/Squidex.sln.DotSettings b/Squidex.sln.DotSettings
index cf27c2d87..0e0d4202d 100644
--- a/Squidex.sln.DotSettings
+++ b/Squidex.sln.DotSettings
@@ -17,6 +17,7 @@
+
<?xml version="1.0" encoding="utf-16"?><Profile name="Header"><CSUpdateFileHeader>True</CSUpdateFileHeader></Profile>
<?xml version="1.0" encoding="utf-16"?><Profile name="Namespaces"><CSOptimizeUsings><OptimizeUsings>True</OptimizeUsings><EmbraceInRegion>False</EmbraceInRegion><RegionName></RegionName></CSOptimizeUsings><CSUpdateFileHeader>True</CSUpdateFileHeader></Profile>
<?xml version="1.0" encoding="utf-16"?><Profile name="Typescript"><JsInsertSemicolon>True</JsInsertSemicolon><FormatAttributeQuoteDescriptor>True</FormatAttributeQuoteDescriptor><CorrectVariableKindsDescriptor>True</CorrectVariableKindsDescriptor><VariablesToInnerScopesDescriptor>True</VariablesToInnerScopesDescriptor><StringToTemplatesDescriptor>True</StringToTemplatesDescriptor><RemoveRedundantQualifiersTs>True</RemoveRedundantQualifiersTs><OptimizeImportsTs>True</OptimizeImportsTs></Profile>
diff --git a/src/Squidex.Domain.Apps.Core.Model/Apps/AppClient.cs b/src/Squidex.Domain.Apps.Core.Model/Apps/AppClient.cs
index fe4fa0bc5..28e17d013 100644
--- a/src/Squidex.Domain.Apps.Core.Model/Apps/AppClient.cs
+++ b/src/Squidex.Domain.Apps.Core.Model/Apps/AppClient.cs
@@ -16,14 +16,30 @@ namespace Squidex.Domain.Apps.Core.Apps
private string name;
private AppClientPermission permission;
- public AppClient(string name, string secret)
+ public string Name
+ {
+ get { return name; }
+ }
+
+ public string Secret
+ {
+ get { return secret; }
+ }
+
+ public AppClientPermission Permission
+ {
+ get { return permission; }
+ }
+
+ public AppClient(string name, string secret, AppClientPermission permission)
{
Guard.NotNullOrEmpty(name, nameof(name));
Guard.NotNullOrEmpty(secret, nameof(secret));
+ Guard.Enum(permission, nameof(permission));
this.name = name;
-
this.secret = secret;
+ this.permission = permission;
}
public void Update(AppClientPermission newPermission)
diff --git a/src/Squidex.Domain.Apps.Core.Model/Apps/AppClients.cs b/src/Squidex.Domain.Apps.Core.Model/Apps/AppClients.cs
index 07001417f..a92de925b 100644
--- a/src/Squidex.Domain.Apps.Core.Model/Apps/AppClients.cs
+++ b/src/Squidex.Domain.Apps.Core.Model/Apps/AppClients.cs
@@ -6,32 +6,32 @@
// All rights reserved.
// ==========================================================================
-using System.Collections.Generic;
using Squidex.Infrastructure;
namespace Squidex.Domain.Apps.Core.Apps
{
- public class AppClients
+ public sealed class AppClients : DictionaryBase
{
- private readonly Dictionary clients = new Dictionary();
-
- public IReadOnlyDictionary Clients
+ public void Add(string id, AppClient client)
{
- get { return clients; }
+ Guard.NotNullOrEmpty(id, nameof(id));
+ Guard.NotNull(client, nameof(client));
+
+ Inner.Add(id, client);
}
public void Add(string id, string secret)
{
Guard.NotNullOrEmpty(id, nameof(id));
- clients.Add(id, new AppClient(secret, id));
+ Inner.Add(id, new AppClient(id, secret, AppClientPermission.Editor));
}
public void Revoke(string id)
{
Guard.NotNullOrEmpty(id, nameof(id));
- clients.Remove(id);
+ Inner.Remove(id);
}
}
}
diff --git a/src/Squidex.Domain.Apps.Core.Model/Apps/AppContributors.cs b/src/Squidex.Domain.Apps.Core.Model/Apps/AppContributors.cs
index 780ed8076..9c4ce924d 100644
--- a/src/Squidex.Domain.Apps.Core.Model/Apps/AppContributors.cs
+++ b/src/Squidex.Domain.Apps.Core.Model/Apps/AppContributors.cs
@@ -6,33 +6,25 @@
// All rights reserved.
// ==========================================================================
-using System.Collections.Generic;
using Squidex.Infrastructure;
namespace Squidex.Domain.Apps.Core.Apps
{
- public class AppContributors
+ public sealed class AppContributors : DictionaryBase
{
- private readonly Dictionary contributors = new Dictionary();
-
- public IReadOnlyDictionary Contributors
- {
- get { return contributors; }
- }
-
public void Assign(string contributorId, AppContributorPermission permission)
{
Guard.NotNullOrEmpty(contributorId, nameof(contributorId));
Guard.Enum(permission, nameof(permission));
- contributors[contributorId] = permission;
+ Inner[contributorId] = permission;
}
public void Remove(string contributorId)
{
Guard.NotNullOrEmpty(contributorId, nameof(contributorId));
- contributors.Remove(contributorId);
+ Inner.Remove(contributorId);
}
}
}
diff --git a/src/Squidex.Domain.Apps.Core.Model/Apps/Json/AppClientsConverter.cs b/src/Squidex.Domain.Apps.Core.Model/Apps/Json/AppClientsConverter.cs
new file mode 100644
index 000000000..908f78c08
--- /dev/null
+++ b/src/Squidex.Domain.Apps.Core.Model/Apps/Json/AppClientsConverter.cs
@@ -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(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>(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);
+ }
+ }
+}
diff --git a/src/Squidex.Domain.Apps.Core.Model/Apps/Json/AppContributorsConverter.cs b/src/Squidex.Domain.Apps.Core.Model/Apps/Json/AppContributorsConverter.cs
new file mode 100644
index 000000000..98c45ad6e
--- /dev/null
+++ b/src/Squidex.Domain.Apps.Core.Model/Apps/Json/AppContributorsConverter.cs
@@ -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(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>(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);
+ }
+ }
+}
diff --git a/src/Squidex.Domain.Apps.Core.Model/Apps/Json/JsonAppClient.cs b/src/Squidex.Domain.Apps.Core.Model/Apps/Json/JsonAppClient.cs
new file mode 100644
index 000000000..c3b11189e
--- /dev/null
+++ b/src/Squidex.Domain.Apps.Core.Model/Apps/Json/JsonAppClient.cs
@@ -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);
+ }
+ }
+}
diff --git a/src/Squidex.Domain.Apps.Core.Model/Apps/Json/JsonLanguageConfig.cs b/src/Squidex.Domain.Apps.Core.Model/Apps/Json/JsonLanguageConfig.cs
new file mode 100644
index 000000000..f85cb70d3
--- /dev/null
+++ b/src/Squidex.Domain.Apps.Core.Model/Apps/Json/JsonLanguageConfig.cs
@@ -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);
+ }
+ }
+}
diff --git a/src/Squidex.Domain.Apps.Core.Model/Apps/Json/LanguagesConfigConverter.cs b/src/Squidex.Domain.Apps.Core.Model/Apps/Json/LanguagesConfigConverter.cs
new file mode 100644
index 000000000..d1f5d6485
--- /dev/null
+++ b/src/Squidex.Domain.Apps.Core.Model/Apps/Json/LanguagesConfigConverter.cs
@@ -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(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>(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);
+ }
+ }
+}
diff --git a/src/Squidex.Domain.Apps.Core.Model/LanguageConfig.cs b/src/Squidex.Domain.Apps.Core.Model/Apps/LanguageConfig.cs
similarity index 97%
rename from src/Squidex.Domain.Apps.Core.Model/LanguageConfig.cs
rename to src/Squidex.Domain.Apps.Core.Model/Apps/LanguageConfig.cs
index 63fd8904f..b1d507067 100644
--- a/src/Squidex.Domain.Apps.Core.Model/LanguageConfig.cs
+++ b/src/Squidex.Domain.Apps.Core.Model/Apps/LanguageConfig.cs
@@ -10,7 +10,7 @@ using System.Collections.Generic;
using System.Linq;
using Squidex.Infrastructure;
-namespace Squidex.Domain.Apps.Core
+namespace Squidex.Domain.Apps.Core.Apps
{
public sealed class LanguageConfig : IFieldPartitionItem
{
diff --git a/src/Squidex.Domain.Apps.Core.Model/LanguagesConfig.cs b/src/Squidex.Domain.Apps.Core.Model/Apps/LanguagesConfig.cs
similarity index 90%
rename from src/Squidex.Domain.Apps.Core.Model/LanguagesConfig.cs
rename to src/Squidex.Domain.Apps.Core.Model/Apps/LanguagesConfig.cs
index c1d8fb2c8..8f0c6f1f9 100644
--- a/src/Squidex.Domain.Apps.Core.Model/LanguagesConfig.cs
+++ b/src/Squidex.Domain.Apps.Core.Model/Apps/LanguagesConfig.cs
@@ -13,7 +13,7 @@ using System.Collections.Immutable;
using System.Linq;
using Squidex.Infrastructure;
-namespace Squidex.Domain.Apps.Core
+namespace Squidex.Domain.Apps.Core.Apps
{
public sealed class LanguagesConfig : IFieldPartitioning
{
@@ -24,11 +24,6 @@ namespace Squidex.Domain.Apps.Core
get { return state.Master; }
}
- public int Count
- {
- get { return state.Languages.Count; }
- }
-
IFieldPartitionItem IFieldPartitioning.Master
{
get { return state.Master; }
@@ -44,6 +39,16 @@ namespace Squidex.Domain.Apps.Core
return state.Languages.Values.GetEnumerator();
}
+ public IEnumerable Configs
+ {
+ get { return state.Languages.Values; }
+ }
+
+ public int Count
+ {
+ get { return state.Languages.Count; }
+ }
+
private LanguagesConfig(ICollection configs)
{
Guard.NotNull(configs, nameof(configs));
@@ -83,7 +88,7 @@ namespace Squidex.Domain.Apps.Core
{
Guard.NotNull(language, nameof(language));
- state = new State(
+ var newLanguages =
state.Languages.Values.Where(x => x.Language != language)
.Select(config =>
{
@@ -92,7 +97,14 @@ namespace Squidex.Domain.Apps.Core
config.IsOptional,
config.LanguageFallbacks.Except(new[] { language }));
})
- .ToImmutableDictionary(x => x.Language), state.Master.Language == language ? null : state.Master);
+ .ToImmutableDictionary(x => x.Language);
+
+ var newMaster =
+ state.Master.Language != language ?
+ state.Master :
+ null;
+
+ state = new State(newLanguages, newMaster);
}
public bool Contains(Language language)
@@ -107,16 +119,18 @@ namespace Squidex.Domain.Apps.Core
public bool TryGetItem(string key, out IFieldPartitionItem item)
{
- item = null;
-
if (Language.IsValidLanguage(key) && state.Languages.TryGetValue(key, out var value))
{
item = value;
return true;
}
+ else
+ {
+ item = null;
- return false;
+ return false;
+ }
}
private sealed class State
diff --git a/src/Squidex.Domain.Apps.Core.Model/DictionaryBase.cs b/src/Squidex.Domain.Apps.Core.Model/DictionaryBase.cs
new file mode 100644
index 000000000..6b3734c6a
--- /dev/null
+++ b/src/Squidex.Domain.Apps.Core.Model/DictionaryBase.cs
@@ -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 : IReadOnlyDictionary
+ {
+ private readonly Dictionary inner = new Dictionary();
+
+ public TValue this[TKey key]
+ {
+ get { return inner[key]; }
+ }
+
+ public IEnumerable Keys
+ {
+ get { return inner.Keys; }
+ }
+
+ public IEnumerable Values
+ {
+ get { return inner.Values; }
+ }
+
+ public int Count
+ {
+ get { return inner.Count; }
+ }
+
+ protected Dictionary 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> IEnumerable>.GetEnumerator()
+ {
+ return inner.GetEnumerator();
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return inner.GetEnumerator();
+ }
+ }
+}
diff --git a/src/Squidex.Domain.Apps.Core.Model/Schemas/FieldProperties.cs b/src/Squidex.Domain.Apps.Core.Model/Schemas/FieldProperties.cs
index 334d5b59e..c975e4ef9 100644
--- a/src/Squidex.Domain.Apps.Core.Model/Schemas/FieldProperties.cs
+++ b/src/Squidex.Domain.Apps.Core.Model/Schemas/FieldProperties.cs
@@ -6,8 +6,6 @@
// All rights reserved.
// ==========================================================================
-using Newtonsoft.Json.Linq;
-
namespace Squidex.Domain.Apps.Core.Schemas
{
public abstract class FieldProperties : NamedElementPropertiesBase
diff --git a/src/Squidex.Domain.Apps.Core.Model/Schemas/NamedElementPropertiesBase.cs b/src/Squidex.Domain.Apps.Core.Model/Schemas/NamedElementPropertiesBase.cs
index dfcbba099..7f5a9d572 100644
--- a/src/Squidex.Domain.Apps.Core.Model/Schemas/NamedElementPropertiesBase.cs
+++ b/src/Squidex.Domain.Apps.Core.Model/Schemas/NamedElementPropertiesBase.cs
@@ -6,8 +6,6 @@
// All rights reserved.
// ==========================================================================
-using System;
-
namespace Squidex.Domain.Apps.Core.Schemas
{
public abstract class NamedElementPropertiesBase
diff --git a/src/Squidex.Domain.Apps.Core.Operations/ConvertContent/ContentConverter.cs b/src/Squidex.Domain.Apps.Core.Operations/ConvertContent/ContentConverter.cs
index 30edad325..87c986cb9 100644
--- a/src/Squidex.Domain.Apps.Core.Operations/ConvertContent/ContentConverter.cs
+++ b/src/Squidex.Domain.Apps.Core.Operations/ConvertContent/ContentConverter.cs
@@ -11,6 +11,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using Newtonsoft.Json.Linq;
+using Squidex.Domain.Apps.Core.Apps;
using Squidex.Domain.Apps.Core.Contents;
using Squidex.Domain.Apps.Core.Schemas;
using Squidex.Infrastructure;
diff --git a/src/Squidex.Domain.Apps.Core.Operations/EnrichContent/ContentEnricher.cs b/src/Squidex.Domain.Apps.Core.Operations/EnrichContent/ContentEnricher.cs
index 10f73cb5e..0aabe935c 100644
--- a/src/Squidex.Domain.Apps.Core.Operations/EnrichContent/ContentEnricher.cs
+++ b/src/Squidex.Domain.Apps.Core.Operations/EnrichContent/ContentEnricher.cs
@@ -6,7 +6,6 @@
// All rights reserved.
// ==========================================================================
-using System;
using Newtonsoft.Json.Linq;
using NodaTime;
using Squidex.Domain.Apps.Core.Contents;
diff --git a/src/Squidex.Domain.Apps.Core.Operations/EnrichContent/DefaultValueFactory.cs b/src/Squidex.Domain.Apps.Core.Operations/EnrichContent/DefaultValueFactory.cs
index d7529af47..0cbd275e2 100644
--- a/src/Squidex.Domain.Apps.Core.Operations/EnrichContent/DefaultValueFactory.cs
+++ b/src/Squidex.Domain.Apps.Core.Operations/EnrichContent/DefaultValueFactory.cs
@@ -6,7 +6,6 @@
// All rights reserved.
// ==========================================================================
-using System;
using Newtonsoft.Json.Linq;
using NodaTime;
using Squidex.Domain.Apps.Core.Schemas;
diff --git a/src/Squidex.Domain.Apps.Events/Apps/Utils/AppEventDispatcher.cs b/src/Squidex.Domain.Apps.Events/Apps/Utils/AppEventDispatcher.cs
index 7e4442977..54f09a5ef 100644
--- a/src/Squidex.Domain.Apps.Events/Apps/Utils/AppEventDispatcher.cs
+++ b/src/Squidex.Domain.Apps.Events/Apps/Utils/AppEventDispatcher.cs
@@ -6,7 +6,6 @@
// All rights reserved.
// ==========================================================================
-using Squidex.Domain.Apps.Core;
using Squidex.Domain.Apps.Core.Apps;
namespace Squidex.Domain.Apps.Events.Apps.Utils
@@ -45,7 +44,7 @@ namespace Squidex.Domain.Apps.Events.Apps.Utils
public static void Apply(this AppClients clients, AppClientRenamed @event)
{
- if (clients.Clients.TryGetValue(@event.Id, out var client))
+ if (clients.TryGetValue(@event.Id, out var client))
{
client.Rename(@event.Name);
}
@@ -53,7 +52,7 @@ namespace Squidex.Domain.Apps.Events.Apps.Utils
public static void Apply(this AppClients clients, AppClientUpdated @event)
{
- if (clients.Clients.TryGetValue(@event.Id, out var client))
+ if (clients.TryGetValue(@event.Id, out var client))
{
client.Update(@event.Permission);
}
diff --git a/src/Squidex.Domain.Apps.Read.MongoDb/Apps/MongoAppEntity.cs b/src/Squidex.Domain.Apps.Read.MongoDb/Apps/MongoAppEntity.cs
index 7810f2814..b7799d63a 100644
--- a/src/Squidex.Domain.Apps.Read.MongoDb/Apps/MongoAppEntity.cs
+++ b/src/Squidex.Domain.Apps.Read.MongoDb/Apps/MongoAppEntity.cs
@@ -39,17 +39,17 @@ namespace Squidex.Domain.Apps.Read.MongoDb.Apps
[BsonRequired]
[BsonElement]
- [BsonSerializer(typeof(JsonBsonSerializer))]
+ [BsonJson]
public AppClients Clients { get; set; } = new AppClients();
[BsonRequired]
[BsonElement]
- [BsonSerializer(typeof(JsonBsonSerializer))]
+ [BsonJson]
public AppContributors Contributors { get; set; } = new AppContributors();
[BsonRequired]
[BsonElement]
- [BsonSerializer(typeof(JsonBsonSerializer))]
+ [BsonJson]
public LanguagesConfig LanguagesConfig { get; } = LanguagesConfig.Build(Language.EN);
public PartitionResolver PartitionResolver
diff --git a/src/Squidex.Domain.Apps.Read.MongoDb/Apps/MongoAppRepository.cs b/src/Squidex.Domain.Apps.Read.MongoDb/Apps/MongoAppRepository.cs
index aabfa2ebd..c6f475e2e 100644
--- a/src/Squidex.Domain.Apps.Read.MongoDb/Apps/MongoAppRepository.cs
+++ b/src/Squidex.Domain.Apps.Read.MongoDb/Apps/MongoAppRepository.cs
@@ -10,9 +10,7 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
-using MongoDB.Bson.Serialization;
using MongoDB.Driver;
-using Newtonsoft.Json;
using Squidex.Domain.Apps.Read.Apps;
using Squidex.Domain.Apps.Read.Apps.Repositories;
using Squidex.Infrastructure.CQRS.Events;
@@ -22,10 +20,9 @@ namespace Squidex.Domain.Apps.Read.MongoDb.Apps
{
public partial class MongoAppRepository : MongoRepositoryBase, IAppRepository, IEventConsumer
{
- public MongoAppRepository(IMongoDatabase database, JsonSerializer serializer)
+ public MongoAppRepository(IMongoDatabase database)
: base(database)
{
- BsonSerializer.RegisterSerializer(new JsonBsonSerializer(serializer));
}
protected override string CollectionName()
diff --git a/src/Squidex.Domain.Apps.Read.MongoDb/Apps/MongoAppRepository_EventHandling.cs b/src/Squidex.Domain.Apps.Read.MongoDb/Apps/MongoAppRepository_EventHandling.cs
index d4d22106b..d70f8aebf 100644
--- a/src/Squidex.Domain.Apps.Read.MongoDb/Apps/MongoAppRepository_EventHandling.cs
+++ b/src/Squidex.Domain.Apps.Read.MongoDb/Apps/MongoAppRepository_EventHandling.cs
@@ -130,7 +130,7 @@ namespace Squidex.Domain.Apps.Read.MongoDb.Apps
{
updater(a);
- a.ContributorIds = a.Contributors.Contributors.Keys.ToArray();
+ a.ContributorIds = a.Contributors.Keys.ToArray();
});
}
}
diff --git a/src/Squidex.Domain.Apps.Read.MongoDb/Contents/Extensions.cs b/src/Squidex.Domain.Apps.Read.MongoDb/Contents/Extensions.cs
index bd8e91547..be7dcb916 100644
--- a/src/Squidex.Domain.Apps.Read.MongoDb/Contents/Extensions.cs
+++ b/src/Squidex.Domain.Apps.Read.MongoDb/Contents/Extensions.cs
@@ -10,14 +10,11 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
-using MongoDB.Bson;
-using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Squidex.Domain.Apps.Core.Contents;
using Squidex.Domain.Apps.Core.ConvertContent;
using Squidex.Domain.Apps.Core.ExtractReferenceIds;
using Squidex.Domain.Apps.Core.Schemas;
-using Squidex.Infrastructure.MongoDb;
namespace Squidex.Domain.Apps.Read.MongoDb.Contents
{
@@ -25,23 +22,14 @@ namespace Squidex.Domain.Apps.Read.MongoDb.Contents
{
private const int MaxLength = 1024 * 1024;
- public static BsonDocument ToBsonDocument(this IdContentData data, JsonSerializer jsonSerializer)
- {
- return (BsonDocument)JToken.FromObject(data, jsonSerializer).ToBson();
- }
-
public static List ToReferencedIds(this IdContentData data, Schema schema)
{
return data.GetReferencedIds(schema).ToList();
}
- public static NamedContentData ToData(this BsonDocument document, Schema schema, List deletedIds, JsonSerializer jsonSerializer)
+ public static NamedContentData ToData(this IdContentData idData, Schema schema, List deletedIds)
{
- return document
- .ToJson()
- .ToObject(jsonSerializer)
- .ToCleanedReferences(schema, new HashSet(deletedIds ?? new List()))
- .ToNameModel(schema, true);
+ return idData.ToCleanedReferences(schema, new HashSet(deletedIds)).ToNameModel(schema, true);
}
public static string ToFullText(this ContentData data)
diff --git a/src/Squidex.Domain.Apps.Read.MongoDb/Contents/MongoContentEntity.cs b/src/Squidex.Domain.Apps.Read.MongoDb/Contents/MongoContentEntity.cs
index 5ca934612..141e33e6f 100644
--- a/src/Squidex.Domain.Apps.Read.MongoDb/Contents/MongoContentEntity.cs
+++ b/src/Squidex.Domain.Apps.Read.MongoDb/Contents/MongoContentEntity.cs
@@ -10,7 +10,6 @@ using System;
using System.Collections.Generic;
using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes;
-using Newtonsoft.Json;
using NodaTime;
using Squidex.Domain.Apps.Core.Contents;
using Squidex.Domain.Apps.Core.Schemas;
@@ -66,10 +65,6 @@ namespace Squidex.Domain.Apps.Read.MongoDb.Contents
[BsonElement("mb")]
public RefToken LastModifiedBy { get; set; }
- [BsonRequired]
- [BsonElement("do")]
- public BsonDocument DataDocument { get; set; }
-
[BsonRequired]
[BsonElement("rf")]
public List ReferencedIds { get; set; }
@@ -78,14 +73,19 @@ namespace Squidex.Domain.Apps.Read.MongoDb.Contents
[BsonElement("rd")]
public List ReferencedIdsDeleted { get; set; } = new List();
+ [BsonRequired]
+ [BsonElement("do")]
+ [BsonJson]
+ public IdContentData IdData { get; set; }
+
NamedContentData IContentEntity.Data
{
get { return data; }
}
- public void ParseData(Schema schema, JsonSerializer serializer)
+ public void ParseData(Schema schema)
{
- data = DataDocument.ToData(schema, ReferencedIdsDeleted, serializer);
+ data = IdData.ToData(schema, ReferencedIdsDeleted);
}
}
}
diff --git a/src/Squidex.Domain.Apps.Read.MongoDb/Contents/MongoContentRepository.cs b/src/Squidex.Domain.Apps.Read.MongoDb/Contents/MongoContentRepository.cs
index 4f124278d..5ca896110 100644
--- a/src/Squidex.Domain.Apps.Read.MongoDb/Contents/MongoContentRepository.cs
+++ b/src/Squidex.Domain.Apps.Read.MongoDb/Contents/MongoContentRepository.cs
@@ -13,7 +13,6 @@ using System.Threading.Tasks;
using Microsoft.OData.UriParser;
using MongoDB.Bson;
using MongoDB.Driver;
-using Newtonsoft.Json;
using Squidex.Domain.Apps.Core.Contents;
using Squidex.Domain.Apps.Read.Apps;
using Squidex.Domain.Apps.Read.Contents;
@@ -31,7 +30,6 @@ namespace Squidex.Domain.Apps.Read.MongoDb.Contents
private const string Prefix = "Projections_Content_";
private readonly IMongoDatabase database;
private readonly ISchemaProvider schemas;
- private readonly JsonSerializer serializer;
protected static FilterDefinitionBuilder Filter
{
@@ -65,15 +63,13 @@ namespace Squidex.Domain.Apps.Read.MongoDb.Contents
}
}
- public MongoContentRepository(IMongoDatabase database, ISchemaProvider schemas, JsonSerializer serializer)
+ public MongoContentRepository(IMongoDatabase database, ISchemaProvider schemas)
{
Guard.NotNull(database, nameof(database));
Guard.NotNull(schemas, nameof(schemas));
- Guard.NotNull(serializer, nameof(serializer));
this.database = database;
this.schemas = schemas;
- this.serializer = serializer;
}
public async Task> QueryAsync(IAppEntity app, ISchemaEntity schema, Status[] status, ODataUriParser odataQuery)
@@ -103,7 +99,7 @@ namespace Squidex.Domain.Apps.Read.MongoDb.Contents
foreach (var entity in contentEntities)
{
- entity.ParseData(schema.SchemaDef, serializer);
+ entity.ParseData(schema.SchemaDef);
}
return contentEntities;
@@ -151,7 +147,7 @@ namespace Squidex.Domain.Apps.Read.MongoDb.Contents
foreach (var entity in contentEntities)
{
- entity.ParseData(schema.SchemaDef, serializer);
+ entity.ParseData(schema.SchemaDef);
}
return contentEntities.OfType().ToList();
@@ -176,7 +172,7 @@ namespace Squidex.Domain.Apps.Read.MongoDb.Contents
await collection.Find(x => x.Id == id)
.FirstOrDefaultAsync();
- contentEntity?.ParseData(schema.SchemaDef, serializer);
+ contentEntity?.ParseData(schema.SchemaDef);
return contentEntity;
}
diff --git a/src/Squidex.Domain.Apps.Read.MongoDb/Contents/MongoContentRepository_EventHandling.cs b/src/Squidex.Domain.Apps.Read.MongoDb/Contents/MongoContentRepository_EventHandling.cs
index 61900dd4f..b76240365 100644
--- a/src/Squidex.Domain.Apps.Read.MongoDb/Contents/MongoContentRepository_EventHandling.cs
+++ b/src/Squidex.Domain.Apps.Read.MongoDb/Contents/MongoContentRepository_EventHandling.cs
@@ -80,7 +80,7 @@ namespace Squidex.Domain.Apps.Read.MongoDb.Contents
var idData = @event.Data?.ToIdModel(schema.SchemaDef, true);
content.DataText = idData?.ToFullText();
- content.DataDocument = idData?.ToBsonDocument(serializer);
+ content.IdData = idData;
content.ReferencedIds = idData?.ToReferencedIds(schema.SchemaDef);
});
});
@@ -90,13 +90,13 @@ namespace Squidex.Domain.Apps.Read.MongoDb.Contents
{
return ForSchemaAsync(@event.AppId.Id, @event.SchemaId.Id, (collection, schema) =>
{
- var idData = @event.Data.ToIdModel(schema.SchemaDef, true);
+ var idData = @event.Data?.ToIdModel(schema.SchemaDef, true);
return collection.UpdateOneAsync(
Filter.Eq(x => x.Id, @event.ContentId),
Update
.Set(x => x.DataText, idData.ToFullText())
- .Set(x => x.DataDocument, idData.ToBsonDocument(serializer))
+ .Set(x => x.IdData, idData)
.Set(x => x.ReferencedIds, idData.ToReferencedIds(schema.SchemaDef))
.Set(x => x.LastModified, headers.Timestamp())
.Set(x => x.LastModifiedBy, @event.Actor)
diff --git a/src/Squidex.Domain.Apps.Read.MongoDb/Schemas/MongoSchemaEntity.cs b/src/Squidex.Domain.Apps.Read.MongoDb/Schemas/MongoSchemaEntity.cs
index bce8e652d..7efc0059b 100644
--- a/src/Squidex.Domain.Apps.Read.MongoDb/Schemas/MongoSchemaEntity.cs
+++ b/src/Squidex.Domain.Apps.Read.MongoDb/Schemas/MongoSchemaEntity.cs
@@ -68,7 +68,7 @@ namespace Squidex.Domain.Apps.Read.MongoDb.Schemas
[BsonRequired]
[BsonElement]
- [BsonSerializer(typeof(JsonBsonSerializer))]
+ [BsonJson]
public Schema SchemaDef { get; set; }
}
}
diff --git a/src/Squidex.Domain.Apps.Read.MongoDb/Schemas/MongoSchemaRepository.cs b/src/Squidex.Domain.Apps.Read.MongoDb/Schemas/MongoSchemaRepository.cs
index a4d8ac949..a43da664f 100644
--- a/src/Squidex.Domain.Apps.Read.MongoDb/Schemas/MongoSchemaRepository.cs
+++ b/src/Squidex.Domain.Apps.Read.MongoDb/Schemas/MongoSchemaRepository.cs
@@ -10,9 +10,7 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
-using MongoDB.Bson.Serialization;
using MongoDB.Driver;
-using Newtonsoft.Json;
using Squidex.Domain.Apps.Core.Schemas;
using Squidex.Domain.Apps.Read.Schemas;
using Squidex.Domain.Apps.Read.Schemas.Repositories;
@@ -26,14 +24,12 @@ namespace Squidex.Domain.Apps.Read.MongoDb.Schemas
{
private readonly FieldRegistry registry;
- public MongoSchemaRepository(IMongoDatabase database, JsonSerializer serializer, FieldRegistry registry)
+ public MongoSchemaRepository(IMongoDatabase database, FieldRegistry registry)
: base(database)
{
Guard.NotNull(registry, nameof(registry));
this.registry = registry;
-
- BsonSerializer.RegisterSerializer(new JsonBsonSerializer(serializer));
}
protected override string CollectionName()
diff --git a/src/Squidex.Domain.Apps.Read/Apps/IAppClientEntity.cs b/src/Squidex.Domain.Apps.Read/Apps/IAppClientEntity.cs
deleted file mode 100644
index 73cae6fba..000000000
--- a/src/Squidex.Domain.Apps.Read/Apps/IAppClientEntity.cs
+++ /dev/null
@@ -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; }
- }
-}
diff --git a/src/Squidex.Domain.Apps.Write/Apps/AppCommandMiddleware.cs b/src/Squidex.Domain.Apps.Write/Apps/AppCommandMiddleware.cs
index 327761d38..03f5957bd 100644
--- a/src/Squidex.Domain.Apps.Write/Apps/AppCommandMiddleware.cs
+++ b/src/Squidex.Domain.Apps.Write/Apps/AppCommandMiddleware.cs
@@ -58,11 +58,6 @@ namespace Squidex.Domain.Apps.Write.Apps
});
}
- protected Task On(AttachClient command, CommandContext context)
- {
- return handler.UpdateAsync(context, a => a.AttachClient(command));
- }
-
protected async Task On(AssignContributor command, CommandContext context)
{
await handler.UpdateAsync(context, async a =>
@@ -83,14 +78,34 @@ namespace Squidex.Domain.Apps.Write.Apps
});
}
+ protected Task On(AttachClient command, CommandContext context)
+ {
+ return handler.UpdateAsync(context, a =>
+ {
+ GuardAppClients.CanAttach(a.Clients, command);
+
+ a.AttachClient(command);
+ });
+ }
+
protected Task On(UpdateClient command, CommandContext context)
{
- return handler.UpdateAsync(context, a => a.UpdateClient(command));
+ return handler.UpdateAsync(context, a =>
+ {
+ GuardAppClients.CanUpdate(a.Clients, command);
+
+ a.UpdateClient(command);
+ });
}
protected Task On(RevokeClient command, CommandContext context)
{
- return handler.UpdateAsync(context, a => a.RevokeClient(command));
+ return handler.UpdateAsync(context, a =>
+ {
+ GuardAppClients.CanRevoke(a.Clients, command);
+
+ a.RevokeClient(command);
+ });
}
protected Task On(AddLanguage command, CommandContext context)
diff --git a/src/Squidex.Domain.Apps.Write/Apps/AppDomainObject.cs b/src/Squidex.Domain.Apps.Write/Apps/AppDomainObject.cs
index ac265d97e..d891c619a 100644
--- a/src/Squidex.Domain.Apps.Write/Apps/AppDomainObject.cs
+++ b/src/Squidex.Domain.Apps.Write/Apps/AppDomainObject.cs
@@ -7,7 +7,6 @@
// ==========================================================================
using System;
-using Squidex.Domain.Apps.Core;
using Squidex.Domain.Apps.Core.Apps;
using Squidex.Domain.Apps.Events;
using Squidex.Domain.Apps.Events.Apps;
diff --git a/src/Squidex.Domain.Apps.Write/Apps/Commands/ChangePlan.cs b/src/Squidex.Domain.Apps.Write/Apps/Commands/ChangePlan.cs
index a15d68fb9..4d84ee36c 100644
--- a/src/Squidex.Domain.Apps.Write/Apps/Commands/ChangePlan.cs
+++ b/src/Squidex.Domain.Apps.Write/Apps/Commands/ChangePlan.cs
@@ -6,8 +6,6 @@
// All rights reserved.
// ==========================================================================
-using Squidex.Infrastructure;
-
namespace Squidex.Domain.Apps.Write.Apps.Commands
{
public sealed class ChangePlan : AppAggregateCommand
diff --git a/src/Squidex.Domain.Apps.Write/Apps/Guards/GuardAppClients.cs b/src/Squidex.Domain.Apps.Write/Apps/Guards/GuardAppClients.cs
new file mode 100644
index 000000000..3a19fe5ea
--- /dev/null
+++ b/src/Squidex.Domain.Apps.Write/Apps/Guards/GuardAppClients.cs
@@ -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;
+ }
+ }
+}
diff --git a/src/Squidex.Domain.Apps.Write/Apps/Guards/GuardAppContributors.cs b/src/Squidex.Domain.Apps.Write/Apps/Guards/GuardAppContributors.cs
index daee2032b..64ecb94f1 100644
--- a/src/Squidex.Domain.Apps.Write/Apps/Guards/GuardAppContributors.cs
+++ b/src/Squidex.Domain.Apps.Write/Apps/Guards/GuardAppContributors.cs
@@ -39,14 +39,14 @@ namespace Squidex.Domain.Apps.Write.Apps.Guards
{
error(new ValidationError("Cannot find contributor id.", nameof(command.ContributorId)));
}
- else if (contributors.Contributors.TryGetValue(command.ContributorId, out var existing))
+ else if (contributors.TryGetValue(command.ContributorId, out var existing))
{
if (existing == command.Permission)
{
error(new ValidationError("Contributor has already this permission.", nameof(command.Permission)));
}
}
- else if (plan.MaxContributors == contributors.Contributors.Count)
+ else if (plan.MaxContributors == contributors.Count)
{
error(new ValidationError("You have reached the maximum number of contributors for your plan."));
}
@@ -65,7 +65,7 @@ namespace Squidex.Domain.Apps.Write.Apps.Guards
error(new ValidationError("Contributor id not assigned.", nameof(command.ContributorId)));
}
- var ownerIds = contributors.Contributors.Where(x => x.Value == AppContributorPermission.Owner).Select(x => x.Key).ToList();
+ var ownerIds = contributors.Where(x => x.Value == AppContributorPermission.Owner).Select(x => x.Key).ToList();
if (ownerIds.Count == 1 && ownerIds.Contains(command.ContributorId))
{
@@ -73,7 +73,7 @@ namespace Squidex.Domain.Apps.Write.Apps.Guards
}
});
- if (!contributors.Contributors.ContainsKey(command.ContributorId))
+ if (!contributors.ContainsKey(command.ContributorId))
{
throw new DomainObjectNotFoundException(command.ContributorId, "Contributors", typeof(AppDomainObject));
}
diff --git a/src/Squidex.Domain.Apps.Write/Apps/Guards/GuardAppLanguages.cs b/src/Squidex.Domain.Apps.Write/Apps/Guards/GuardAppLanguages.cs
index a65e5d05b..1ac39c4b2 100644
--- a/src/Squidex.Domain.Apps.Write/Apps/Guards/GuardAppLanguages.cs
+++ b/src/Squidex.Domain.Apps.Write/Apps/Guards/GuardAppLanguages.cs
@@ -6,7 +6,7 @@
// All rights reserved.
// ==========================================================================
-using Squidex.Domain.Apps.Core;
+using Squidex.Domain.Apps.Core.Apps;
using Squidex.Domain.Apps.Write.Apps.Commands;
using Squidex.Infrastructure;
@@ -39,6 +39,11 @@ namespace Squidex.Domain.Apps.Write.Apps.Guards
Validate.It(() => "Cannot remove language.", error =>
{
+ if (command.Language == null)
+ {
+ error(new ValidationError("Language cannot be null.", nameof(command.Language)));
+ }
+
if (languages.Master == languageConfig)
{
error(new ValidationError("Language config is master.", nameof(command.Language)));
@@ -54,6 +59,11 @@ namespace Squidex.Domain.Apps.Write.Apps.Guards
Validate.It(() => "Cannot update language.", error =>
{
+ if (command.Language == null)
+ {
+ error(new ValidationError("Language cannot be null.", nameof(command.Language)));
+ }
+
if ((languages.Master == languageConfig || command.IsMaster) && command.IsOptional)
{
error(new ValidationError("Cannot make master language optional.", nameof(command.IsMaster)));
@@ -76,7 +86,7 @@ namespace Squidex.Domain.Apps.Write.Apps.Guards
{
if (language == null)
{
- throw new DomainObjectNotFoundException(language, "Languages", typeof(AppDomainObject));
+ return null;
}
if (!languages.TryGetConfig(language, out var languageConfig))
diff --git a/src/Squidex.Domain.Apps.Write/Contents/Commands/PatchContent.cs b/src/Squidex.Domain.Apps.Write/Contents/Commands/PatchContent.cs
index 410315879..ff38a5638 100644
--- a/src/Squidex.Domain.Apps.Write/Contents/Commands/PatchContent.cs
+++ b/src/Squidex.Domain.Apps.Write/Contents/Commands/PatchContent.cs
@@ -6,8 +6,6 @@
// All rights reserved.
// ==========================================================================
-using Squidex.Domain.Apps.Core.Contents;
-
namespace Squidex.Domain.Apps.Write.Contents.Commands
{
public sealed class PatchContent : ContentDataCommand
diff --git a/src/Squidex.Domain.Apps.Write/Contents/Commands/UpdateContent.cs b/src/Squidex.Domain.Apps.Write/Contents/Commands/UpdateContent.cs
index 47d6128ad..be9546173 100644
--- a/src/Squidex.Domain.Apps.Write/Contents/Commands/UpdateContent.cs
+++ b/src/Squidex.Domain.Apps.Write/Contents/Commands/UpdateContent.cs
@@ -6,8 +6,6 @@
// All rights reserved.
// ==========================================================================
-using Squidex.Domain.Apps.Core.Contents;
-
namespace Squidex.Domain.Apps.Write.Contents.Commands
{
public sealed class UpdateContent : ContentDataCommand
diff --git a/src/Squidex.Domain.Apps.Write/Contents/ContentCommandMiddleware.cs b/src/Squidex.Domain.Apps.Write/Contents/ContentCommandMiddleware.cs
index 810eb7b8e..d64143b2f 100644
--- a/src/Squidex.Domain.Apps.Write/Contents/ContentCommandMiddleware.cs
+++ b/src/Squidex.Domain.Apps.Write/Contents/ContentCommandMiddleware.cs
@@ -7,19 +7,14 @@
// ==========================================================================
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.Domain.Apps.Write.Contents.Guards;
using Squidex.Infrastructure;
using Squidex.Infrastructure.CQRS.Commands;
using Squidex.Infrastructure.Dispatching;
@@ -62,18 +57,18 @@ namespace Squidex.Domain.Apps.Write.Contents
{
await handler.CreateAsync(context, async content =>
{
- var schemaAndApp = await ResolveSchemaAndAppAsync(command);
+ GuardContent.CanCreate(command);
- ExecuteScriptAndTransform(command, content, schemaAndApp.SchemaEntity.ScriptCreate, "Create");
+ var operationContext = await CreateContext(command, content, () => "Failed to create content.");
if (command.Publish)
{
- ExecuteScript(command, content, schemaAndApp.SchemaEntity.ScriptChange, "Published");
+ await operationContext.ExecuteScriptAsync(x => x.ScriptChange, "Published");
}
- command.Data.Enrich(schemaAndApp.SchemaEntity.SchemaDef, schemaAndApp.AppEntity.PartitionResolver);
-
- await ValidateAsync(schemaAndApp, command, () => "Failed to create content", false);
+ await operationContext.ExecuteScriptAndTransformAsync(x => x.ScriptCreate, "Create");
+ await operationContext.EnrichAsync();
+ await operationContext.ValidateAsync(false);
content.Create(command);
@@ -85,11 +80,12 @@ namespace Squidex.Domain.Apps.Write.Contents
{
await handler.UpdateAsync(context, async content =>
{
- var schemaAndApp = await ResolveSchemaAndAppAsync(command);
+ GuardContent.CanUpdate(command);
- ExecuteScriptAndTransform(command, content, schemaAndApp.SchemaEntity.ScriptUpdate, "Update");
+ var operationContext = await CreateContext(command, content, () => "Failed to update content.");
- await ValidateAsync(schemaAndApp, command, () => "Failed to update content", false);
+ await operationContext.ValidateAsync(true);
+ await operationContext.ExecuteScriptAndTransformAsync(x => x.ScriptUpdate, "Update");
content.Update(command);
@@ -101,11 +97,12 @@ namespace Squidex.Domain.Apps.Write.Contents
{
await handler.UpdateAsync(context, async content =>
{
- var schemaAndApp = await ResolveSchemaAndAppAsync(command);
+ GuardContent.CanPatch(command);
- ExecuteScriptAndTransform(command, content, schemaAndApp.SchemaEntity.ScriptUpdate, "Patch");
+ var operationContext = await CreateContext(command, content, () => "Failed to patch content.");
- await ValidateAsync(schemaAndApp, command, () => "Failed to patch content", true);
+ await operationContext.ValidateAsync(true);
+ await operationContext.ExecuteScriptAndTransformAsync(x => x.ScriptUpdate, "Patch");
content.Patch(command);
@@ -117,9 +114,11 @@ namespace Squidex.Domain.Apps.Write.Contents
{
return handler.UpdateAsync(context, async content =>
{
- var schemaAndApp = await ResolveSchemaAndAppAsync(command);
+ GuardContent.CanChangeContentStatus(content.Status, command);
+
+ var operationContext = await CreateContext(command, content, () => "Failed to patch content.");
- ExecuteScript(command, content, schemaAndApp.SchemaEntity.ScriptChange, command.Status);
+ await operationContext.ExecuteScriptAsync(x => x.ScriptChange, command.Status);
content.ChangeStatus(command);
});
@@ -129,9 +128,11 @@ namespace Squidex.Domain.Apps.Write.Contents
{
return handler.UpdateAsync(context, async content =>
{
- var schemaAndApp = await ResolveSchemaAndAppAsync(command);
+ GuardContent.CanDelete(command);
+
+ var operationContext = await CreateContext(command, content, () => "Failed to delete content.");
- ExecuteScript(command, content, schemaAndApp.SchemaEntity.ScriptDelete, "Delete");
+ await operationContext.ExecuteScriptAsync(x => x.ScriptDelete, "Delete");
content.Delete(command);
});
@@ -145,60 +146,20 @@ namespace Squidex.Domain.Apps.Write.Contents
}
}
- private async Task ValidateAsync((ISchemaEntity Schema, IAppEntity App) schemaAndApp, ContentDataCommand command, Func message, bool partial)
+ private async Task CreateContext(ContentCommand command, ContentDomainObject content, Func message)
{
- var schemaErrors = new List();
-
- var appId = command.AppId.Id;
-
- var validationContext =
- new ValidationContext(
- (contentIds, schemaId) =>
- {
- return contentRepository.QueryNotFoundAsync(appId, schemaId, contentIds.ToList());
- },
- assetIds =>
- {
- return assetRepository.QueryNotFoundAsync(appId, assetIds.ToList());
- });
-
- if (partial)
- {
- await command.Data.ValidatePartialAsync(validationContext, schemaAndApp.Schema.SchemaDef, schemaAndApp.App.PartitionResolver, schemaErrors);
- }
- else
- {
- await command.Data.ValidateAsync(validationContext, schemaAndApp.Schema.SchemaDef, schemaAndApp.App.PartitionResolver, schemaErrors);
- }
-
- if (schemaErrors.Count > 0)
- {
- throw new ValidationException(message(), schemaErrors);
- }
- }
-
- private void ExecuteScriptAndTransform(ContentDataCommand command, ContentDomainObject content, string script, object operation)
- {
- var ctx = new ScriptContext { ContentId = content.Id, OldData = content.Data, User = command.User, Operation = operation.ToString(), Data = command.Data };
-
- command.Data = scriptEngine.ExecuteAndTransform(ctx, script);
- }
-
- private void ExecuteScript(ContentCommand command, ContentDomainObject content, string script, object operation)
- {
- var ctx = new ScriptContext { ContentId = content.Id, OldData = content.Data, User = command.User, Operation = operation.ToString() };
-
- scriptEngine.Execute(ctx, script);
- }
-
- private async Task<(ISchemaEntity SchemaEntity, IAppEntity AppEntity)> ResolveSchemaAndAppAsync(SchemaCommand command)
- {
- var taskForApp = appProvider.FindAppByIdAsync(command.AppId.Id);
- var taskForSchema = schemas.FindSchemaByIdAsync(command.SchemaId.Id);
-
- await Task.WhenAll(taskForApp, taskForSchema);
-
- return (taskForSchema.Result, taskForApp.Result);
+ var operationContext =
+ await ContentOperationContext.CreateAsync(
+ contentRepository,
+ content,
+ command,
+ appProvider,
+ schemas,
+ scriptEngine,
+ assetRepository,
+ message);
+
+ return operationContext;
}
}
}
diff --git a/src/Squidex.Domain.Apps.Write/Contents/ContentOperationContext.cs b/src/Squidex.Domain.Apps.Write/Contents/ContentOperationContext.cs
new file mode 100644
index 000000000..72a4ad097
--- /dev/null
+++ b/src/Squidex.Domain.Apps.Write/Contents/ContentOperationContext.cs
@@ -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 message;
+
+ public static async Task CreateAsync(
+ IContentRepository contentRepository,
+ ContentDomainObject content,
+ ContentCommand command,
+ IAppProvider appProvider,
+ ISchemaProvider schemas,
+ IScriptEngine scriptEngine,
+ IAssetRepository assetRepository,
+ Func 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();
+
+ 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 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 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;
+ }
+ }
+}
diff --git a/src/Squidex.Domain.Apps.Write/Contents/Guards/GuardContent.cs b/src/Squidex.Domain.Apps.Write/Contents/Guards/GuardContent.cs
index 28b7736ce..06178cdb1 100644
--- a/src/Squidex.Domain.Apps.Write/Contents/Guards/GuardContent.cs
+++ b/src/Squidex.Domain.Apps.Write/Contents/Guards/GuardContent.cs
@@ -27,7 +27,7 @@ namespace Squidex.Domain.Apps.Write.Contents.Guards
});
}
- public static void CanCreate(UpdateContent command)
+ public static void CanUpdate(UpdateContent command)
{
Guard.NotNull(command, nameof(command));
@@ -40,7 +40,7 @@ namespace Squidex.Domain.Apps.Write.Contents.Guards
});
}
- public static void CanCreate(PatchContent command)
+ public static void CanPatch(PatchContent command)
{
Guard.NotNull(command, nameof(command));
@@ -53,7 +53,7 @@ namespace Squidex.Domain.Apps.Write.Contents.Guards
});
}
- public static void CanChangeStatus(Status status, ChangeContentStatus command)
+ public static void CanChangeContentStatus(Status status, ChangeContentStatus command)
{
Guard.NotNull(command, nameof(command));
@@ -65,5 +65,10 @@ namespace Squidex.Domain.Apps.Write.Contents.Guards
}
});
}
+
+ public static void CanDelete(DeleteContent command)
+ {
+ Guard.NotNull(command, nameof(command));
+ }
}
}
diff --git a/src/Squidex.Domain.Apps.Write/Schemas/Guards/GuardSchema.cs b/src/Squidex.Domain.Apps.Write/Schemas/Guards/GuardSchema.cs
index ed0e69533..6502794b5 100644
--- a/src/Squidex.Domain.Apps.Write/Schemas/Guards/GuardSchema.cs
+++ b/src/Squidex.Domain.Apps.Write/Schemas/Guards/GuardSchema.cs
@@ -6,7 +6,6 @@
// All rights reserved.
// ==========================================================================
-using System;
using System.Linq;
using System.Threading.Tasks;
using Squidex.Domain.Apps.Core;
diff --git a/src/Squidex.Domain.Users/UserClaimsPrincipalFactoryWithEmail.cs b/src/Squidex.Domain.Users/UserClaimsPrincipalFactoryWithEmail.cs
index a18f6c9ee..a2a78ef90 100644
--- a/src/Squidex.Domain.Users/UserClaimsPrincipalFactoryWithEmail.cs
+++ b/src/Squidex.Domain.Users/UserClaimsPrincipalFactoryWithEmail.cs
@@ -9,7 +9,6 @@
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
-using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Options;
using Squidex.Infrastructure.Security;
diff --git a/src/Squidex.Domain.Apps.Read/Apps/IAppContributorEntity.cs b/src/Squidex.Infrastructure.MongoDb/MongoDb/BsonJsonAttribute.cs
similarity index 62%
rename from src/Squidex.Domain.Apps.Read/Apps/IAppContributorEntity.cs
rename to src/Squidex.Infrastructure.MongoDb/MongoDb/BsonJsonAttribute.cs
index 15a6ad8bc..807a46627 100644
--- a/src/Squidex.Domain.Apps.Read/Apps/IAppContributorEntity.cs
+++ b/src/Squidex.Infrastructure.MongoDb/MongoDb/BsonJsonAttribute.cs
@@ -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; }
}
}
diff --git a/src/Squidex.Infrastructure.MongoDb/MongoDb/BsonJsonConvention.cs b/src/Squidex.Infrastructure.MongoDb/MongoDb/BsonJsonConvention.cs
new file mode 100644
index 000000000..e6b485f82
--- /dev/null
+++ b/src/Squidex.Infrastructure.MongoDb/MongoDb/BsonJsonConvention.cs
@@ -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().Any())
+ {
+ memberMap.SetSerializer(bsonSerializer);
+ }
+ });
+
+ ConventionRegistry.Register("json", pack, t => true);
+ }
+ }
+}
diff --git a/src/Squidex.Infrastructure/CollectionExtensions.cs b/src/Squidex.Infrastructure/CollectionExtensions.cs
index 845f523bb..da9268948 100644
--- a/src/Squidex.Infrastructure/CollectionExtensions.cs
+++ b/src/Squidex.Infrastructure/CollectionExtensions.cs
@@ -14,6 +14,22 @@ namespace Squidex.Infrastructure
{
public static class CollectionExtensions
{
+ public static bool TryGetValue(this IReadOnlyDictionary values, TKey key, out TBase item) where TValue : TBase
+ {
+ if (values.TryGetValue(key, out var value))
+ {
+ item = value;
+
+ return true;
+ }
+ else
+ {
+ item = default(TBase);
+
+ return false;
+ }
+ }
+
public static int SequentialHashCode(this IEnumerable collection)
{
return collection.SequentialHashCode(EqualityComparer.Default);
diff --git a/src/Squidex.Infrastructure/DictionaryWrapper.cs b/src/Squidex.Infrastructure/DictionaryWrapper.cs
deleted file mode 100644
index 609406085..000000000
--- a/src/Squidex.Infrastructure/DictionaryWrapper.cs
+++ /dev/null
@@ -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 : IReadOnlyDictionary where TSuper : class, TValue where TValue : class
- {
- private readonly Func> inner;
-
- public DictionaryWrapper(Func> inner)
- {
- Guard.NotNull(inner, nameof(inner));
-
- this.inner = inner;
- }
-
- public IEnumerable Keys
- {
- get { return inner().Keys; }
- }
-
- public IEnumerable Values
- {
- get { return inner().Values.OfType(); }
- }
-
- 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> GetEnumerator()
- {
- return Enumerate().GetEnumerator();
- }
-
- IEnumerator IEnumerable.GetEnumerator()
- {
- return GetEnumerator();
- }
-
- private IEnumerable> Enumerate()
- {
- foreach (var kvp in inner())
- {
- yield return new KeyValuePair(kvp.Key, (TValue)kvp.Value);
- }
- }
- }
-}
\ No newline at end of file
diff --git a/src/Squidex/Config/Domain/Serializers.cs b/src/Squidex/Config/Domain/Serializers.cs
index 185a1c3a2..9ab3b0040 100644
--- a/src/Squidex/Config/Domain/Serializers.cs
+++ b/src/Squidex/Config/Domain/Serializers.cs
@@ -12,12 +12,14 @@ using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using NodaTime;
using NodaTime.Serialization.JsonNet;
+using Squidex.Domain.Apps.Core.Apps.Json;
using Squidex.Domain.Apps.Core.Schemas;
using Squidex.Domain.Apps.Core.Schemas.Json;
using Squidex.Domain.Apps.Events;
using Squidex.Infrastructure;
using Squidex.Infrastructure.CQRS.Events;
using Squidex.Infrastructure.Json;
+using Squidex.Infrastructure.MongoDb;
namespace Squidex.Config.Domain
{
@@ -32,8 +34,11 @@ namespace Squidex.Config.Domain
settings.SerializationBinder = new TypeNameSerializationBinder(TypeNameRegistry);
settings.ContractResolver = new ConverterContractResolver(
+ new AppClientsConverter(),
+ new AppContributorsConverter(),
new InstantConverter(),
new LanguageConverter(),
+ new LanguagesConfigConverter(),
new NamedGuidIdConverter(),
new NamedLongIdConverter(),
new NamedStringIdConverter(),
@@ -59,6 +64,8 @@ namespace Squidex.Config.Domain
TypeNameRegistry.Map(typeof(SquidexEvent).GetTypeInfo().Assembly);
TypeNameRegistry.Map(typeof(NoopEvent).GetTypeInfo().Assembly);
+ BsonJsonConvention.Register(JsonSerializer.Create(SerializerSettings));
+
ConfigureJson(SerializerSettings, TypeNameHandling.Auto);
}
diff --git a/src/Squidex/Config/Identity/LazyClientStore.cs b/src/Squidex/Config/Identity/LazyClientStore.cs
index b60f4688e..2fb3a33ca 100644
--- a/src/Squidex/Config/Identity/LazyClientStore.cs
+++ b/src/Squidex/Config/Identity/LazyClientStore.cs
@@ -13,7 +13,7 @@ using IdentityServer4;
using IdentityServer4.Models;
using IdentityServer4.Stores;
using Microsoft.Extensions.Options;
-using Squidex.Domain.Apps.Read.Apps;
+using Squidex.Domain.Apps.Core.Apps;
using Squidex.Domain.Apps.Read.Apps.Services;
using Squidex.Infrastructure;
@@ -64,7 +64,7 @@ namespace Squidex.Config.Identity
return client;
}
- private static Client CreateClientFromApp(string id, IAppClientEntity appClient)
+ private static Client CreateClientFromApp(string id, AppClient appClient)
{
return new Client
{
diff --git a/src/Squidex/Controllers/Api/Apps/AppContributorsController.cs b/src/Squidex/Controllers/Api/Apps/AppContributorsController.cs
index cc14ca983..b6acd8d12 100644
--- a/src/Squidex/Controllers/Api/Apps/AppContributorsController.cs
+++ b/src/Squidex/Controllers/Api/Apps/AppContributorsController.cs
@@ -52,7 +52,7 @@ namespace Squidex.Controllers.Api.Apps
[ApiCosts(1)]
public IActionResult GetContributors(string app)
{
- var contributors = App.Contributors.Select(x => SimpleMapper.Map(x.Value, new ContributorDto { ContributorId = x.Key })).ToArray();
+ var contributors = App.Contributors.Select(x => new ContributorDto { ContributorId = x.Key, Permission = x.Value }).ToArray();
var response = new ContributorsDto { Contributors = contributors, MaxContributors = appPlansProvider.GetPlanForApp(App).MaxContributors };
diff --git a/src/Squidex/Controllers/Api/Apps/AppLanguagesController.cs b/src/Squidex/Controllers/Api/Apps/AppLanguagesController.cs
index fcb38bc72..4d0ee698a 100644
--- a/src/Squidex/Controllers/Api/Apps/AppLanguagesController.cs
+++ b/src/Squidex/Controllers/Api/Apps/AppLanguagesController.cs
@@ -14,7 +14,7 @@ using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Primitives;
using NSwag.Annotations;
using Squidex.Controllers.Api.Apps.Models;
-using Squidex.Domain.Apps.Core;
+using Squidex.Domain.Apps.Core.Apps;
using Squidex.Domain.Apps.Write.Apps.Commands;
using Squidex.Infrastructure;
using Squidex.Infrastructure.CQRS.Commands;
diff --git a/src/Squidex/Controllers/Api/Apps/AppsController.cs b/src/Squidex/Controllers/Api/Apps/AppsController.cs
index e1a39b542..dbb119dbd 100644
--- a/src/Squidex/Controllers/Api/Apps/AppsController.cs
+++ b/src/Squidex/Controllers/Api/Apps/AppsController.cs
@@ -61,7 +61,7 @@ namespace Squidex.Controllers.Api.Apps
{
var dto = SimpleMapper.Map(s, new AppDto());
- dto.Permission = s.Contributors[subject].Permission;
+ dto.Permission = s.Contributors[subject];
return dto;
}).ToList();
diff --git a/src/Squidex/Controllers/Api/Schemas/Models/NumberFieldPropertiesDto.cs b/src/Squidex/Controllers/Api/Schemas/Models/NumberFieldPropertiesDto.cs
index a45904268..3bd914770 100644
--- a/src/Squidex/Controllers/Api/Schemas/Models/NumberFieldPropertiesDto.cs
+++ b/src/Squidex/Controllers/Api/Schemas/Models/NumberFieldPropertiesDto.cs
@@ -6,7 +6,6 @@
// All rights reserved.
// ==========================================================================
-using System.Collections.Immutable;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using NJsonSchema.Annotations;
@@ -48,11 +47,6 @@ namespace Squidex.Controllers.Api.Schemas.Models
{
var result = SimpleMapper.Map(this, new NumberFieldProperties());
- if (AllowedValues != null)
- {
- result.AllowedValues = ImmutableList.Create(AllowedValues);
- }
-
return result;
}
}
diff --git a/src/Squidex/Controllers/Api/Schemas/Models/StringFieldPropertiesDto.cs b/src/Squidex/Controllers/Api/Schemas/Models/StringFieldPropertiesDto.cs
index c36674309..32a3e00da 100644
--- a/src/Squidex/Controllers/Api/Schemas/Models/StringFieldPropertiesDto.cs
+++ b/src/Squidex/Controllers/Api/Schemas/Models/StringFieldPropertiesDto.cs
@@ -6,7 +6,6 @@
// All rights reserved.
// ==========================================================================
-using System.Collections.Immutable;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using NJsonSchema.Annotations;
@@ -58,11 +57,6 @@ namespace Squidex.Controllers.Api.Schemas.Models
{
var result = SimpleMapper.Map(this, new StringFieldProperties());
- if (AllowedValues != null)
- {
- result.AllowedValues = ImmutableList.Create(AllowedValues);
- }
-
return result;
}
}
diff --git a/src/Squidex/Controllers/ContentApi/ContentsController.cs b/src/Squidex/Controllers/ContentApi/ContentsController.cs
index edb868f80..763a7c6fb 100644
--- a/src/Squidex/Controllers/ContentApi/ContentsController.cs
+++ b/src/Squidex/Controllers/ContentApi/ContentsController.cs
@@ -15,6 +15,7 @@ using Microsoft.Extensions.Primitives;
using NSwag.Annotations;
using Squidex.Controllers.ContentApi.Models;
using Squidex.Domain.Apps.Core.Contents;
+using Squidex.Domain.Apps.Core.ConvertContent;
using Squidex.Domain.Apps.Read.Contents;
using Squidex.Domain.Apps.Read.Contents.GraphQL;
using Squidex.Domain.Apps.Write.Contents;
diff --git a/src/Squidex/Controllers/ContentApi/Generator/SchemaSwaggerGenerator.cs b/src/Squidex/Controllers/ContentApi/Generator/SchemaSwaggerGenerator.cs
index 094b7c335..82840cb94 100644
--- a/src/Squidex/Controllers/ContentApi/Generator/SchemaSwaggerGenerator.cs
+++ b/src/Squidex/Controllers/ContentApi/Generator/SchemaSwaggerGenerator.cs
@@ -13,8 +13,8 @@ using NJsonSchema;
using NSwag;
using Squidex.Config;
using Squidex.Domain.Apps.Core;
+using Squidex.Domain.Apps.Core.GenerateJsonSchema;
using Squidex.Domain.Apps.Core.Schemas;
-using Squidex.Domain.Apps.Core.Schemas.JsonSchema;
using Squidex.Infrastructure;
using Squidex.Pipeline.Swagger;
using Squidex.Shared.Identity;
diff --git a/src/Squidex/Pipeline/AppPermissionAttribute.cs b/src/Squidex/Pipeline/AppPermissionAttribute.cs
index 5abfbf000..82517dd38 100644
--- a/src/Squidex/Pipeline/AppPermissionAttribute.cs
+++ b/src/Squidex/Pipeline/AppPermissionAttribute.cs
@@ -96,9 +96,9 @@ namespace Squidex.Pipeline
{
var subjectId = user.FindFirst(OpenIdClaims.Subject)?.Value;
- if (subjectId != null && app.Contributors.TryGetValue(subjectId, out var contributor))
+ if (subjectId != null && app.Contributors.TryGetValue(subjectId, out var permission))
{
- return contributor.Permission.ToAppPermission();
+ return permission.ToAppPermission();
}
return null;
diff --git a/src/Squidex/Squidex.csproj b/src/Squidex/Squidex.csproj
index d7f56a3ee..a7ffd5aa4 100644
--- a/src/Squidex/Squidex.csproj
+++ b/src/Squidex/Squidex.csproj
@@ -23,12 +23,14 @@
-
+
PreserveNewest
+
+
diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Model/Apps/AppClientsTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Model/Apps/AppClientsTests.cs
new file mode 100644
index 000000000..99a38afec
--- /dev/null
+++ b/tests/Squidex.Domain.Apps.Core.Tests/Model/Apps/AppClientsTests.cs
@@ -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(() => 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(serializer);
+
+ appClients.ShouldBeEquivalentTo(sut);
+ }
+ }
+}
diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Model/Apps/AppContributorsTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Model/Apps/AppContributorsTests.cs
new file mode 100644
index 000000000..e56b792a9
--- /dev/null
+++ b/tests/Squidex.Domain.Apps.Core.Tests/Model/Apps/AppContributorsTests.cs
@@ -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(serializer);
+
+ serialized.ShouldBeEquivalentTo(sut);
+ }
+ }
+}
diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Model/Apps/AppPlanTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Model/Apps/AppPlanTests.cs
new file mode 100644
index 000000000..c32406f9f
--- /dev/null
+++ b/tests/Squidex.Domain.Apps.Core.Tests/Model/Apps/AppPlanTests.cs
@@ -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(serializer);
+
+ serialized.ShouldBeEquivalentTo(sut);
+ }
+ }
+}
diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Model/Apps/LanguagesConfigJsonTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Model/Apps/LanguagesConfigJsonTests.cs
new file mode 100644
index 000000000..cd5ae5eb9
--- /dev/null
+++ b/tests/Squidex.Domain.Apps.Core.Tests/Model/Apps/LanguagesConfigJsonTests.cs
@@ -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(serializer);
+
+ serialized.ShouldBeEquivalentTo(sut);
+ }
+ }
+}
diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Model/LanguagesConfigTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Model/Apps/LanguagesConfigTests.cs
similarity index 98%
rename from tests/Squidex.Domain.Apps.Core.Tests/Model/LanguagesConfigTests.cs
rename to tests/Squidex.Domain.Apps.Core.Tests/Model/Apps/LanguagesConfigTests.cs
index d801a9810..b0830d366 100644
--- a/tests/Squidex.Domain.Apps.Core.Tests/Model/LanguagesConfigTests.cs
+++ b/tests/Squidex.Domain.Apps.Core.Tests/Model/Apps/LanguagesConfigTests.cs
@@ -11,10 +11,11 @@ using System.Collections;
using System.Collections.Generic;
using System.Linq;
using FluentAssertions;
+using Squidex.Domain.Apps.Core.Apps;
using Squidex.Infrastructure;
using Xunit;
-namespace Squidex.Domain.Apps.Core.Model
+namespace Squidex.Domain.Apps.Core.Model.Apps
{
public class LanguagesConfigTests
{
diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Model/Contents/ContentDataTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Model/Contents/ContentDataTests.cs
index cb4b36c77..f9fe1e6f8 100644
--- a/tests/Squidex.Domain.Apps.Core.Tests/Model/Contents/ContentDataTests.cs
+++ b/tests/Squidex.Domain.Apps.Core.Tests/Model/Contents/ContentDataTests.cs
@@ -59,6 +59,23 @@ namespace Squidex.Domain.Apps.Core.Model.Contents
Assert.Equal(expected, actual);
}
+ [Fact]
+ public void Should_return_same_content_if_merging_same_references()
+ {
+ var source =
+ new NamedContentData()
+ .AddField("field1",
+ new ContentFieldData()
+ .AddValue("iv", 1))
+ .AddField("field2",
+ new ContentFieldData()
+ .AddValue("de", 2));
+
+ var actual = source.MergeInto(source);
+
+ Assert.Same(source, actual);
+ }
+
[Fact]
public void Should_merge_two_name_models()
{
diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Model/Schemas/Json/JsonSerializerTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Model/Schemas/Json/JsonSerializerTests.cs
deleted file mode 100644
index 941c85d5e..000000000
--- a/tests/Squidex.Domain.Apps.Core.Tests/Model/Schemas/Json/JsonSerializerTests.cs
+++ /dev/null
@@ -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(serializer);
-
- schemaTarget.ShouldBeEquivalentTo(schemaSource);
- }
- }
-}
diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Model/Schemas/SchemaFieldTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Model/Schemas/SchemaFieldTests.cs
new file mode 100644
index 000000000..02f805529
--- /dev/null
+++ b/tests/Squidex.Domain.Apps.Core.Tests/Model/Schemas/SchemaFieldTests.cs
@@ -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(() => 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(() => sut.Update(new StringFieldProperties()));
+ }
+ }
+}
diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Model/Schemas/SchemaTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Model/Schemas/SchemaTests.cs
index 8d5fbebfa..93b5006a9 100644
--- a/tests/Squidex.Domain.Apps.Core.Tests/Model/Schemas/SchemaTests.cs
+++ b/tests/Squidex.Domain.Apps.Core.Tests/Model/Schemas/SchemaTests.cs
@@ -9,6 +9,9 @@
using System;
using System.Collections.Generic;
using System.Linq;
+using FluentAssertions;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
using Squidex.Domain.Apps.Core.Schemas;
using Xunit;
@@ -16,6 +19,7 @@ namespace Squidex.Domain.Apps.Core.Model.Schemas
{
public class SchemaTests
{
+ private readonly JsonSerializer serializer = TestData.DefaultSerializer();
private readonly Schema sut = new Schema("my-schema");
[Fact]
@@ -65,59 +69,11 @@ namespace Squidex.Domain.Apps.Core.Model.Schemas
}
[Fact]
- public void Should_hide_field()
- {
- AddNumberField(1);
-
- sut.FieldsById[1].Hide();
- sut.FieldsById[1].Hide();
-
- Assert.True(sut.FieldsById[1].IsHidden);
- }
-
- [Fact]
- public void Should_show_field()
- {
- AddNumberField(1);
-
- sut.FieldsById[1].Hide();
- sut.FieldsById[1].Show();
- sut.FieldsById[1].Show();
-
- Assert.False(sut.FieldsById[1].IsHidden);
- }
-
- [Fact]
- public void Should_disable_field()
- {
- AddNumberField(1);
-
- sut.FieldsById[1].Disable();
- sut.FieldsById[1].Disable();
-
- Assert.True(sut.FieldsById[1].IsDisabled);
- }
-
- [Fact]
- public void Should_enable_field()
- {
- AddNumberField(1);
-
- sut.FieldsById[1].Disable();
- sut.FieldsById[1].Enable();
- sut.FieldsById[1].Enable();
-
- Assert.False(sut.FieldsById[1].IsDisabled);
- }
-
- [Fact]
- public void Should_lock_field()
+ public void Should_throw_exception_if_updating_with_invalid_properties_type()
{
AddNumberField(1);
- sut.FieldsById[1].Lock();
-
- Assert.True(sut.FieldsById[1].IsLocked);
+ Assert.Throws(() => sut.FieldsById[1].Update(new StringFieldProperties()));
}
[Fact]
@@ -140,24 +96,6 @@ namespace Squidex.Domain.Apps.Core.Model.Schemas
Assert.Empty(sut.FieldsById);
}
- [Fact]
- public void Should_update_field()
- {
- AddNumberField(1);
-
- sut.FieldsById[1].Update(new NumberFieldProperties { Hints = "my-hints" });
-
- Assert.Equal("my-hints", sut.FieldsById[1].RawProperties.Hints);
- }
-
- [Fact]
- public void Should_throw_exception_if_updating_with_invalid_properties_type()
- {
- AddNumberField(1);
-
- Assert.Throws(() => sut.FieldsById[1].Update(new StringFieldProperties()));
- }
-
[Fact]
public void Should_publish_schema()
{
@@ -205,6 +143,15 @@ namespace Squidex.Domain.Apps.Core.Model.Schemas
Assert.Throws(() => sut.ReorderFields(new List { 1, 4 }));
}
+ [Fact]
+ public void Should_serialize_and_deserialize_schema()
+ {
+ var schemaSource = TestData.MixedSchema();
+ var schemaTarget = JToken.FromObject(schemaSource, serializer).ToObject(serializer);
+
+ schemaTarget.ShouldBeEquivalentTo(schemaSource);
+ }
+
private NumberField AddNumberField(int id)
{
var field = new NumberField(id, $"my-field-{id}", Partitioning.Invariant);
diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ConvertContent/ContentConversionTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ConvertContent/ContentConversionTests.cs
index a6c436d1a..663e00cbd 100644
--- a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ConvertContent/ContentConversionTests.cs
+++ b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ConvertContent/ContentConversionTests.cs
@@ -6,12 +6,11 @@
// All rights reserved.
// ==========================================================================
-using System;
using System.Collections.Generic;
using Newtonsoft.Json.Linq;
+using Squidex.Domain.Apps.Core.Apps;
using Squidex.Domain.Apps.Core.Contents;
using Squidex.Domain.Apps.Core.ConvertContent;
-using Squidex.Domain.Apps.Core.ExtractReferenceIds;
using Squidex.Domain.Apps.Core.Schemas;
using Squidex.Infrastructure;
using Xunit;
diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Operations/EnrichContent/ContentEnrichmentTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Operations/EnrichContent/ContentEnrichmentTests.cs
index 5f2b899d0..25b650970 100644
--- a/tests/Squidex.Domain.Apps.Core.Tests/Operations/EnrichContent/ContentEnrichmentTests.cs
+++ b/tests/Squidex.Domain.Apps.Core.Tests/Operations/EnrichContent/ContentEnrichmentTests.cs
@@ -9,6 +9,7 @@
using System;
using Newtonsoft.Json.Linq;
using NodaTime;
+using Squidex.Domain.Apps.Core.Apps;
using Squidex.Domain.Apps.Core.Contents;
using Squidex.Domain.Apps.Core.EnrichContent;
using Squidex.Domain.Apps.Core.Schemas;
diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ExtractReferenceIds/ReferenceExtractionTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ExtractReferenceIds/ReferenceExtractionTests.cs
index 7f4af1cd6..1c69bdb85 100644
--- a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ExtractReferenceIds/ReferenceExtractionTests.cs
+++ b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ExtractReferenceIds/ReferenceExtractionTests.cs
@@ -10,6 +10,7 @@ using System;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json.Linq;
+using Squidex.Domain.Apps.Core.Apps;
using Squidex.Domain.Apps.Core.Contents;
using Squidex.Domain.Apps.Core.ExtractReferenceIds;
using Squidex.Domain.Apps.Core.Schemas;
diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Operations/GenerateEdmSchema/EdmTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Operations/GenerateEdmSchema/EdmTests.cs
index 9bc7060ab..e76471ee1 100644
--- a/tests/Squidex.Domain.Apps.Core.Tests/Operations/GenerateEdmSchema/EdmTests.cs
+++ b/tests/Squidex.Domain.Apps.Core.Tests/Operations/GenerateEdmSchema/EdmTests.cs
@@ -6,6 +6,7 @@
// All rights reserved.
// ==========================================================================
+using Squidex.Domain.Apps.Core.Apps;
using Squidex.Domain.Apps.Core.GenerateEdmSchema;
using Squidex.Infrastructure;
using Xunit;
diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Operations/GenerateJsonSchema/JsonSchemaTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Operations/GenerateJsonSchema/JsonSchemaTests.cs
index 508e88d38..b786f90a2 100644
--- a/tests/Squidex.Domain.Apps.Core.Tests/Operations/GenerateJsonSchema/JsonSchemaTests.cs
+++ b/tests/Squidex.Domain.Apps.Core.Tests/Operations/GenerateJsonSchema/JsonSchemaTests.cs
@@ -7,6 +7,7 @@
// ==========================================================================
using NJsonSchema;
+using Squidex.Domain.Apps.Core.Apps;
using Squidex.Domain.Apps.Core.GenerateJsonSchema;
using Squidex.Domain.Apps.Core.Schemas;
using Squidex.Infrastructure;
diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/ContentValidationTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/ContentValidationTests.cs
index 7376cd51c..9b0a35e5a 100644
--- a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/ContentValidationTests.cs
+++ b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/ContentValidationTests.cs
@@ -9,6 +9,7 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using FluentAssertions;
+using Squidex.Domain.Apps.Core.Apps;
using Squidex.Domain.Apps.Core.Contents;
using Squidex.Domain.Apps.Core.Schemas;
using Squidex.Domain.Apps.Core.ValidateContent;
diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/NumberFieldTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/NumberFieldTests.cs
index 33978a938..955fcdc74 100644
--- a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/NumberFieldTests.cs
+++ b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/NumberFieldTests.cs
@@ -7,7 +7,6 @@
// ==========================================================================
using System.Collections.Generic;
-using System.Collections.Immutable;
using System.Threading.Tasks;
using FluentAssertions;
using Newtonsoft.Json.Linq;
diff --git a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/StringFieldTests.cs b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/StringFieldTests.cs
index eda35ca87..c1103da56 100644
--- a/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/StringFieldTests.cs
+++ b/tests/Squidex.Domain.Apps.Core.Tests/Operations/ValidateContent/StringFieldTests.cs
@@ -7,7 +7,6 @@
// ==========================================================================
using System.Collections.Generic;
-using System.Collections.Immutable;
using System.Threading.Tasks;
using FluentAssertions;
using Newtonsoft.Json.Linq;
diff --git a/tests/Squidex.Domain.Apps.Core.Tests/TestData.cs b/tests/Squidex.Domain.Apps.Core.Tests/TestData.cs
index 0930c69da..15b4449a0 100644
--- a/tests/Squidex.Domain.Apps.Core.Tests/TestData.cs
+++ b/tests/Squidex.Domain.Apps.Core.Tests/TestData.cs
@@ -6,12 +6,45 @@
// All rights reserved.
// ==========================================================================
+using Newtonsoft.Json;
+using Newtonsoft.Json.Converters;
+using Squidex.Domain.Apps.Core.Apps.Json;
using Squidex.Domain.Apps.Core.Schemas;
+using Squidex.Domain.Apps.Core.Schemas.Json;
+using Squidex.Infrastructure;
+using Squidex.Infrastructure.Json;
namespace Squidex.Domain.Apps.Core
{
public static class TestData
{
+ public static JsonSerializer DefaultSerializer()
+ {
+ var typeNameRegistry = new TypeNameRegistry();
+
+ var serializerSettings = new JsonSerializerSettings
+ {
+ SerializationBinder = new TypeNameSerializationBinder(typeNameRegistry),
+
+ ContractResolver = new ConverterContractResolver(
+ new AppClientsConverter(),
+ new AppContributorsConverter(),
+ new InstantConverter(),
+ new LanguageConverter(),
+ new LanguagesConfigConverter(),
+ new NamedGuidIdConverter(),
+ new NamedLongIdConverter(),
+ new NamedStringIdConverter(),
+ new RefTokenConverter(),
+ new SchemaConverter(new FieldRegistry(typeNameRegistry)),
+ new StringEnumConverter()),
+
+ TypeNameHandling = TypeNameHandling.Auto
+ };
+
+ return JsonSerializer.Create(serializerSettings);
+ }
+
public static Schema MixedSchema()
{
var inv = Partitioning.Invariant;
diff --git a/tests/Squidex.Domain.Apps.Read.Tests/Contents/GraphQLTests.cs b/tests/Squidex.Domain.Apps.Read.Tests/Contents/GraphQLTests.cs
index 2a4419573..a32193a3d 100644
--- a/tests/Squidex.Domain.Apps.Read.Tests/Contents/GraphQLTests.cs
+++ b/tests/Squidex.Domain.Apps.Read.Tests/Contents/GraphQLTests.cs
@@ -37,28 +37,7 @@ namespace Squidex.Domain.Apps.Read.Contents
{
private static readonly Guid schemaId = Guid.NewGuid();
private static readonly Guid appId = Guid.NewGuid();
-
- private readonly Schema schemaDef =
- Schema.Create("my-schema", new SchemaProperties())
- .AddField(new JsonField(1, "my-json", Partitioning.Invariant,
- new JsonFieldProperties()))
- .AddField(new StringField(2, "my-string", Partitioning.Language,
- new StringFieldProperties()))
- .AddField(new NumberField(3, "my-number", Partitioning.Invariant,
- new NumberFieldProperties()))
- .AddField(new AssetsField(4, "my-assets", Partitioning.Invariant,
- new AssetsFieldProperties()))
- .AddField(new BooleanField(5, "my-boolean", Partitioning.Invariant,
- new BooleanFieldProperties()))
- .AddField(new DateTimeField(6, "my-datetime", Partitioning.Invariant,
- new DateTimeFieldProperties()))
- .AddField(new ReferencesField(7, "my-references", Partitioning.Invariant,
- new ReferencesFieldProperties { SchemaId = schemaId }))
- .AddField(new ReferencesField(9, "my-invalid", Partitioning.Invariant,
- new ReferencesFieldProperties { SchemaId = Guid.NewGuid() }))
- .AddField(new GeolocationField(10, "my-geolocation", Partitioning.Invariant,
- new GeolocationFieldProperties()));
-
+ private readonly Schema schemaDef = new Schema("my-schema");
private readonly IContentQueryService contentQuery = A.Fake();
private readonly ISchemaRepository schemaRepository = A.Fake();
private readonly IAssetRepository assetRepository = A.Fake();
@@ -70,6 +49,33 @@ namespace Squidex.Domain.Apps.Read.Contents
public GraphQLTests()
{
+ schemaDef.AddField(new JsonField(1, "my-json", Partitioning.Invariant,
+ new JsonFieldProperties()));
+
+ schemaDef.AddField(new StringField(2, "my-string", Partitioning.Language,
+ new StringFieldProperties()));
+
+ schemaDef.AddField(new NumberField(3, "my-number", Partitioning.Invariant,
+ new NumberFieldProperties()));
+
+ schemaDef.AddField(new AssetsField(4, "my-assets", Partitioning.Invariant,
+ new AssetsFieldProperties()));
+
+ schemaDef.AddField(new BooleanField(5, "my-boolean", Partitioning.Invariant,
+ new BooleanFieldProperties()));
+
+ schemaDef.AddField(new DateTimeField(6, "my-datetime", Partitioning.Invariant,
+ new DateTimeFieldProperties()));
+
+ schemaDef.AddField(new ReferencesField(7, "my-references", Partitioning.Invariant,
+ new ReferencesFieldProperties { SchemaId = schemaId }));
+
+ schemaDef.AddField(new ReferencesField(9, "my-invalid", Partitioning.Invariant,
+ new ReferencesFieldProperties { SchemaId = Guid.NewGuid() }));
+
+ schemaDef.AddField(new GeolocationField(10, "my-geolocation", Partitioning.Invariant,
+ new GeolocationFieldProperties()));
+
A.CallTo(() => app.Id).Returns(appId);
A.CallTo(() => app.PartitionResolver).Returns(x => InvariantPartitioning.Instance);
diff --git a/tests/Squidex.Domain.Apps.Read.Tests/Contents/ODataQueryTests.cs b/tests/Squidex.Domain.Apps.Read.Tests/Contents/ODataQueryTests.cs
index c34b87fbc..f256b7d47 100644
--- a/tests/Squidex.Domain.Apps.Read.Tests/Contents/ODataQueryTests.cs
+++ b/tests/Squidex.Domain.Apps.Read.Tests/Contents/ODataQueryTests.cs
@@ -7,7 +7,6 @@
// ==========================================================================
using System;
-using System.Collections.Immutable;
using FakeItEasy;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Options;
@@ -15,6 +14,7 @@ using Microsoft.OData.Edm;
using MongoDB.Bson.Serialization;
using MongoDB.Driver;
using Squidex.Domain.Apps.Core;
+using Squidex.Domain.Apps.Core.Apps;
using Squidex.Domain.Apps.Core.Schemas;
using Squidex.Domain.Apps.Read.Apps;
using Squidex.Domain.Apps.Read.Contents.Edm;
@@ -29,29 +29,11 @@ namespace Squidex.Domain.Apps.Read.Contents
{
public class ODataQueryTests
{
- private readonly Schema schemaDef =
- Schema.Create("user", new SchemaProperties { Hints = "The User" })
- .AddField(new StringField(1, "firstName", Partitioning.Language,
- new StringFieldProperties { Label = "FirstName", IsRequired = true, AllowedValues = new[] { "1", "2" }.ToImmutableList() }))
- .AddField(new StringField(2, "lastName", Partitioning.Language,
- new StringFieldProperties { Hints = "Last Name", Editor = StringFieldEditor.Input }))
- .AddField(new BooleanField(3, "isAdmin", Partitioning.Invariant,
- new BooleanFieldProperties()))
- .AddField(new NumberField(4, "age", Partitioning.Invariant,
- new NumberFieldProperties { MinValue = 1, MaxValue = 10 }))
- .AddField(new DateTimeField(5, "birthday", Partitioning.Invariant,
- new DateTimeFieldProperties()))
- .AddField(new AssetsField(6, "pictures", Partitioning.Invariant,
- new AssetsFieldProperties()))
- .AddField(new ReferencesField(7, "friends", Partitioning.Invariant,
- new ReferencesFieldProperties()))
- .AddField(new StringField(8, "dashed-field", Partitioning.Invariant,
- new StringFieldProperties()));
-
+ private readonly Schema schemaDef = new Schema("user");
private readonly IBsonSerializerRegistry registry = BsonSerializer.SerializerRegistry;
private readonly IBsonSerializer serializer = BsonSerializer.SerializerRegistry.GetSerializer();
private readonly IEdmModel edmModel;
- private readonly LanguagesConfig languagesConfig = LanguagesConfig.Create(Language.EN, Language.DE);
+ private readonly LanguagesConfig languagesConfig = LanguagesConfig.Build(Language.EN, Language.DE);
static ODataQueryTests()
{
@@ -60,6 +42,31 @@ namespace Squidex.Domain.Apps.Read.Contents
public ODataQueryTests()
{
+ schemaDef.Update(new SchemaProperties { Hints = "The User" });
+
+ schemaDef.AddField(new StringField(1, "firstName", Partitioning.Language,
+ new StringFieldProperties { Label = "FirstName", IsRequired = true, AllowedValues = new[] { "1", "2" } }));
+ schemaDef.AddField(new StringField(2, "lastName", Partitioning.Language,
+ new StringFieldProperties { Hints = "Last Name", Editor = StringFieldEditor.Input }));
+
+ schemaDef.AddField(new BooleanField(3, "isAdmin", Partitioning.Invariant,
+ new BooleanFieldProperties()));
+
+ schemaDef.AddField(new NumberField(4, "age", Partitioning.Invariant,
+ new NumberFieldProperties { MinValue = 1, MaxValue = 10 }));
+
+ schemaDef.AddField(new DateTimeField(5, "birthday", Partitioning.Invariant,
+ new DateTimeFieldProperties()));
+
+ schemaDef.AddField(new AssetsField(6, "pictures", Partitioning.Invariant,
+ new AssetsFieldProperties()));
+
+ schemaDef.AddField(new ReferencesField(7, "friends", Partitioning.Invariant,
+ new ReferencesFieldProperties()));
+
+ schemaDef.AddField(new StringField(8, "dashed-field", Partitioning.Invariant,
+ new StringFieldProperties()));
+
var builder = new EdmModelBuilder(new MemoryCache(Options.Create(new MemoryCacheOptions())));
var schema = A.Dummy();
diff --git a/tests/Squidex.Domain.Apps.Write.Tests/Apps/Guards/GuardAppClientsTests.cs b/tests/Squidex.Domain.Apps.Write.Tests/Apps/Guards/GuardAppClientsTests.cs
new file mode 100644
index 000000000..c10fc34d7
--- /dev/null
+++ b/tests/Squidex.Domain.Apps.Write.Tests/Apps/Guards/GuardAppClientsTests.cs
@@ -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(() => 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(() => 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(() => GuardAppClients.CanRevoke(clients, command));
+ }
+
+ [Fact]
+ public void CanRevoke_should_throw_exception_if_client_is_not_found()
+ {
+ var command = new RevokeClient { Id = "ios" };
+
+ Assert.Throws(() => 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(() => 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(() => 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(() => 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(() => 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(() => 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(() => 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);
+ }
+ }
+}
diff --git a/tests/Squidex.Domain.Apps.Write.Tests/Apps/Guards/GuardAppContributorsTests.cs b/tests/Squidex.Domain.Apps.Write.Tests/Apps/Guards/GuardAppContributorsTests.cs
index f9d007afd..fc59e17a5 100644
--- a/tests/Squidex.Domain.Apps.Write.Tests/Apps/Guards/GuardAppContributorsTests.cs
+++ b/tests/Squidex.Domain.Apps.Write.Tests/Apps/Guards/GuardAppContributorsTests.cs
@@ -21,6 +21,7 @@ namespace Squidex.Domain.Apps.Write.Apps.Guards
{
private readonly IUserResolver users = A.Fake();
private readonly IAppLimitsPlan appPlan = A.Fake();
+ private readonly AppContributors contributors = new AppContributors();
public GuardAppContributorsTests()
{
@@ -36,8 +37,6 @@ namespace Squidex.Domain.Apps.Write.Apps.Guards
{
var command = new AssignContributor();
- var contributors = new AppContributors();
-
return Assert.ThrowsAsync(() => GuardAppContributors.CanAssign(contributors, command, users, appPlan));
}
@@ -46,8 +45,6 @@ namespace Squidex.Domain.Apps.Write.Apps.Guards
{
var command = new AssignContributor { ContributorId = "1", Permission = (AppContributorPermission)10 };
- var contributors = new AppContributors();
-
return Assert.ThrowsAsync(() => GuardAppContributors.CanAssign(contributors, command, users, appPlan));
}
@@ -56,8 +53,6 @@ namespace Squidex.Domain.Apps.Write.Apps.Guards
{
var command = new AssignContributor { ContributorId = "1" };
- var contributors = new AppContributors();
-
contributors.Assign("1", AppContributorPermission.Owner);
return Assert.ThrowsAsync(() => GuardAppContributors.CanAssign(contributors, command, users, appPlan));
@@ -71,8 +66,6 @@ namespace Squidex.Domain.Apps.Write.Apps.Guards
var command = new AssignContributor { ContributorId = "1", Permission = (AppContributorPermission)10 };
- var contributors = new AppContributors();
-
return Assert.ThrowsAsync(() => GuardAppContributors.CanAssign(contributors, command, users, appPlan));
}
@@ -84,8 +77,6 @@ namespace Squidex.Domain.Apps.Write.Apps.Guards
var command = new AssignContributor { ContributorId = "3" };
- var contributors = new AppContributors();
-
contributors.Assign("1", AppContributorPermission.Owner);
contributors.Assign("2", AppContributorPermission.Editor);
@@ -97,8 +88,6 @@ namespace Squidex.Domain.Apps.Write.Apps.Guards
{
var command = new AssignContributor { ContributorId = "1" };
- var contributors = new AppContributors();
-
return GuardAppContributors.CanAssign(contributors, command, users, appPlan);
}
@@ -107,8 +96,6 @@ namespace Squidex.Domain.Apps.Write.Apps.Guards
{
var command = new AssignContributor { ContributorId = "1" };
- var contributors = new AppContributors();
-
contributors.Assign("1", AppContributorPermission.Editor);
return GuardAppContributors.CanAssign(contributors, command, users, appPlan);
@@ -122,8 +109,6 @@ namespace Squidex.Domain.Apps.Write.Apps.Guards
var command = new AssignContributor { ContributorId = "1" };
- var contributors = new AppContributors();
-
contributors.Assign("1", AppContributorPermission.Editor);
contributors.Assign("2", AppContributorPermission.Editor);
@@ -135,8 +120,6 @@ namespace Squidex.Domain.Apps.Write.Apps.Guards
{
var command = new RemoveContributor();
- var contributors = new AppContributors();
-
Assert.Throws(() => GuardAppContributors.CanRemove(contributors, command));
}
@@ -145,8 +128,6 @@ namespace Squidex.Domain.Apps.Write.Apps.Guards
{
var command = new RemoveContributor { ContributorId = "1" };
- var contributors = new AppContributors();
-
Assert.Throws(() => GuardAppContributors.CanRemove(contributors, command));
}
@@ -155,8 +136,6 @@ namespace Squidex.Domain.Apps.Write.Apps.Guards
{
var command = new RemoveContributor { ContributorId = "1" };
- var contributors = new AppContributors();
-
contributors.Assign("1", AppContributorPermission.Owner);
contributors.Assign("2", AppContributorPermission.Editor);
@@ -168,8 +147,6 @@ namespace Squidex.Domain.Apps.Write.Apps.Guards
{
var command = new RemoveContributor { ContributorId = "1" };
- var contributors = new AppContributors();
-
contributors.Assign("1", AppContributorPermission.Owner);
contributors.Assign("2", AppContributorPermission.Owner);
diff --git a/tests/Squidex.Domain.Apps.Write.Tests/Apps/Guards/GuardAppLanguagesTests.cs b/tests/Squidex.Domain.Apps.Write.Tests/Apps/Guards/GuardAppLanguagesTests.cs
index a03087358..02e3ce614 100644
--- a/tests/Squidex.Domain.Apps.Write.Tests/Apps/Guards/GuardAppLanguagesTests.cs
+++ b/tests/Squidex.Domain.Apps.Write.Tests/Apps/Guards/GuardAppLanguagesTests.cs
@@ -7,7 +7,7 @@
// ==========================================================================
using System.Collections.Generic;
-using Squidex.Domain.Apps.Core;
+using Squidex.Domain.Apps.Core.Apps;
using Squidex.Domain.Apps.Write.Apps.Commands;
using Squidex.Infrastructure;
using Xunit;
@@ -16,13 +16,13 @@ namespace Squidex.Domain.Apps.Write.Apps.Guards
{
public class GuardAppLanguagesTests
{
+ private readonly LanguagesConfig languages = LanguagesConfig.Build(Language.DE);
+
[Fact]
public void CanAddLanguage_should_throw_exception_if_language_is_null()
{
var command = new AddLanguage();
- var languages = LanguagesConfig.Build(Language.DE);
-
Assert.Throws(() => GuardAppLanguages.CanAdd(languages, command));
}
@@ -31,8 +31,6 @@ namespace Squidex.Domain.Apps.Write.Apps.Guards
{
var command = new AddLanguage { Language = Language.DE };
- var languages = LanguagesConfig.Build(Language.DE);
-
Assert.Throws(() => GuardAppLanguages.CanAdd(languages, command));
}
@@ -41,8 +39,6 @@ namespace Squidex.Domain.Apps.Write.Apps.Guards
{
var command = new AddLanguage { Language = Language.EN };
- var languages = LanguagesConfig.Build(Language.DE);
-
GuardAppLanguages.CanAdd(languages, command);
}
@@ -51,9 +47,7 @@ namespace Squidex.Domain.Apps.Write.Apps.Guards
{
var command = new RemoveLanguage();
- var languages = LanguagesConfig.Build(Language.DE);
-
- Assert.Throws(() => GuardAppLanguages.CanRemove(languages, command));
+ Assert.Throws(() => GuardAppLanguages.CanRemove(languages, command));
}
[Fact]
@@ -61,8 +55,6 @@ namespace Squidex.Domain.Apps.Write.Apps.Guards
{
var command = new RemoveLanguage { Language = Language.EN };
- var languages = LanguagesConfig.Build(Language.DE);
-
Assert.Throws(() => GuardAppLanguages.CanRemove(languages, command));
}
@@ -71,8 +63,6 @@ namespace Squidex.Domain.Apps.Write.Apps.Guards
{
var command = new RemoveLanguage { Language = Language.DE };
- var languages = LanguagesConfig.Build(Language.DE);
-
Assert.Throws(() => GuardAppLanguages.CanRemove(languages, command));
}
@@ -81,17 +71,27 @@ namespace Squidex.Domain.Apps.Write.Apps.Guards
{
var command = new RemoveLanguage { Language = Language.EN };
- var languages = LanguagesConfig.Build(Language.DE, Language.EN);
+ languages.Set(new LanguageConfig(Language.EN));
GuardAppLanguages.CanRemove(languages, command);
}
+ [Fact]
+ public void CanUpdateLanguage_should_throw_exception_if_language_is_null()
+ {
+ var command = new UpdateLanguage();
+
+ languages.Set(new LanguageConfig(Language.EN));
+
+ Assert.Throws(() => GuardAppLanguages.CanUpdate(languages, command));
+ }
+
[Fact]
public void CanUpdateLanguage_should_throw_exception_if_language_is_optional_and_master()
{
var command = new UpdateLanguage { Language = Language.DE, IsOptional = true };
- var languages = LanguagesConfig.Build(Language.DE, Language.EN);
+ languages.Set(new LanguageConfig(Language.EN));
Assert.Throws(() => GuardAppLanguages.CanUpdate(languages, command));
}
@@ -101,7 +101,7 @@ namespace Squidex.Domain.Apps.Write.Apps.Guards
{
var command = new UpdateLanguage { Language = Language.DE, Fallback = new List { Language.IT } };
- var languages = LanguagesConfig.Build(Language.DE, Language.EN);
+ languages.Set(new LanguageConfig(Language.EN));
Assert.Throws(() => GuardAppLanguages.CanUpdate(languages, command));
}
@@ -111,7 +111,7 @@ namespace Squidex.Domain.Apps.Write.Apps.Guards
{
var command = new UpdateLanguage { Language = Language.IT };
- var languages = LanguagesConfig.Build(Language.DE, Language.EN);
+ languages.Set(new LanguageConfig(Language.EN));
Assert.Throws(() => GuardAppLanguages.CanUpdate(languages, command));
}
@@ -121,7 +121,7 @@ namespace Squidex.Domain.Apps.Write.Apps.Guards
{
var command = new UpdateLanguage { Language = Language.DE, Fallback = new List { Language.EN } };
- var languages = LanguagesConfig.Build(Language.DE, Language.EN);
+ languages.Set(new LanguageConfig(Language.EN));
GuardAppLanguages.CanUpdate(languages, command);
}
diff --git a/tests/Squidex.Domain.Apps.Write.Tests/Contents/ContentCommandMiddlewareTests.cs b/tests/Squidex.Domain.Apps.Write.Tests/Contents/ContentCommandMiddlewareTests.cs
index 9d02d19b5..3ea088770 100644
--- a/tests/Squidex.Domain.Apps.Write.Tests/Contents/ContentCommandMiddlewareTests.cs
+++ b/tests/Squidex.Domain.Apps.Write.Tests/Contents/ContentCommandMiddlewareTests.cs
@@ -11,6 +11,7 @@ using System.Security.Claims;
using System.Threading.Tasks;
using FakeItEasy;
using Squidex.Domain.Apps.Core;
+using Squidex.Domain.Apps.Core.Apps;
using Squidex.Domain.Apps.Core.Contents;
using Squidex.Domain.Apps.Core.Schemas;
using Squidex.Domain.Apps.Core.Scripting;
diff --git a/tests/Squidex.Domain.Apps.Write.Tests/Contents/Guard/GuardContentTests.cs b/tests/Squidex.Domain.Apps.Write.Tests/Contents/Guard/GuardContentTests.cs
new file mode 100644
index 000000000..b0f78570d
--- /dev/null
+++ b/tests/Squidex.Domain.Apps.Write.Tests/Contents/Guard/GuardContentTests.cs
@@ -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(() => 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(() => 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(() => 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(() => 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(() => 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);
+ }
+ }
+}