diff --git a/Squidex.sln b/Squidex.sln index cb23f22ff..72eff25c0 100644 --- a/Squidex.sln +++ b/Squidex.sln @@ -1,6 +1,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 -VisualStudioVersion = 15.0.27004.2009 +VisualStudioVersion = 15.0.27130.2003 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Squidex", "src\Squidex\Squidex.csproj", "{61F6BBCE-A080-4400-B194-70E2F5D2096E}" EndProject @@ -12,22 +12,12 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Squidex.Infrastructure", "s EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Squidex.Domain.Apps.Events", "src\Squidex.Domain.Apps.Events\Squidex.Domain.Apps.Events.csproj", "{25F66C64-058A-4D44-BC0C-F12A054F9A91}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Squidex.Domain.Apps.Write", "src\Squidex.Domain.Apps.Write\Squidex.Domain.Apps.Write.csproj", "{A85201C6-6AF8-4B63-8365-08F741050438}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Squidex.Domain.Apps.Read", "src\Squidex.Domain.Apps.Read\Squidex.Domain.Apps.Read.csproj", "{A92B4734-2587-4F6F-97A3-741BE48709A5}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Squidex.Domain.Apps.Read.MongoDb", "src\Squidex.Domain.Apps.Read.MongoDb\Squidex.Domain.Apps.Read.MongoDb.csproj", "{28F8E9E2-FE24-41F7-A888-9FC244A9E2DD}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Squidex.Domain.Apps.Write.Tests", "tests\Squidex.Domain.Apps.Write.Tests\Squidex.Domain.Apps.Write.Tests.csproj", "{9A3DEA7E-1681-4D48-AC5C-1F0DE421A203}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Squidex.Infrastructure.Tests", "tests\Squidex.Infrastructure.Tests\Squidex.Infrastructure.Tests.csproj", "{7FD0A92B-7862-4BB1-932B-B52A9CACB56B}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Squidex.Domain.Apps.Core.Tests", "tests\Squidex.Domain.Apps.Core.Tests\Squidex.Domain.Apps.Core.Tests.csproj", "{FD0AFD44-7A93-4F9E-B5ED-72582392E435}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Squidex.Infrastructure.MongoDb", "src\Squidex.Infrastructure.MongoDb\Squidex.Infrastructure.MongoDb.csproj", "{6A811927-3C37-430A-90F4-503E37123956}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Squidex.Domain.Apps.Read.Tests", "tests\Squidex.Domain.Apps.Read.Tests\Squidex.Domain.Apps.Read.Tests.csproj", "{8B074219-F69A-4E41-83C6-12EE1E647779}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Squidex.Infrastructure.Redis", "src\Squidex.Infrastructure.Redis\Squidex.Infrastructure.Redis.csproj", "{D7166C56-178A-4457-B56A-C615C7450DEE}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Squidex.Infrastructure.RabbitMq", "src\Squidex.Infrastructure.RabbitMq\Squidex.Infrastructure.RabbitMq.csproj", "{C1E5BBB6-6B6A-4DE5-B19D-0538304DE343}" @@ -63,14 +53,14 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Squidex.Domain.Apps.Core.Mo EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Squidex.Domain.Apps.Core.Operations", "src\Squidex.Domain.Apps.Core.Operations\Squidex.Domain.Apps.Core.Operations.csproj", "{6B3F75B6-5888-468E-BA4F-4FC725DAEF31}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Benchmarks", "tests\Benchmarks\Benchmarks.csproj", "{9B4A55F4-D9A4-4FC3-8D85-02A9EF93FBAB}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Squidex.Domain.Apps.Entities", "src\Squidex.Domain.Apps.Entities\Squidex.Domain.Apps.Entities.csproj", "{79FEF326-CA5E-4698-B2BA-C16A4580B4D5}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Squidex.Domain.Apps.Entities.Tests", "tests\Squidex.Domain.Apps.Entities.Tests\Squidex.Domain.Apps.Entities.Tests.csproj", "{AA003372-CD8D-4DBC-962C-F61E0C93CF05}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Squidex.Domain.Apps.Entities.MongoDb", "src\Squidex.Domain.Apps.Entities.MongoDb\Squidex.Domain.Apps.Entities.MongoDb.csproj", "{7DA5B308-D950-4496-93D5-21D6C4D91644}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Migrate_01", "tools\Migrate_01\Migrate_01.csproj", "{A4823E14-C0E5-4A4D-B28F-27424C25C3C7}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -105,38 +95,6 @@ Global {25F66C64-058A-4D44-BC0C-F12A054F9A91}.Release|Any CPU.Build.0 = Release|Any CPU {25F66C64-058A-4D44-BC0C-F12A054F9A91}.Release|x64.ActiveCfg = Release|Any CPU {25F66C64-058A-4D44-BC0C-F12A054F9A91}.Release|x86.ActiveCfg = Release|Any CPU - {A85201C6-6AF8-4B63-8365-08F741050438}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A85201C6-6AF8-4B63-8365-08F741050438}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A85201C6-6AF8-4B63-8365-08F741050438}.Debug|x64.ActiveCfg = Debug|Any CPU - {A85201C6-6AF8-4B63-8365-08F741050438}.Debug|x86.ActiveCfg = Debug|Any CPU - {A85201C6-6AF8-4B63-8365-08F741050438}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A85201C6-6AF8-4B63-8365-08F741050438}.Release|Any CPU.Build.0 = Release|Any CPU - {A85201C6-6AF8-4B63-8365-08F741050438}.Release|x64.ActiveCfg = Release|Any CPU - {A85201C6-6AF8-4B63-8365-08F741050438}.Release|x86.ActiveCfg = Release|Any CPU - {A92B4734-2587-4F6F-97A3-741BE48709A5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A92B4734-2587-4F6F-97A3-741BE48709A5}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A92B4734-2587-4F6F-97A3-741BE48709A5}.Debug|x64.ActiveCfg = Debug|Any CPU - {A92B4734-2587-4F6F-97A3-741BE48709A5}.Debug|x86.ActiveCfg = Debug|Any CPU - {A92B4734-2587-4F6F-97A3-741BE48709A5}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A92B4734-2587-4F6F-97A3-741BE48709A5}.Release|Any CPU.Build.0 = Release|Any CPU - {A92B4734-2587-4F6F-97A3-741BE48709A5}.Release|x64.ActiveCfg = Release|Any CPU - {A92B4734-2587-4F6F-97A3-741BE48709A5}.Release|x86.ActiveCfg = Release|Any CPU - {28F8E9E2-FE24-41F7-A888-9FC244A9E2DD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {28F8E9E2-FE24-41F7-A888-9FC244A9E2DD}.Debug|Any CPU.Build.0 = Debug|Any CPU - {28F8E9E2-FE24-41F7-A888-9FC244A9E2DD}.Debug|x64.ActiveCfg = Debug|Any CPU - {28F8E9E2-FE24-41F7-A888-9FC244A9E2DD}.Debug|x86.ActiveCfg = Debug|Any CPU - {28F8E9E2-FE24-41F7-A888-9FC244A9E2DD}.Release|Any CPU.ActiveCfg = Release|Any CPU - {28F8E9E2-FE24-41F7-A888-9FC244A9E2DD}.Release|Any CPU.Build.0 = Release|Any CPU - {28F8E9E2-FE24-41F7-A888-9FC244A9E2DD}.Release|x64.ActiveCfg = Release|Any CPU - {28F8E9E2-FE24-41F7-A888-9FC244A9E2DD}.Release|x86.ActiveCfg = Release|Any CPU - {9A3DEA7E-1681-4D48-AC5C-1F0DE421A203}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {9A3DEA7E-1681-4D48-AC5C-1F0DE421A203}.Debug|Any CPU.Build.0 = Debug|Any CPU - {9A3DEA7E-1681-4D48-AC5C-1F0DE421A203}.Debug|x64.ActiveCfg = Debug|Any CPU - {9A3DEA7E-1681-4D48-AC5C-1F0DE421A203}.Debug|x86.ActiveCfg = Debug|Any CPU - {9A3DEA7E-1681-4D48-AC5C-1F0DE421A203}.Release|Any CPU.ActiveCfg = Release|Any CPU - {9A3DEA7E-1681-4D48-AC5C-1F0DE421A203}.Release|Any CPU.Build.0 = Release|Any CPU - {9A3DEA7E-1681-4D48-AC5C-1F0DE421A203}.Release|x64.ActiveCfg = Release|Any CPU - {9A3DEA7E-1681-4D48-AC5C-1F0DE421A203}.Release|x86.ActiveCfg = Release|Any CPU {7FD0A92B-7862-4BB1-932B-B52A9CACB56B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {7FD0A92B-7862-4BB1-932B-B52A9CACB56B}.Debug|Any CPU.Build.0 = Debug|Any CPU {7FD0A92B-7862-4BB1-932B-B52A9CACB56B}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -161,14 +119,6 @@ Global {6A811927-3C37-430A-90F4-503E37123956}.Release|Any CPU.Build.0 = Release|Any CPU {6A811927-3C37-430A-90F4-503E37123956}.Release|x64.ActiveCfg = Release|Any CPU {6A811927-3C37-430A-90F4-503E37123956}.Release|x86.ActiveCfg = Release|Any CPU - {8B074219-F69A-4E41-83C6-12EE1E647779}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {8B074219-F69A-4E41-83C6-12EE1E647779}.Debug|Any CPU.Build.0 = Debug|Any CPU - {8B074219-F69A-4E41-83C6-12EE1E647779}.Debug|x64.ActiveCfg = Debug|Any CPU - {8B074219-F69A-4E41-83C6-12EE1E647779}.Debug|x86.ActiveCfg = Debug|Any CPU - {8B074219-F69A-4E41-83C6-12EE1E647779}.Release|Any CPU.ActiveCfg = Release|Any CPU - {8B074219-F69A-4E41-83C6-12EE1E647779}.Release|Any CPU.Build.0 = Release|Any CPU - {8B074219-F69A-4E41-83C6-12EE1E647779}.Release|x64.ActiveCfg = Release|Any CPU - {8B074219-F69A-4E41-83C6-12EE1E647779}.Release|x86.ActiveCfg = Release|Any CPU {D7166C56-178A-4457-B56A-C615C7450DEE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {D7166C56-178A-4457-B56A-C615C7450DEE}.Debug|Any CPU.Build.0 = Debug|Any CPU {D7166C56-178A-4457-B56A-C615C7450DEE}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -309,18 +259,6 @@ Global {6B3F75B6-5888-468E-BA4F-4FC725DAEF31}.Release|x64.Build.0 = Release|Any CPU {6B3F75B6-5888-468E-BA4F-4FC725DAEF31}.Release|x86.ActiveCfg = Release|Any CPU {6B3F75B6-5888-468E-BA4F-4FC725DAEF31}.Release|x86.Build.0 = Release|Any CPU - {9B4A55F4-D9A4-4FC3-8D85-02A9EF93FBAB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {9B4A55F4-D9A4-4FC3-8D85-02A9EF93FBAB}.Debug|Any CPU.Build.0 = Debug|Any CPU - {9B4A55F4-D9A4-4FC3-8D85-02A9EF93FBAB}.Debug|x64.ActiveCfg = Debug|Any CPU - {9B4A55F4-D9A4-4FC3-8D85-02A9EF93FBAB}.Debug|x64.Build.0 = Debug|Any CPU - {9B4A55F4-D9A4-4FC3-8D85-02A9EF93FBAB}.Debug|x86.ActiveCfg = Debug|Any CPU - {9B4A55F4-D9A4-4FC3-8D85-02A9EF93FBAB}.Debug|x86.Build.0 = Debug|Any CPU - {9B4A55F4-D9A4-4FC3-8D85-02A9EF93FBAB}.Release|Any CPU.ActiveCfg = Release|Any CPU - {9B4A55F4-D9A4-4FC3-8D85-02A9EF93FBAB}.Release|Any CPU.Build.0 = Release|Any CPU - {9B4A55F4-D9A4-4FC3-8D85-02A9EF93FBAB}.Release|x64.ActiveCfg = Release|Any CPU - {9B4A55F4-D9A4-4FC3-8D85-02A9EF93FBAB}.Release|x64.Build.0 = Release|Any CPU - {9B4A55F4-D9A4-4FC3-8D85-02A9EF93FBAB}.Release|x86.ActiveCfg = Release|Any CPU - {9B4A55F4-D9A4-4FC3-8D85-02A9EF93FBAB}.Release|x86.Build.0 = Release|Any CPU {79FEF326-CA5E-4698-B2BA-C16A4580B4D5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {79FEF326-CA5E-4698-B2BA-C16A4580B4D5}.Debug|Any CPU.Build.0 = Debug|Any CPU {79FEF326-CA5E-4698-B2BA-C16A4580B4D5}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -357,6 +295,18 @@ Global {7DA5B308-D950-4496-93D5-21D6C4D91644}.Release|x64.Build.0 = Release|Any CPU {7DA5B308-D950-4496-93D5-21D6C4D91644}.Release|x86.ActiveCfg = Release|Any CPU {7DA5B308-D950-4496-93D5-21D6C4D91644}.Release|x86.Build.0 = Release|Any CPU + {A4823E14-C0E5-4A4D-B28F-27424C25C3C7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A4823E14-C0E5-4A4D-B28F-27424C25C3C7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A4823E14-C0E5-4A4D-B28F-27424C25C3C7}.Debug|x64.ActiveCfg = Debug|Any CPU + {A4823E14-C0E5-4A4D-B28F-27424C25C3C7}.Debug|x64.Build.0 = Debug|Any CPU + {A4823E14-C0E5-4A4D-B28F-27424C25C3C7}.Debug|x86.ActiveCfg = Debug|Any CPU + {A4823E14-C0E5-4A4D-B28F-27424C25C3C7}.Debug|x86.Build.0 = Debug|Any CPU + {A4823E14-C0E5-4A4D-B28F-27424C25C3C7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A4823E14-C0E5-4A4D-B28F-27424C25C3C7}.Release|Any CPU.Build.0 = Release|Any CPU + {A4823E14-C0E5-4A4D-B28F-27424C25C3C7}.Release|x64.ActiveCfg = Release|Any CPU + {A4823E14-C0E5-4A4D-B28F-27424C25C3C7}.Release|x64.Build.0 = Release|Any CPU + {A4823E14-C0E5-4A4D-B28F-27424C25C3C7}.Release|x86.ActiveCfg = Release|Any CPU + {A4823E14-C0E5-4A4D-B28F-27424C25C3C7}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -364,14 +314,9 @@ Global GlobalSection(NestedProjects) = preSolution {BD1C30A8-8FFA-4A92-A9BD-B67B1CDDD84C} = {8CF53B92-5EB1-461D-98F8-70DA9B603FBF} {25F66C64-058A-4D44-BC0C-F12A054F9A91} = {C9809D59-6665-471E-AD87-5AC624C65892} - {A85201C6-6AF8-4B63-8365-08F741050438} = {C9809D59-6665-471E-AD87-5AC624C65892} - {A92B4734-2587-4F6F-97A3-741BE48709A5} = {C9809D59-6665-471E-AD87-5AC624C65892} - {28F8E9E2-FE24-41F7-A888-9FC244A9E2DD} = {C9809D59-6665-471E-AD87-5AC624C65892} - {9A3DEA7E-1681-4D48-AC5C-1F0DE421A203} = {C9809D59-6665-471E-AD87-5AC624C65892} {7FD0A92B-7862-4BB1-932B-B52A9CACB56B} = {8CF53B92-5EB1-461D-98F8-70DA9B603FBF} {FD0AFD44-7A93-4F9E-B5ED-72582392E435} = {C9809D59-6665-471E-AD87-5AC624C65892} {6A811927-3C37-430A-90F4-503E37123956} = {8CF53B92-5EB1-461D-98F8-70DA9B603FBF} - {8B074219-F69A-4E41-83C6-12EE1E647779} = {C9809D59-6665-471E-AD87-5AC624C65892} {D7166C56-178A-4457-B56A-C615C7450DEE} = {8CF53B92-5EB1-461D-98F8-70DA9B603FBF} {C1E5BBB6-6B6A-4DE5-B19D-0538304DE343} = {8CF53B92-5EB1-461D-98F8-70DA9B603FBF} {945871B1-77B8-43FB-B53C-27CF385AB756} = {8CF53B92-5EB1-461D-98F8-70DA9B603FBF} @@ -389,6 +334,7 @@ Global {79FEF326-CA5E-4698-B2BA-C16A4580B4D5} = {C9809D59-6665-471E-AD87-5AC624C65892} {AA003372-CD8D-4DBC-962C-F61E0C93CF05} = {C9809D59-6665-471E-AD87-5AC624C65892} {7DA5B308-D950-4496-93D5-21D6C4D91644} = {C9809D59-6665-471E-AD87-5AC624C65892} + {A4823E14-C0E5-4A4D-B28F-27424C25C3C7} = {94207AA6-4923-4183-A558-E0F8196B8CA3} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {02F2E872-3141-44F5-BD6A-33CD84E9FE08} diff --git a/src/Squidex.Domain.Apps.Entities.MongoDb/Apps/MongoAppRepository.cs b/src/Squidex.Domain.Apps.Entities.MongoDb/Apps/MongoAppRepository.cs index 77fec730e..1adb16a06 100644 --- a/src/Squidex.Domain.Apps.Entities.MongoDb/Apps/MongoAppRepository.cs +++ b/src/Squidex.Domain.Apps.Entities.MongoDb/Apps/MongoAppRepository.cs @@ -28,7 +28,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Apps protected override string CollectionName() { - return "Snapshots_Apps"; + return "States_Apps"; } protected override async Task SetupCollectionAsync(IMongoCollection collection) diff --git a/src/Squidex.Domain.Apps.Entities.MongoDb/Assets/MongoAssetRepository.cs b/src/Squidex.Domain.Apps.Entities.MongoDb/Assets/MongoAssetRepository.cs index 440d82e3f..f632f8d81 100644 --- a/src/Squidex.Domain.Apps.Entities.MongoDb/Assets/MongoAssetRepository.cs +++ b/src/Squidex.Domain.Apps.Entities.MongoDb/Assets/MongoAssetRepository.cs @@ -30,7 +30,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Assets protected override string CollectionName() { - return "Snapshots_Assets"; + return "States_Assets"; } protected override Task SetupCollectionAsync(IMongoCollection collection) diff --git a/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentRepository.cs b/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentRepository.cs index ca185a3c0..05ea8586e 100644 --- a/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentRepository.cs +++ b/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentRepository.cs @@ -45,7 +45,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents protected override string CollectionName() { - return "Snapshots_Contents"; + return "States_Contents"; } protected override async Task SetupCollectionAsync(IMongoCollection collection) @@ -96,7 +96,6 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents try { await Collection.InsertOneAsync(document); - await Collection.UpdateManyAsync(x => x.Id == value.Id && x.Version < value.Version, Update.Set(x => x.IsLatest, false)); } catch (MongoWriteException ex) diff --git a/src/Squidex.Domain.Apps.Entities.MongoDb/Rules/MongoRuleRepository.cs b/src/Squidex.Domain.Apps.Entities.MongoDb/Rules/MongoRuleRepository.cs index 4ad5b8bd8..ff579d0f3 100644 --- a/src/Squidex.Domain.Apps.Entities.MongoDb/Rules/MongoRuleRepository.cs +++ b/src/Squidex.Domain.Apps.Entities.MongoDb/Rules/MongoRuleRepository.cs @@ -28,7 +28,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Rules protected override string CollectionName() { - return "Snapshots_Rules"; + return "States_Rules"; } protected override async Task SetupCollectionAsync(IMongoCollection collection) diff --git a/src/Squidex.Domain.Apps.Entities.MongoDb/Schemas/MongoSchemaRepository.cs b/src/Squidex.Domain.Apps.Entities.MongoDb/Schemas/MongoSchemaRepository.cs index 5f373c18c..9da25e5e7 100644 --- a/src/Squidex.Domain.Apps.Entities.MongoDb/Schemas/MongoSchemaRepository.cs +++ b/src/Squidex.Domain.Apps.Entities.MongoDb/Schemas/MongoSchemaRepository.cs @@ -28,7 +28,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Schemas protected override string CollectionName() { - return "Snapshots_Schemas"; + return "States_Schemas"; } protected override async Task SetupCollectionAsync(IMongoCollection collection) diff --git a/src/Squidex.Domain.Apps.Events/Apps/Utils/AppEventDispatcher.cs b/src/Squidex.Domain.Apps.Events/Apps/Utils/AppEventDispatcher.cs deleted file mode 100644 index 5da60f86e..000000000 --- a/src/Squidex.Domain.Apps.Events/Apps/Utils/AppEventDispatcher.cs +++ /dev/null @@ -1,77 +0,0 @@ -// ========================================================================== -// AppEventDispatcher.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using System.Linq; -using Squidex.Domain.Apps.Core.Apps; - -namespace Squidex.Domain.Apps.Events.Apps.Utils -{ - public static class AppEventDispatcher - { - public static AppContributors Apply(this AppContributors contributors, AppContributorRemoved @event) - { - return contributors.Remove(@event.ContributorId); - } - - public static AppContributors Apply(this AppContributors contributors, AppContributorAssigned @event) - { - return contributors.Assign(@event.ContributorId, @event.Permission); - } - - public static LanguagesConfig Apply(this LanguagesConfig languagesConfig, AppLanguageAdded @event) - { - return languagesConfig.Set(new LanguageConfig(@event.Language)); - } - - public static LanguagesConfig Apply(this LanguagesConfig languagesConfig, AppLanguageRemoved @event) - { - return languagesConfig.Remove(@event.Language); - } - - public static AppClients Apply(this AppClients clients, AppClientAttached @event) - { - return clients.Add(@event.Id, @event.Secret); - } - - public static AppClients Apply(this AppClients clients, AppClientRevoked @event) - { - return clients.Revoke(@event.Id); - } - - public static AppClients Apply(this AppClients clients, AppClientRenamed @event) - { - return clients.Rename(@event.Id, @event.Name); - } - - public static AppClients Apply(this AppClients clients, AppClientUpdated @event) - { - return clients.Update(@event.Id, @event.Permission); - } - - public static LanguagesConfig Apply(this LanguagesConfig languagesConfig, AppLanguageUpdated @event) - { - var fallback = @event.Fallback; - - if (fallback != null && fallback.Count > 0) - { - var existingLangauges = languagesConfig.OfType().Select(x => x.Language); - - fallback = fallback.Intersect(existingLangauges).ToList(); - } - - languagesConfig = languagesConfig.Set(new LanguageConfig(@event.Language, @event.IsOptional, fallback)); - - if (@event.IsMaster) - { - languagesConfig = languagesConfig.MakeMaster(@event.Language); - } - - return languagesConfig; - } - } -} diff --git a/src/Squidex.Domain.Apps.Events/Rules/Utils/RuleEventDispatcher.cs b/src/Squidex.Domain.Apps.Events/Rules/Utils/RuleEventDispatcher.cs deleted file mode 100644 index e85f4eecf..000000000 --- a/src/Squidex.Domain.Apps.Events/Rules/Utils/RuleEventDispatcher.cs +++ /dev/null @@ -1,45 +0,0 @@ -// ========================================================================== -// RuleEventDispatcher.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using Squidex.Domain.Apps.Core.Rules; - -namespace Squidex.Domain.Apps.Events.Rules.Utils -{ - public static class RuleEventDispatcher - { - public static Rule Create(RuleCreated @event) - { - return new Rule(@event.Trigger, @event.Action); - } - - public static Rule Apply(this Rule rule, RuleUpdated @event) - { - if (@event.Trigger != null) - { - return rule.Update(@event.Trigger); - } - - if (@event.Action != null) - { - return rule.Update(@event.Action); - } - - return rule; - } - - public static Rule Apply(this Rule rule, RuleEnabled @event) - { - return rule.Enable(); - } - - public static Rule Apply(this Rule rule, RuleDisabled @event) - { - return rule.Disable(); - } - } -} diff --git a/src/Squidex.Domain.Apps.Events/Schemas/Utils/SchemaEventDispatcher.cs b/src/Squidex.Domain.Apps.Events/Schemas/Utils/SchemaEventDispatcher.cs deleted file mode 100644 index 7deea8e63..000000000 --- a/src/Squidex.Domain.Apps.Events/Schemas/Utils/SchemaEventDispatcher.cs +++ /dev/null @@ -1,133 +0,0 @@ -// ========================================================================== -// SchemaEventDispatcher.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using System; -using Squidex.Domain.Apps.Core; -using Squidex.Domain.Apps.Core.Schemas; - -namespace Squidex.Domain.Apps.Events.Schemas.Utils -{ - public static class SchemaEventDispatcher - { - public static Schema Create(SchemaCreated @event, FieldRegistry registry) - { - var schema = new Schema(@event.Name); - - if (@event.Properties != null) - { - schema = schema.Update(@event.Properties); - } - - if (@event.Fields != null) - { - var fieldId = 1; - - foreach (var eventField in @event.Fields) - { - var partitioning = - string.Equals(eventField.Partitioning, Partitioning.Language.Key, StringComparison.OrdinalIgnoreCase) ? - Partitioning.Language : - Partitioning.Invariant; - - var field = registry.CreateField(fieldId, eventField.Name, partitioning, eventField.Properties); - - if (eventField.IsHidden) - { - field = field.Hide(); - } - - if (eventField.IsDisabled) - { - field = field.Disable(); - } - - if (eventField.IsLocked) - { - field = field.Lock(); - } - - schema = schema.AddField(field); - - fieldId++; - } - } - - return schema; - } - - public static Schema Apply(this Schema schema, FieldAdded @event, FieldRegistry registry) - { - var partitioning = - string.Equals(@event.Partitioning, Partitioning.Language.Key, StringComparison.OrdinalIgnoreCase) ? - Partitioning.Language : - Partitioning.Invariant; - - var field = registry.CreateField(@event.FieldId.Id, @event.Name, partitioning, @event.Properties); - - schema = schema.DeleteField(@event.FieldId.Id); - schema = schema.AddField(field); - - return schema; - } - - public static Schema Apply(this Schema schema, FieldUpdated @event) - { - return schema.UpdateField(@event.FieldId.Id, @event.Properties); - } - - public static Schema Apply(this Schema schema, FieldLocked @event) - { - return schema.LockField(@event.FieldId.Id); - } - - public static Schema Apply(this Schema schema, FieldHidden @event) - { - return schema.HideField(@event.FieldId.Id); - } - - public static Schema Apply(this Schema schema, FieldShown @event) - { - return schema.ShowField(@event.FieldId.Id); - } - - public static Schema Apply(this Schema schema, FieldDisabled @event) - { - return schema.DisableField(@event.FieldId.Id); - } - - public static Schema Apply(this Schema schema, FieldEnabled @event) - { - return schema.EnableField(@event.FieldId.Id); - } - - public static Schema Apply(this Schema schema, SchemaUpdated @event) - { - return schema.Update(@event.Properties); - } - - public static Schema Apply(this Schema schema, SchemaFieldsReordered @event) - { - return schema.ReorderFields(@event.FieldIds); - } - - public static Schema Apply(this Schema schema, FieldDeleted @event) - { - return schema.DeleteField(@event.FieldId.Id); - } - - public static Schema Apply(this Schema schema, SchemaPublished @event) - { - return schema.Publish(); - } - - public static Schema Apply(this Schema schema, SchemaUnpublished @event) - { - return schema.Unpublish(); - } - } -} diff --git a/src/Squidex.Domain.Apps.Read/Apps/AppEntityExtensions.cs b/src/Squidex.Domain.Apps.Read/Apps/AppEntityExtensions.cs deleted file mode 100644 index 39fe7824b..000000000 --- a/src/Squidex.Domain.Apps.Read/Apps/AppEntityExtensions.cs +++ /dev/null @@ -1,20 +0,0 @@ -// ========================================================================== -// AppEntityExtensions.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using Squidex.Domain.Apps.Core; - -namespace Squidex.Domain.Apps.Read.Apps -{ - public static class AppEntityExtensions - { - public static PartitionResolver PartitionResolver(this IAppEntity entity) - { - return entity.LanguagesConfig.ToResolver(); - } - } -} diff --git a/src/Squidex.Domain.Apps.Read/Apps/AppHistoryEventsCreator.cs b/src/Squidex.Domain.Apps.Read/Apps/AppHistoryEventsCreator.cs deleted file mode 100644 index 2e677ba59..000000000 --- a/src/Squidex.Domain.Apps.Read/Apps/AppHistoryEventsCreator.cs +++ /dev/null @@ -1,145 +0,0 @@ -// ========================================================================== -// AppHistoryEventsCreator.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using System.Threading.Tasks; -using Squidex.Domain.Apps.Events.Apps; -using Squidex.Domain.Apps.Read.History; -using Squidex.Infrastructure; -using Squidex.Infrastructure.Dispatching; -using Squidex.Infrastructure.EventSourcing; - -namespace Squidex.Domain.Apps.Read.Apps -{ - public class AppHistoryEventsCreator : HistoryEventsCreatorBase - { - public AppHistoryEventsCreator(TypeNameRegistry typeNameRegistry) - : base(typeNameRegistry) - { - AddEventMessage( - "assigned {user:[Contributor]} as [Permission]"); - - AddEventMessage( - "removed {user:[Contributor]} from app"); - - AddEventMessage( - "added client {[Id]} to app"); - - AddEventMessage( - "revoked client {[Id]}"); - - AddEventMessage( - "updated client {[Id]}"); - - AddEventMessage( - "renamed client {[Id]} to {[Name]}"); - - AddEventMessage( - "added language {[Language]}"); - - AddEventMessage( - "removed language {[Language]}"); - - AddEventMessage( - "updated language {[Language]}"); - - AddEventMessage( - "changed master language to {[Language]}"); - } - - protected Task On(AppContributorRemoved @event, EnvelopeHeaders headers) - { - const string channel = "settings.contributors"; - - return Task.FromResult( - ForEvent(@event, channel) - .AddParameter("Contributor", @event.ContributorId)); - } - - protected Task On(AppContributorAssigned @event, EnvelopeHeaders headers) - { - const string channel = "settings.contributors"; - - return Task.FromResult( - ForEvent(@event, channel) - .AddParameter("Contributor", @event.ContributorId).AddParameter("Permission", @event.Permission)); - } - - protected Task On(AppClientAttached @event, EnvelopeHeaders headers) - { - const string channel = "settings.clients"; - - return Task.FromResult( - ForEvent(@event, channel) - .AddParameter("Id", @event.Id)); - } - - protected Task On(AppClientRevoked @event, EnvelopeHeaders headers) - { - const string channel = "settings.clients"; - - return Task.FromResult( - ForEvent(@event, channel) - .AddParameter("Id", @event.Id)); - } - - protected Task On(AppClientRenamed @event, EnvelopeHeaders headers) - { - const string channel = "settings.clients"; - - return Task.FromResult( - ForEvent(@event, channel) - .AddParameter("Id", @event.Id).AddParameter("Name", ClientName(@event))); - } - - protected Task On(AppLanguageAdded @event, EnvelopeHeaders headers) - { - const string channel = "settings.languages"; - - return Task.FromResult( - ForEvent(@event, channel) - .AddParameter("Language", @event.Language)); - } - - protected Task On(AppLanguageRemoved @event, EnvelopeHeaders headers) - { - const string channel = "settings.languages"; - - return Task.FromResult( - ForEvent(@event, channel) - .AddParameter("Language", @event.Language)); - } - - protected Task On(AppLanguageUpdated @event, EnvelopeHeaders headers) - { - const string channel = "settings.languages"; - - return Task.FromResult( - ForEvent(@event, channel) - .AddParameter("Language", @event.Language)); - } - - protected Task On(AppMasterLanguageSet @event, EnvelopeHeaders headers) - { - const string channel = "settings.languages"; - - return Task.FromResult( - ForEvent(@event, channel) - .AddParameter("Language", @event.Language)); - } - - protected override Task CreateEventCoreAsync(Envelope @event) - { - return this.DispatchFuncAsync(@event.Payload, @event.Headers, (HistoryEventToStore)null); - } - - private static string ClientName(AppClientRenamed @event) - { - return !string.IsNullOrWhiteSpace(@event.Name) ? @event.Name : @event.Id; - } - } -} \ No newline at end of file diff --git a/src/Squidex.Domain.Apps.Read/Apps/IAppEntity.cs b/src/Squidex.Domain.Apps.Read/Apps/IAppEntity.cs deleted file mode 100644 index df1743d69..000000000 --- a/src/Squidex.Domain.Apps.Read/Apps/IAppEntity.cs +++ /dev/null @@ -1,29 +0,0 @@ -// ========================================================================== -// IAppEntity.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 IAppEntity : IEntity, IEntityWithVersion - { - string Etag { get; } - - string Name { get; } - - string PlanId { get; } - - string PlanOwner { get; } - - AppClients Clients { get; } - - AppContributors Contributors { get; } - - LanguagesConfig LanguagesConfig { get; } - } -} diff --git a/src/Squidex.Domain.Apps.Read/Apps/Services/IAppLimitsPlan.cs b/src/Squidex.Domain.Apps.Read/Apps/Services/IAppLimitsPlan.cs deleted file mode 100644 index 3bc0a0012..000000000 --- a/src/Squidex.Domain.Apps.Read/Apps/Services/IAppLimitsPlan.cs +++ /dev/null @@ -1,25 +0,0 @@ -// ========================================================================== -// IAppLimitsPlan.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -namespace Squidex.Domain.Apps.Read.Apps.Services -{ - public interface IAppLimitsPlan - { - string Id { get; } - - string Name { get; } - - string Costs { get; } - - long MaxApiCalls { get; } - - long MaxAssetSize { get; } - - int MaxContributors { get; } - } -} \ No newline at end of file diff --git a/src/Squidex.Domain.Apps.Read/Apps/Services/IAppPlanBillingManager.cs b/src/Squidex.Domain.Apps.Read/Apps/Services/IAppPlanBillingManager.cs deleted file mode 100644 index ebb189b2e..000000000 --- a/src/Squidex.Domain.Apps.Read/Apps/Services/IAppPlanBillingManager.cs +++ /dev/null @@ -1,22 +0,0 @@ -// ========================================================================== -// IAppPlanBillingManager.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using System; -using System.Threading.Tasks; - -namespace Squidex.Domain.Apps.Read.Apps.Services -{ - public interface IAppPlanBillingManager - { - bool HasPortal { get; } - - Task ChangePlanAsync(string userId, Guid appId, string appName, string planId); - - Task GetPortalLinkAsync(string userId); - } -} diff --git a/src/Squidex.Domain.Apps.Read/Apps/Services/IAppPlansProvider.cs b/src/Squidex.Domain.Apps.Read/Apps/Services/IAppPlansProvider.cs deleted file mode 100644 index 5128fdfb2..000000000 --- a/src/Squidex.Domain.Apps.Read/Apps/Services/IAppPlansProvider.cs +++ /dev/null @@ -1,27 +0,0 @@ -// ========================================================================== -// IAppPlansProvider.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using System.Collections.Generic; - -namespace Squidex.Domain.Apps.Read.Apps.Services -{ - public interface IAppPlansProvider - { - IEnumerable GetAvailablePlans(); - - bool IsConfiguredPlan(string planId); - - IAppLimitsPlan GetPlanUpgradeForApp(IAppEntity app); - - IAppLimitsPlan GetPlanUpgrade(string planId); - - IAppLimitsPlan GetPlanForApp(IAppEntity app); - - IAppLimitsPlan GetPlan(string planId); - } -} diff --git a/src/Squidex.Domain.Apps.Read/Apps/Services/IChangePlanResult.cs b/src/Squidex.Domain.Apps.Read/Apps/Services/IChangePlanResult.cs deleted file mode 100644 index 5086dff24..000000000 --- a/src/Squidex.Domain.Apps.Read/Apps/Services/IChangePlanResult.cs +++ /dev/null @@ -1,14 +0,0 @@ -// ========================================================================== -// IChangePlanResult.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -namespace Squidex.Domain.Apps.Read.Apps.Services -{ - public interface IChangePlanResult - { - } -} diff --git a/src/Squidex.Domain.Apps.Read/Apps/Services/Implementations/ConfigAppLimitsPlan.cs b/src/Squidex.Domain.Apps.Read/Apps/Services/Implementations/ConfigAppLimitsPlan.cs deleted file mode 100644 index 0ed64ddcb..000000000 --- a/src/Squidex.Domain.Apps.Read/Apps/Services/Implementations/ConfigAppLimitsPlan.cs +++ /dev/null @@ -1,30 +0,0 @@ -// ========================================================================== -// ConfigAppLimitsPlan.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -namespace Squidex.Domain.Apps.Read.Apps.Services.Implementations -{ - public sealed class ConfigAppLimitsPlan : IAppLimitsPlan - { - public string Id { get; set; } - - public string Name { get; set; } - - public string Costs { get; set; } - - public long MaxApiCalls { get; set; } - - public long MaxAssetSize { get; set; } - - public int MaxContributors { get; set; } - - public ConfigAppLimitsPlan Clone() - { - return (ConfigAppLimitsPlan)MemberwiseClone(); - } - } -} \ No newline at end of file diff --git a/src/Squidex.Domain.Apps.Read/Apps/Services/Implementations/ConfigAppPlansProvider.cs b/src/Squidex.Domain.Apps.Read/Apps/Services/Implementations/ConfigAppPlansProvider.cs deleted file mode 100644 index ed2e6181a..000000000 --- a/src/Squidex.Domain.Apps.Read/Apps/Services/Implementations/ConfigAppPlansProvider.cs +++ /dev/null @@ -1,86 +0,0 @@ -// ========================================================================== -// ConfigAppLimitsProvider.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using System; -using System.Collections.Generic; -using System.Linq; -using Squidex.Infrastructure; - -namespace Squidex.Domain.Apps.Read.Apps.Services.Implementations -{ - public sealed class ConfigAppPlansProvider : IAppPlansProvider - { - private static readonly ConfigAppLimitsPlan Infinite = new ConfigAppLimitsPlan - { - Id = "infinite", - Name = "Infinite", - MaxApiCalls = -1, - MaxAssetSize = -1, - MaxContributors = -1 - }; - - private readonly Dictionary plansById; - private readonly List plansList; - - public ConfigAppPlansProvider(IEnumerable config) - { - Guard.NotNull(config, nameof(config)); - - plansList = config.Select(c => c.Clone()).OrderBy(x => x.MaxApiCalls).ToList(); - plansById = plansList.ToDictionary(c => c.Id, StringComparer.OrdinalIgnoreCase); - } - - public IEnumerable GetAvailablePlans() - { - return plansList; - } - - public bool IsConfiguredPlan(string planId) - { - return planId != null && plansById.ContainsKey(planId); - } - - public IAppLimitsPlan GetPlanForApp(IAppEntity app) - { - Guard.NotNull(app, nameof(app)); - - return GetPlan(app.PlanId); - } - - public IAppLimitsPlan GetPlan(string planId) - { - return GetPlanCore(planId); - } - - public IAppLimitsPlan GetPlanUpgradeForApp(IAppEntity app) - { - Guard.NotNull(app, nameof(app)); - - return GetPlanUpgrade(app.PlanId); - } - - public IAppLimitsPlan GetPlanUpgrade(string planId) - { - var plan = GetPlanCore(planId); - - var nextPlanIndex = plansList.IndexOf(plan); - - if (nextPlanIndex >= 0 && nextPlanIndex < plansList.Count - 1) - { - return plansList[nextPlanIndex + 1]; - } - - return null; - } - - private ConfigAppLimitsPlan GetPlanCore(string planId) - { - return plansById.GetOrDefault(planId ?? string.Empty) ?? plansById.Values.FirstOrDefault() ?? Infinite; - } - } -} diff --git a/src/Squidex.Domain.Apps.Read/Apps/Services/Implementations/NoopAppPlanBillingManager.cs b/src/Squidex.Domain.Apps.Read/Apps/Services/Implementations/NoopAppPlanBillingManager.cs deleted file mode 100644 index 5f6bdec01..000000000 --- a/src/Squidex.Domain.Apps.Read/Apps/Services/Implementations/NoopAppPlanBillingManager.cs +++ /dev/null @@ -1,31 +0,0 @@ -// ========================================================================== -// NoopAppPlanBillingManager.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using System; -using System.Threading.Tasks; - -namespace Squidex.Domain.Apps.Read.Apps.Services.Implementations -{ - public sealed class NoopAppPlanBillingManager : IAppPlanBillingManager - { - public bool HasPortal - { - get { return false; } - } - - public Task ChangePlanAsync(string userId, Guid appId, string appName, string planId) - { - return Task.FromResult(PlanChangedResult.Instance); - } - - public Task GetPortalLinkAsync(string userId) - { - return Task.FromResult(string.Empty); - } - } -} diff --git a/src/Squidex.Domain.Apps.Read/Apps/Services/PlanChangeAsyncResult.cs b/src/Squidex.Domain.Apps.Read/Apps/Services/PlanChangeAsyncResult.cs deleted file mode 100644 index 4f57733e8..000000000 --- a/src/Squidex.Domain.Apps.Read/Apps/Services/PlanChangeAsyncResult.cs +++ /dev/null @@ -1,19 +0,0 @@ -// ========================================================================== -// PlanChangeAsyncResult.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -namespace Squidex.Domain.Apps.Read.Apps.Services -{ - public sealed class PlanChangeAsyncResult : IChangePlanResult - { - public static readonly PlanChangeAsyncResult Instance = new PlanChangeAsyncResult(); - - private PlanChangeAsyncResult() - { - } - } -} diff --git a/src/Squidex.Domain.Apps.Read/Apps/Services/PlanChangedResult.cs b/src/Squidex.Domain.Apps.Read/Apps/Services/PlanChangedResult.cs deleted file mode 100644 index 1456823c5..000000000 --- a/src/Squidex.Domain.Apps.Read/Apps/Services/PlanChangedResult.cs +++ /dev/null @@ -1,19 +0,0 @@ -// ========================================================================== -// PlanChangedResult.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -namespace Squidex.Domain.Apps.Read.Apps.Services -{ - public sealed class PlanChangedResult : IChangePlanResult - { - public static readonly PlanChangedResult Instance = new PlanChangedResult(); - - private PlanChangedResult() - { - } - } -} diff --git a/src/Squidex.Domain.Apps.Read/Apps/Services/RedirectToCheckoutResult.cs b/src/Squidex.Domain.Apps.Read/Apps/Services/RedirectToCheckoutResult.cs deleted file mode 100644 index 21b3043d1..000000000 --- a/src/Squidex.Domain.Apps.Read/Apps/Services/RedirectToCheckoutResult.cs +++ /dev/null @@ -1,25 +0,0 @@ -// ========================================================================== -// RedirectToCheckoutResult.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using System; -using Squidex.Infrastructure; - -namespace Squidex.Domain.Apps.Read.Apps.Services -{ - public sealed class RedirectToCheckoutResult : IChangePlanResult - { - public Uri Url { get; } - - public RedirectToCheckoutResult(Uri url) - { - Guard.NotNull(url, nameof(url)); - - Url = url; - } - } -} diff --git a/src/Squidex.Domain.Apps.Read/Assets/IAssetEntity.cs b/src/Squidex.Domain.Apps.Read/Assets/IAssetEntity.cs deleted file mode 100644 index 9a502ed7b..000000000 --- a/src/Squidex.Domain.Apps.Read/Assets/IAssetEntity.cs +++ /dev/null @@ -1,25 +0,0 @@ -// ========================================================================== -// IAssetEntity.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using Squidex.Domain.Apps.Core.ValidateContent; - -namespace Squidex.Domain.Apps.Read.Assets -{ - public interface IAssetEntity : - IEntity, - IEntityWithAppRef, - IEntityWithCreatedBy, - IEntityWithLastModifiedBy, - IEntityWithVersion, - IAssetInfo - { - string MimeType { get; } - - long FileVersion { get; } - } -} diff --git a/src/Squidex.Domain.Apps.Read/Assets/IAssetEventConsumer.cs b/src/Squidex.Domain.Apps.Read/Assets/IAssetEventConsumer.cs deleted file mode 100644 index bd0a6ddb9..000000000 --- a/src/Squidex.Domain.Apps.Read/Assets/IAssetEventConsumer.cs +++ /dev/null @@ -1,16 +0,0 @@ -// ========================================================================== -// IAssetEventConsumer.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using Squidex.Infrastructure.EventSourcing; - -namespace Squidex.Domain.Apps.Read.Assets -{ - public interface IAssetEventConsumer : IEventConsumer - { - } -} diff --git a/src/Squidex.Domain.Apps.Read/Assets/IAssetStatsEntity.cs b/src/Squidex.Domain.Apps.Read/Assets/IAssetStatsEntity.cs deleted file mode 100644 index 05f7b342d..000000000 --- a/src/Squidex.Domain.Apps.Read/Assets/IAssetStatsEntity.cs +++ /dev/null @@ -1,21 +0,0 @@ -// ========================================================================== -// IAssetStatsEntity.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using System; - -namespace Squidex.Domain.Apps.Read.Assets -{ - public interface IAssetStatsEntity - { - DateTime Date { get; } - - long TotalSize { get; } - - long TotalCount { get; } - } -} diff --git a/src/Squidex.Domain.Apps.Read/Assets/Repositories/IAssetRepository.cs b/src/Squidex.Domain.Apps.Read/Assets/Repositories/IAssetRepository.cs deleted file mode 100644 index 48c2ce66e..000000000 --- a/src/Squidex.Domain.Apps.Read/Assets/Repositories/IAssetRepository.cs +++ /dev/null @@ -1,23 +0,0 @@ -// ========================================================================== -// IAssetRepository.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using System; -using System.Collections.Generic; -using System.Threading.Tasks; - -namespace Squidex.Domain.Apps.Read.Assets.Repositories -{ - public interface IAssetRepository - { - Task> QueryAsync(Guid appId, HashSet mimeTypes = null, HashSet ids = null, string query = null, int take = 10, int skip = 0); - - Task FindAssetAsync(Guid id); - - Task CountAsync(Guid appId, HashSet mimeTypes = null, HashSet ids = null, string query = null); - } -} diff --git a/src/Squidex.Domain.Apps.Read/Assets/Repositories/IAssetStatsRepository.cs b/src/Squidex.Domain.Apps.Read/Assets/Repositories/IAssetStatsRepository.cs deleted file mode 100644 index 09159069b..000000000 --- a/src/Squidex.Domain.Apps.Read/Assets/Repositories/IAssetStatsRepository.cs +++ /dev/null @@ -1,21 +0,0 @@ -// ========================================================================== -// IAssetStatsRepository.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using System; -using System.Collections.Generic; -using System.Threading.Tasks; - -namespace Squidex.Domain.Apps.Read.Assets.Repositories -{ - public interface IAssetStatsRepository - { - Task> QueryAsync(Guid appId, DateTime fromDate, DateTime toDate); - - Task GetTotalSizeAsync(Guid appId); - } -} diff --git a/src/Squidex.Domain.Apps.Read/CachingProviderBase.cs b/src/Squidex.Domain.Apps.Read/CachingProviderBase.cs deleted file mode 100644 index 5883b29ab..000000000 --- a/src/Squidex.Domain.Apps.Read/CachingProviderBase.cs +++ /dev/null @@ -1,30 +0,0 @@ -// ========================================================================== -// CachingProviderBase.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using Microsoft.Extensions.Caching.Memory; -using Squidex.Infrastructure; - -namespace Squidex.Domain.Apps.Read -{ - public abstract class CachingProviderBase - { - private readonly IMemoryCache cache; - - protected IMemoryCache Cache - { - get { return cache; } - } - - protected CachingProviderBase(IMemoryCache cache) - { - Guard.NotNull(cache, nameof(cache)); - - this.cache = cache; - } - } -} diff --git a/src/Squidex.Domain.Apps.Read/Contents/ContentHistoryEventsCreator.cs b/src/Squidex.Domain.Apps.Read/Contents/ContentHistoryEventsCreator.cs deleted file mode 100644 index ab734aab4..000000000 --- a/src/Squidex.Domain.Apps.Read/Contents/ContentHistoryEventsCreator.cs +++ /dev/null @@ -1,49 +0,0 @@ -// ========================================================================== -// ContentHistoryEventsCreator.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using System.Threading.Tasks; -using Squidex.Domain.Apps.Events.Contents; -using Squidex.Domain.Apps.Read.History; -using Squidex.Infrastructure; -using Squidex.Infrastructure.EventSourcing; - -namespace Squidex.Domain.Apps.Read.Contents -{ - public sealed class ContentHistoryEventsCreator : HistoryEventsCreatorBase - { - public ContentHistoryEventsCreator(TypeNameRegistry typeNameRegistry) - : base(typeNameRegistry) - { - AddEventMessage( - "created content item."); - - AddEventMessage( - "updated content item."); - - AddEventMessage( - "deleted content item."); - - AddEventMessage( - "changed status of content item to {[Status]}."); - } - - protected override Task CreateEventCoreAsync(Envelope @event) - { - var channel = $"contents.{@event.Headers.AggregateId()}"; - - var result = ForEvent(@event.Payload, channel); - - if (@event.Payload is ContentStatusChanged contentStatusChanged) - { - result = result.AddParameter("Status", contentStatusChanged.Status); - } - - return Task.FromResult(result); - } - } -} diff --git a/src/Squidex.Domain.Apps.Read/Contents/ContentQueryService.cs b/src/Squidex.Domain.Apps.Read/Contents/ContentQueryService.cs deleted file mode 100644 index 46bb4848e..000000000 --- a/src/Squidex.Domain.Apps.Read/Contents/ContentQueryService.cs +++ /dev/null @@ -1,216 +0,0 @@ -// ========================================================================== -// ContentQueryService.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Security.Claims; -using System.Threading.Tasks; -using Microsoft.OData; -using Microsoft.OData.UriParser; -using NodaTime; -using Squidex.Domain.Apps.Core.Contents; -using Squidex.Domain.Apps.Core.Scripting; -using Squidex.Domain.Apps.Read.Apps; -using Squidex.Domain.Apps.Read.Contents.Edm; -using Squidex.Domain.Apps.Read.Contents.Repositories; -using Squidex.Domain.Apps.Read.Schemas; -using Squidex.Infrastructure; -using Squidex.Infrastructure.Reflection; -using Squidex.Infrastructure.Security; - -namespace Squidex.Domain.Apps.Read.Contents -{ - public sealed class ContentQueryService : IContentQueryService - { - private readonly IContentRepository contentRepository; - private readonly IAppProvider appProvider; - private readonly IScriptEngine scriptEngine; - private readonly EdmModelBuilder modelBuilder; - - public ContentQueryService( - IContentRepository contentRepository, - IAppProvider appProvider, - IScriptEngine scriptEngine, - EdmModelBuilder modelBuilder) - { - Guard.NotNull(contentRepository, nameof(contentRepository)); - Guard.NotNull(scriptEngine, nameof(scriptEngine)); - Guard.NotNull(modelBuilder, nameof(modelBuilder)); - Guard.NotNull(appProvider, nameof(appProvider)); - - this.contentRepository = contentRepository; - this.appProvider = appProvider; - this.scriptEngine = scriptEngine; - this.modelBuilder = modelBuilder; - } - - public async Task<(ISchemaEntity Schema, IContentEntity Content)> FindContentAsync(IAppEntity app, string schemaIdOrName, ClaimsPrincipal user, Guid id) - { - Guard.NotNull(app, nameof(app)); - Guard.NotNull(user, nameof(user)); - Guard.NotNullOrEmpty(schemaIdOrName, nameof(schemaIdOrName)); - - var isFrontendClient = user.IsInClient("squidex-frontend"); - - var schema = await FindSchemaAsync(app, schemaIdOrName); - - var content = await contentRepository.FindContentAsync(app, schema, id); - - if (content == null || (content.Status != Status.Published && !isFrontendClient)) - { - throw new DomainObjectNotFoundException(id.ToString(), typeof(ISchemaEntity)); - } - - content = TransformContent(user, schema, new List { content })[0]; - - return (schema, content); - } - - public async Task<(ISchemaEntity Schema, long Total, IReadOnlyList Items)> QueryWithCountAsync(IAppEntity app, string schemaIdOrName, ClaimsPrincipal user, bool archived, string query) - { - Guard.NotNull(app, nameof(app)); - Guard.NotNull(user, nameof(user)); - Guard.NotNullOrEmpty(schemaIdOrName, nameof(schemaIdOrName)); - - var schema = await FindSchemaAsync(app, schemaIdOrName); - - var parsedQuery = ParseQuery(app, query, schema); - - var status = ParseStatus(user, archived); - - var taskForItems = contentRepository.QueryAsync(app, schema, status.ToArray(), parsedQuery); - var taskForCount = contentRepository.CountAsync(app, schema, status.ToArray(), parsedQuery); - - await Task.WhenAll(taskForItems, taskForCount); - - var list = TransformContent(user, schema, taskForItems.Result.ToList()); - - return (schema, taskForCount.Result, list); - } - - public async Task<(ISchemaEntity Schema, long Total, IReadOnlyList Items)> QueryWithCountAsync(IAppEntity app, string schemaIdOrName, ClaimsPrincipal user, bool archived, HashSet ids) - { - Guard.NotNull(ids, nameof(ids)); - Guard.NotNull(app, nameof(app)); - Guard.NotNull(user, nameof(user)); - Guard.NotNullOrEmpty(schemaIdOrName, nameof(schemaIdOrName)); - - var schema = await FindSchemaAsync(app, schemaIdOrName); - - var status = ParseStatus(user, archived); - - var taskForItems = contentRepository.QueryAsync(app, schema, status.ToArray(), ids); - var taskForCount = contentRepository.CountAsync(app, schema, status.ToArray(), ids); - - await Task.WhenAll(taskForItems, taskForCount); - - var list = TransformContent(user, schema, taskForItems.Result.ToList()); - - return (schema, taskForCount.Result, list); - } - - private List TransformContent(ClaimsPrincipal user, ISchemaEntity schema, List contents) - { - var scriptText = schema.ScriptQuery; - - if (!string.IsNullOrWhiteSpace(scriptText)) - { - for (var i = 0; i < contents.Count; i++) - { - var content = contents[i]; - var contentData = scriptEngine.Transform(new ScriptContext { User = user, Data = content.Data, ContentId = content.Id }, scriptText); - - contents[i] = SimpleMapper.Map(content, new Content { Data = contentData }); - } - } - - return contents; - } - - private ODataUriParser ParseQuery(IAppEntity app, string query, ISchemaEntity schema) - { - try - { - var model = modelBuilder.BuildEdmModel(schema, app); - - return model.ParseQuery(query); - } - catch (ODataException ex) - { - throw new ValidationException($"Failed to parse query: {ex.Message}", ex); - } - } - - public async Task FindSchemaAsync(IAppEntity app, string schemaIdOrName) - { - Guard.NotNull(app, nameof(app)); - - ISchemaEntity schema = null; - - if (Guid.TryParse(schemaIdOrName, out var id)) - { - schema = await appProvider.GetSchemaAsync(app.Name, id); - } - - if (schema == null) - { - schema = await appProvider.GetSchemaAsync(app.Name, schemaIdOrName); - } - - if (schema == null) - { - throw new DomainObjectNotFoundException(schemaIdOrName, typeof(ISchemaEntity)); - } - - return schema; - } - - private static List ParseStatus(ClaimsPrincipal user, bool archived) - { - var status = new List(); - - if (user.IsInClient("squidex-frontend")) - { - if (archived) - { - status.Add(Status.Archived); - } - else - { - status.Add(Status.Draft); - status.Add(Status.Published); - } - } - else - { - status.Add(Status.Published); - } - - return status; - } - - private sealed class Content : IContentEntity - { - public Guid Id { get; set; } - public Guid AppId { get; set; } - - public long Version { get; set; } - - public Instant Created { get; set; } - public Instant LastModified { get; set; } - - public RefToken CreatedBy { get; set; } - public RefToken LastModifiedBy { get; set; } - - public NamedContentData Data { get; set; } - - public Status Status { get; set; } - } - } -} diff --git a/src/Squidex.Domain.Apps.Read/Contents/Edm/EdmModelBuilder.cs b/src/Squidex.Domain.Apps.Read/Contents/Edm/EdmModelBuilder.cs deleted file mode 100644 index 696d5282d..000000000 --- a/src/Squidex.Domain.Apps.Read/Contents/Edm/EdmModelBuilder.cs +++ /dev/null @@ -1,74 +0,0 @@ -// ========================================================================== -// EdmModelBuilder.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using System; -using Microsoft.Extensions.Caching.Memory; -using Microsoft.OData.Edm; -using Squidex.Domain.Apps.Core; -using Squidex.Domain.Apps.Core.GenerateEdmSchema; -using Squidex.Domain.Apps.Core.Schemas; -using Squidex.Domain.Apps.Read.Apps; -using Squidex.Domain.Apps.Read.Schemas; -using Squidex.Infrastructure; - -namespace Squidex.Domain.Apps.Read.Contents.Edm -{ - public class EdmModelBuilder : CachingProviderBase - { - public EdmModelBuilder(IMemoryCache cache) - : base(cache) - { - } - - public virtual IEdmModel BuildEdmModel(ISchemaEntity schema, IAppEntity app) - { - Guard.NotNull(schema, nameof(schema)); - - var cacheKey = $"{schema.Id}_{schema.Version}_{app.Id}_{app.Version}"; - - var result = Cache.GetOrCreate(cacheKey, entry => - { - entry.AbsoluteExpiration = DateTimeOffset.UtcNow.AddMinutes(60); - - return BuildEdmModel(schema.SchemaDef, app.PartitionResolver()); - }); - - return result; - } - - private static EdmModel BuildEdmModel(Schema schema, PartitionResolver partitionResolver) - { - var model = new EdmModel(); - - var container = new EdmEntityContainer("Squidex", "Container"); - - var schemaType = schema.BuildEdmType(partitionResolver, x => - { - model.AddElement(x); - - return x; - }); - - var entityType = new EdmEntityType("Squidex", schema.Name); - entityType.AddStructuralProperty("data", new EdmComplexTypeReference(schemaType, false)); - entityType.AddStructuralProperty("version", EdmPrimitiveTypeKind.Int32); - entityType.AddStructuralProperty("created", EdmPrimitiveTypeKind.DateTimeOffset); - entityType.AddStructuralProperty("createdBy", EdmPrimitiveTypeKind.String); - entityType.AddStructuralProperty("lastModified", EdmPrimitiveTypeKind.DateTimeOffset); - entityType.AddStructuralProperty("lastModifiedBy", EdmPrimitiveTypeKind.String); - - model.AddElement(container); - model.AddElement(schemaType); - model.AddElement(entityType); - - container.AddEntitySet("ContentSet", entityType); - - return model; - } - } -} diff --git a/src/Squidex.Domain.Apps.Read/Contents/Edm/EdmModelExtensions.cs b/src/Squidex.Domain.Apps.Read/Contents/Edm/EdmModelExtensions.cs deleted file mode 100644 index 7da78c5be..000000000 --- a/src/Squidex.Domain.Apps.Read/Contents/Edm/EdmModelExtensions.cs +++ /dev/null @@ -1,39 +0,0 @@ -// ========================================================================== -// EdmModelExtensions.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using System; -using System.Linq; -using Microsoft.OData.Edm; -using Microsoft.OData.UriParser; - -namespace Squidex.Domain.Apps.Read.Contents.Edm -{ - public static class EdmModelExtensions - { - public static ODataUriParser ParseQuery(this IEdmModel model, string query) - { - if (!model.EntityContainer.EntitySets().Any()) - { - return null; - } - - query = query ?? string.Empty; - - var path = model.EntityContainer.EntitySets().First().Path.Path.Split('.').Last(); - - if (query.StartsWith("?", StringComparison.Ordinal)) - { - query = query.Substring(1); - } - - var parser = new ODataUriParser(model, new Uri($"{path}?{query}", UriKind.Relative)); - - return parser; - } - } -} diff --git a/src/Squidex.Domain.Apps.Read/Contents/GraphQL/CachingGraphQLService.cs b/src/Squidex.Domain.Apps.Read/Contents/GraphQL/CachingGraphQLService.cs deleted file mode 100644 index 17d31bb7d..000000000 --- a/src/Squidex.Domain.Apps.Read/Contents/GraphQL/CachingGraphQLService.cs +++ /dev/null @@ -1,85 +0,0 @@ -// ========================================================================== -// CachingGraphQLService.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using System; -using System.Linq; -using System.Security.Claims; -using System.Threading.Tasks; -using Microsoft.Extensions.Caching.Memory; -using Squidex.Domain.Apps.Read.Apps; -using Squidex.Domain.Apps.Read.Assets.Repositories; -using Squidex.Infrastructure; - -namespace Squidex.Domain.Apps.Read.Contents.GraphQL -{ - public sealed class CachingGraphQLService : CachingProviderBase, IGraphQLService - { - private static readonly TimeSpan CacheDuration = TimeSpan.FromMinutes(60); - private readonly IContentQueryService contentQuery; - private readonly IGraphQLUrlGenerator urlGenerator; - private readonly IAssetRepository assetRepository; - private readonly IAppProvider appProvider; - - public CachingGraphQLService(IMemoryCache cache, - IAppProvider appProvider, - IAssetRepository assetRepository, - IContentQueryService contentQuery, - IGraphQLUrlGenerator urlGenerator) - : base(cache) - { - Guard.NotNull(appProvider, nameof(appProvider)); - Guard.NotNull(assetRepository, nameof(assetRepository)); - Guard.NotNull(contentQuery, nameof(urlGenerator)); - Guard.NotNull(contentQuery, nameof(contentQuery)); - - this.appProvider = appProvider; - this.assetRepository = assetRepository; - this.contentQuery = contentQuery; - this.urlGenerator = urlGenerator; - } - - public async Task<(object Data, object[] Errors)> QueryAsync(IAppEntity app, ClaimsPrincipal user, GraphQLQuery query) - { - Guard.NotNull(app, nameof(app)); - Guard.NotNull(query, nameof(query)); - - if (string.IsNullOrWhiteSpace(query.Query)) - { - return (new object(), new object[0]); - } - - var modelContext = await GetModelAsync(app); - var queryContext = new GraphQLQueryContext(app, assetRepository, contentQuery, user, urlGenerator); - - return await modelContext.ExecuteAsync(queryContext, query); - } - - private async Task GetModelAsync(IAppEntity app) - { - var cacheKey = CreateCacheKey(app.Id, app.Etag); - - var modelContext = Cache.Get(cacheKey); - - if (modelContext == null) - { - var allSchemas = await appProvider.GetSchemasAsync(app.Name); - - modelContext = new GraphQLModel(app, allSchemas.Where(x => x.IsPublished), urlGenerator); - - Cache.Set(cacheKey, modelContext, CacheDuration); - } - - return modelContext; - } - - private static object CreateCacheKey(Guid appId, string etag) - { - return $"GraphQLModel_{appId}_{etag}"; - } - } -} diff --git a/src/Squidex.Domain.Apps.Read/Contents/GraphQL/GraphQLModel.cs b/src/Squidex.Domain.Apps.Read/Contents/GraphQL/GraphQLModel.cs deleted file mode 100644 index 292cc138b..000000000 --- a/src/Squidex.Domain.Apps.Read/Contents/GraphQL/GraphQLModel.cs +++ /dev/null @@ -1,229 +0,0 @@ -// ========================================================================== -// GraphQLContext.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 GraphQL; -using GraphQL.Resolvers; -using GraphQL.Types; -using Squidex.Domain.Apps.Core; -using Squidex.Domain.Apps.Core.Contents; -using Squidex.Domain.Apps.Core.Schemas; -using Squidex.Domain.Apps.Read.Apps; -using Squidex.Domain.Apps.Read.Assets; -using Squidex.Domain.Apps.Read.Contents.GraphQL.Types; -using Squidex.Domain.Apps.Read.Schemas; -using Squidex.Infrastructure; -using GraphQLSchema = GraphQL.Types.Schema; - -namespace Squidex.Domain.Apps.Read.Contents.GraphQL -{ - public sealed class GraphQLModel : IGraphQLContext - { - private readonly Dictionary> fieldInfos; - private readonly Dictionary schemaTypes = new Dictionary(); - private readonly Dictionary schemas; - private readonly PartitionResolver partitionResolver; - private readonly IAppEntity app; - private readonly IGraphType assetType; - private readonly IGraphType assetListType; - private readonly GraphQLSchema graphQLSchema; - - public bool CanGenerateAssetSourceUrl { get; } - - public GraphQLModel(IAppEntity app, IEnumerable schemas, IGraphQLUrlGenerator urlGenerator) - { - this.app = app; - - CanGenerateAssetSourceUrl = urlGenerator.CanGenerateAssetSourceUrl; - - partitionResolver = app.PartitionResolver(); - - assetType = new AssetGraphType(this); - assetListType = new ListGraphType(new NonNullGraphType(assetType)); - - fieldInfos = new Dictionary> - { - { - typeof(StringField), - field => ResolveDefault("String") - }, - { - typeof(BooleanField), - field => ResolveDefault("Boolean") - }, - { - typeof(NumberField), - field => ResolveDefault("Float") - }, - { - typeof(DateTimeField), - field => ResolveDefault("Date") - }, - { - typeof(JsonField), - field => ResolveDefault("Json") - }, - { - typeof(TagsField), - field => ResolveDefault("String") - }, - { - typeof(GeolocationField), - field => ResolveDefault("Geolocation") - }, - { - typeof(AssetsField), - field => ResolveAssets(assetListType) - }, - { - typeof(ReferencesField), - field => ResolveReferences(field) - } - }; - - this.schemas = schemas.ToDictionary(x => x.Id); - - graphQLSchema = new GraphQLSchema { Query = new ContentQueryGraphType(this, this.schemas.Values) }; - - foreach (var schemaType in schemaTypes.Values) - { - schemaType.Initialize(); - } - } - - private static (IGraphType ResolveType, IFieldResolver Resolver) ResolveDefault(string name) - { - return (new NoopGraphType(name), new FuncFieldResolver(c => c.Source.GetOrDefault(c.FieldName))); - } - - public IFieldResolver ResolveAssetUrl() - { - var resolver = new FuncFieldResolver(c => - { - var context = (GraphQLQueryContext)c.UserContext; - - return context.UrlGenerator.GenerateAssetUrl(app, c.Source); - }); - - return resolver; - } - - public IFieldResolver ResolveAssetSourceUrl() - { - var resolver = new FuncFieldResolver(c => - { - var context = (GraphQLQueryContext)c.UserContext; - - return context.UrlGenerator.GenerateAssetSourceUrl(app, c.Source); - }); - - return resolver; - } - - public IFieldResolver ResolveAssetThumbnailUrl() - { - var resolver = new FuncFieldResolver(c => - { - var context = (GraphQLQueryContext)c.UserContext; - - return context.UrlGenerator.GenerateAssetThumbnailUrl(app, c.Source); - }); - - return resolver; - } - - public IFieldResolver ResolveContentUrl(ISchemaEntity schema) - { - var resolver = new FuncFieldResolver(c => - { - var context = (GraphQLQueryContext)c.UserContext; - - return context.UrlGenerator.GenerateContentUrl(app, schema, c.Source); - }); - - return resolver; - } - - private static ValueTuple ResolveAssets(IGraphType assetListType) - { - var resolver = new FuncFieldResolver(c => - { - var context = (GraphQLQueryContext)c.UserContext; - var contentIds = c.Source.GetOrDefault(c.FieldName); - - return context.GetReferencedAssetsAsync(contentIds); - }); - - return (assetListType, resolver); - } - - private ValueTuple ResolveReferences(Field field) - { - var schemaId = ((ReferencesField)field).Properties.SchemaId; - var schemaType = GetSchemaType(schemaId); - - if (schemaType == null) - { - return (null, null); - } - - var resolver = new FuncFieldResolver(c => - { - var context = (GraphQLQueryContext)c.UserContext; - var contentIds = c.Source.GetOrDefault(c.FieldName); - - return context.GetReferencedContentsAsync(schemaId, contentIds); - }); - - var schemaFieldType = new ListGraphType(new NonNullGraphType(GetSchemaType(schemaId))); - - return (schemaFieldType, resolver); - } - - public async Task<(object Data, object[] Errors)> ExecuteAsync(GraphQLQueryContext context, GraphQLQuery query) - { - Guard.NotNull(context, nameof(context)); - - var result = await new DocumentExecuter().ExecuteAsync(options => - { - options.Query = query.Query; - options.Schema = graphQLSchema; - options.Inputs = query.Variables?.ToInputs() ?? new Inputs(); - options.UserContext = context; - options.OperationName = query.OperationName; - }).ConfigureAwait(false); - - return (result.Data, result.Errors?.Select(x => (object)new { x.Message, x.Locations }).ToArray()); - } - - public IFieldPartitioning ResolvePartition(Partitioning key) - { - return partitionResolver(key); - } - - public IGraphType GetAssetType() - { - return assetType; - } - - public (IGraphType ResolveType, IFieldResolver Resolver) GetGraphType(Field field) - { - return fieldInfos[field.GetType()](field); - } - - public IGraphType GetSchemaType(Guid schemaId) - { - var schema = schemas.GetOrDefault(schemaId); - - return schema != null ? schemaTypes.GetOrAdd(schemaId, k => new ContentGraphType(schema, this)) : null; - } - } -} diff --git a/src/Squidex.Domain.Apps.Read/Contents/GraphQL/GraphQLQuery.cs b/src/Squidex.Domain.Apps.Read/Contents/GraphQL/GraphQLQuery.cs deleted file mode 100644 index 476230a3a..000000000 --- a/src/Squidex.Domain.Apps.Read/Contents/GraphQL/GraphQLQuery.cs +++ /dev/null @@ -1,23 +0,0 @@ -// ========================================================================== -// GraphQLQuery.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using Newtonsoft.Json.Linq; - -namespace Squidex.Domain.Apps.Read.Contents.GraphQL -{ - public class GraphQLQuery - { - public string OperationName { get; set; } - - public string NamedQuery { get; set; } - - public string Query { get; set; } - - public JObject Variables { get; set; } - } -} diff --git a/src/Squidex.Domain.Apps.Read/Contents/GraphQL/GraphQLQueryContext.cs b/src/Squidex.Domain.Apps.Read/Contents/GraphQL/GraphQLQueryContext.cs deleted file mode 100644 index e1abc0316..000000000 --- a/src/Squidex.Domain.Apps.Read/Contents/GraphQL/GraphQLQueryContext.cs +++ /dev/null @@ -1,67 +0,0 @@ -// ========================================================================== -// GraphQLQueryContext.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using System; -using System.Collections.Generic; -using System.Security.Claims; -using System.Threading.Tasks; -using Newtonsoft.Json.Linq; -using Squidex.Domain.Apps.Read.Apps; -using Squidex.Domain.Apps.Read.Assets; -using Squidex.Domain.Apps.Read.Assets.Repositories; - -namespace Squidex.Domain.Apps.Read.Contents.GraphQL -{ - public sealed class GraphQLQueryContext : QueryContext - { - public IGraphQLUrlGenerator UrlGenerator { get; } - - public GraphQLQueryContext(IAppEntity app, IAssetRepository assetRepository, IContentQueryService contentQuery, ClaimsPrincipal user, - IGraphQLUrlGenerator urlGenerator) - : base(app, assetRepository, contentQuery, user) - { - UrlGenerator = urlGenerator; - } - - public Task> GetReferencedAssetsAsync(JToken value) - { - var ids = ParseIds(value); - - return GetReferencedAssetsAsync(ids); - } - - public Task> GetReferencedContentsAsync(Guid schemaId, JToken value) - { - var ids = ParseIds(value); - - return GetReferencedContentsAsync(schemaId, ids); - } - - private static ICollection ParseIds(JToken value) - { - try - { - var result = new List(); - - if (value is JArray) - { - foreach (var id in value) - { - result.Add(Guid.Parse(id.ToString())); - } - } - - return result; - } - catch - { - return new List(); - } - } - } -} diff --git a/src/Squidex.Domain.Apps.Read/Contents/GraphQL/IGraphQLContext.cs b/src/Squidex.Domain.Apps.Read/Contents/GraphQL/IGraphQLContext.cs deleted file mode 100644 index 30e8afdcf..000000000 --- a/src/Squidex.Domain.Apps.Read/Contents/GraphQL/IGraphQLContext.cs +++ /dev/null @@ -1,38 +0,0 @@ -// ========================================================================== -// SchemaGraphType.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using System; -using GraphQL.Resolvers; -using GraphQL.Types; -using Squidex.Domain.Apps.Core; -using Squidex.Domain.Apps.Core.Schemas; -using Squidex.Domain.Apps.Read.Schemas; - -namespace Squidex.Domain.Apps.Read.Contents.GraphQL -{ - public interface IGraphQLContext - { - bool CanGenerateAssetSourceUrl { get; } - - IFieldPartitioning ResolvePartition(Partitioning key); - - IGraphType GetAssetType(); - - IGraphType GetSchemaType(Guid schemaId); - - IFieldResolver ResolveAssetUrl(); - - IFieldResolver ResolveAssetSourceUrl(); - - IFieldResolver ResolveAssetThumbnailUrl(); - - IFieldResolver ResolveContentUrl(ISchemaEntity schema); - - (IGraphType ResolveType, IFieldResolver Resolver) GetGraphType(Field field); - } -} diff --git a/src/Squidex.Domain.Apps.Read/Contents/GraphQL/IGraphQLService.cs b/src/Squidex.Domain.Apps.Read/Contents/GraphQL/IGraphQLService.cs deleted file mode 100644 index 1181813c3..000000000 --- a/src/Squidex.Domain.Apps.Read/Contents/GraphQL/IGraphQLService.cs +++ /dev/null @@ -1,19 +0,0 @@ -// ========================================================================== -// IGraphQLService.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using System.Security.Claims; -using System.Threading.Tasks; -using Squidex.Domain.Apps.Read.Apps; - -namespace Squidex.Domain.Apps.Read.Contents.GraphQL -{ - public interface IGraphQLService - { - Task<(object Data, object[] Errors)> QueryAsync(IAppEntity app, ClaimsPrincipal user, GraphQLQuery query); - } -} diff --git a/src/Squidex.Domain.Apps.Read/Contents/GraphQL/IGraphQLUrlGenerator.cs b/src/Squidex.Domain.Apps.Read/Contents/GraphQL/IGraphQLUrlGenerator.cs deleted file mode 100644 index 849004c0f..000000000 --- a/src/Squidex.Domain.Apps.Read/Contents/GraphQL/IGraphQLUrlGenerator.cs +++ /dev/null @@ -1,27 +0,0 @@ -// ========================================================================== -// IGraphQLUrlGenerator.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using Squidex.Domain.Apps.Read.Apps; -using Squidex.Domain.Apps.Read.Assets; -using Squidex.Domain.Apps.Read.Schemas; - -namespace Squidex.Domain.Apps.Read.Contents.GraphQL -{ - public interface IGraphQLUrlGenerator - { - bool CanGenerateAssetSourceUrl { get; } - - string GenerateAssetUrl(IAppEntity app, IAssetEntity asset); - - string GenerateAssetThumbnailUrl(IAppEntity app, IAssetEntity asset); - - string GenerateAssetSourceUrl(IAppEntity app, IAssetEntity asset); - - string GenerateContentUrl(IAppEntity app, ISchemaEntity schema, IContentEntity content); - } -} diff --git a/src/Squidex.Domain.Apps.Read/Contents/GraphQL/Types/AssetGraphType.cs b/src/Squidex.Domain.Apps.Read/Contents/GraphQL/Types/AssetGraphType.cs deleted file mode 100644 index 4d2b04e26..000000000 --- a/src/Squidex.Domain.Apps.Read/Contents/GraphQL/Types/AssetGraphType.cs +++ /dev/null @@ -1,170 +0,0 @@ -// ========================================================================== -// AssetGraphType.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using System; -using GraphQL.Resolvers; -using GraphQL.Types; -using Squidex.Domain.Apps.Read.Assets; -using Squidex.Infrastructure; - -namespace Squidex.Domain.Apps.Read.Contents.GraphQL.Types -{ - public sealed class AssetGraphType : ObjectGraphType - { - public AssetGraphType(IGraphQLContext context) - { - Name = "AssetDto"; - - AddField(new FieldType - { - Name = "id", - Resolver = Resolver(x => x.Id.ToString()), - ResolvedType = new NonNullGraphType(new StringGraphType()), - Description = "The id of the asset." - }); - - AddField(new FieldType - { - Name = "version", - Resolver = Resolver(x => x.Version), - ResolvedType = new NonNullGraphType(new IntGraphType()), - Description = "The version of the asset." - }); - - AddField(new FieldType - { - Name = "created", - Resolver = Resolver(x => x.Created.ToDateTimeUtc()), - ResolvedType = new NonNullGraphType(new DateGraphType()), - Description = "The date and time when the asset has been created." - }); - - AddField(new FieldType - { - Name = "createdBy", - Resolver = Resolver(x => x.CreatedBy.ToString()), - ResolvedType = new NonNullGraphType(new StringGraphType()), - Description = "The user that has created the asset." - }); - - AddField(new FieldType - { - Name = "lastModified", - Resolver = Resolver(x => x.LastModified.ToDateTimeUtc()), - ResolvedType = new NonNullGraphType(new DateGraphType()), - Description = "The date and time when the asset has been modified last." - }); - - AddField(new FieldType - { - Name = "lastModifiedBy", - Resolver = Resolver(x => x.LastModifiedBy.ToString()), - ResolvedType = new NonNullGraphType(new StringGraphType()), - Description = "The user that has updated the asset last." - }); - - AddField(new FieldType - { - Name = "mimeType", - Resolver = Resolver(x => x.MimeType), - ResolvedType = new NonNullGraphType(new StringGraphType()), - Description = "The mime type." - }); - - AddField(new FieldType - { - Name = "url", - Resolver = context.ResolveAssetUrl(), - ResolvedType = new NonNullGraphType(new StringGraphType()), - Description = "The url to the asset." - }); - - AddField(new FieldType - { - Name = "thumbnailUrl", - Resolver = context.ResolveAssetThumbnailUrl(), - ResolvedType = new StringGraphType(), - Description = "The thumbnail url to the asset." - }); - - AddField(new FieldType - { - Name = "fileName", - Resolver = Resolver(x => x.FileName), - ResolvedType = new NonNullGraphType(new StringGraphType()), - Description = "The file name." - }); - - AddField(new FieldType - { - Name = "fileType", - Resolver = Resolver(x => x.FileName.FileType()), - ResolvedType = new NonNullGraphType(new StringGraphType()), - Description = "The file type." - }); - - AddField(new FieldType - { - Name = "fileSize", - Resolver = Resolver(x => x.FileSize), - ResolvedType = new NonNullGraphType(new IntGraphType()), - Description = "The size of the file in bytes." - }); - - AddField(new FieldType - { - Name = "fileVersion", - Resolver = Resolver(x => x.FileVersion), - ResolvedType = new NonNullGraphType(new IntGraphType()), - Description = "The version of the file." - }); - - AddField(new FieldType - { - Name = "isImage", - Resolver = Resolver(x => x.IsImage), - ResolvedType = new NonNullGraphType(new BooleanGraphType()), - Description = "Determines of the created file is an image." - }); - - AddField(new FieldType - { - Name = "pixelWidth", - Resolver = Resolver(x => x.PixelWidth), - ResolvedType = new IntGraphType(), - Description = "The width of the image in pixels if the asset is an image." - }); - - AddField(new FieldType - { - Name = "pixelHeight", - Resolver = Resolver(x => x.PixelHeight), - ResolvedType = new IntGraphType(), - Description = "The height of the image in pixels if the asset is an image." - }); - - if (context.CanGenerateAssetSourceUrl) - { - AddField(new FieldType - { - Name = "sourceUrl", - Resolver = context.ResolveAssetSourceUrl(), - ResolvedType = new StringGraphType(), - Description = "The source url of the asset." - }); - } - - Description = "An asset"; - } - - private static IFieldResolver Resolver(Func action) - { - return new FuncFieldResolver(c => action(c.Source)); - } - } -} diff --git a/src/Squidex.Domain.Apps.Read/Contents/GraphQL/Types/ContentDataGraphType.cs b/src/Squidex.Domain.Apps.Read/Contents/GraphQL/Types/ContentDataGraphType.cs deleted file mode 100644 index b342efa6b..000000000 --- a/src/Squidex.Domain.Apps.Read/Contents/GraphQL/Types/ContentDataGraphType.cs +++ /dev/null @@ -1,68 +0,0 @@ -// ========================================================================== -// ContentDataGraphType.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using System.Linq; -using GraphQL.Resolvers; -using GraphQL.Types; -using Squidex.Domain.Apps.Core.Contents; -using Squidex.Infrastructure; -using Schema = Squidex.Domain.Apps.Core.Schemas.Schema; - -namespace Squidex.Domain.Apps.Read.Contents.GraphQL.Types -{ - public sealed class ContentDataGraphType : ObjectGraphType - { - public ContentDataGraphType(Schema schema, IGraphQLContext context) - { - var schemaName = schema.Properties.Label.WithFallback(schema.Name); - - Name = $"{schema.Name.ToPascalCase()}DataDto"; - - foreach (var field in schema.Fields.Where(x => !x.IsHidden)) - { - var fieldInfo = context.GetGraphType(field); - - if (fieldInfo.ResolveType != null) - { - var fieldName = field.RawProperties.Label.WithFallback(field.Name); - - var fieldGraphType = new ObjectGraphType - { - Name = $"{schema.Name.ToPascalCase()}Data{field.Name.ToPascalCase()}Dto" - }; - - var partition = context.ResolvePartition(field.Partitioning); - - foreach (var partitionItem in partition) - { - fieldGraphType.AddField(new FieldType - { - Name = partitionItem.Key, - Resolver = fieldInfo.Resolver, - ResolvedType = fieldInfo.ResolveType, - Description = field.RawProperties.Hints - }); - } - - fieldGraphType.Description = $"The structure of the {fieldName} of a {schemaName} content type."; - - var fieldResolver = new FuncFieldResolver(c => c.Source.GetOrDefault(field.Name)); - - AddField(new FieldType - { - Name = field.Name.ToCamelCase(), - Resolver = fieldResolver, - ResolvedType = fieldGraphType - }); - } - } - - Description = $"The structure of a {schemaName} content type."; - } - } -} diff --git a/src/Squidex.Domain.Apps.Read/Contents/GraphQL/Types/ContentGraphType.cs b/src/Squidex.Domain.Apps.Read/Contents/GraphQL/Types/ContentGraphType.cs deleted file mode 100644 index 93019e19d..000000000 --- a/src/Squidex.Domain.Apps.Read/Contents/GraphQL/Types/ContentGraphType.cs +++ /dev/null @@ -1,112 +0,0 @@ -// ========================================================================== -// SchemaGraphType.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using System; -using System.Linq; -using GraphQL.Resolvers; -using GraphQL.Types; -using Squidex.Domain.Apps.Read.Schemas; -using Squidex.Infrastructure; - -namespace Squidex.Domain.Apps.Read.Contents.GraphQL.Types -{ - public sealed class ContentGraphType : ObjectGraphType - { - private readonly ISchemaEntity schema; - private readonly IGraphQLContext context; - - public ContentGraphType(ISchemaEntity schema, IGraphQLContext context) - { - this.context = context; - this.schema = schema; - - Name = $"{schema.Name.ToPascalCase()}Dto"; - } - - public void Initialize() - { - var schemaName = schema.SchemaDef.Properties.Label.WithFallback(schema.Name); - - AddField(new FieldType - { - Name = "id", - Resolver = Resolver(x => x.Id.ToString()), - ResolvedType = new NonNullGraphType(new StringGraphType()), - Description = $"The id of the {schemaName} content." - }); - - AddField(new FieldType - { - Name = "version", - Resolver = Resolver(x => x.Version), - ResolvedType = new NonNullGraphType(new IntGraphType()), - Description = $"The version of the {schemaName} content." - }); - - AddField(new FieldType - { - Name = "created", - Resolver = Resolver(x => x.Created.ToDateTimeUtc()), - ResolvedType = new NonNullGraphType(new DateGraphType()), - Description = $"The date and time when the {schemaName} content has been created." - }); - - AddField(new FieldType - { - Name = "createdBy", - Resolver = Resolver(x => x.CreatedBy.ToString()), - ResolvedType = new NonNullGraphType(new StringGraphType()), - Description = $"The user that has created the {schemaName} content." - }); - - AddField(new FieldType - { - Name = "lastModified", - Resolver = Resolver(x => x.LastModified.ToDateTimeUtc()), - ResolvedType = new NonNullGraphType(new DateGraphType()), - Description = $"The date and time when the {schemaName} content has been modified last." - }); - - AddField(new FieldType - { - Name = "lastModifiedBy", - Resolver = Resolver(x => x.LastModifiedBy.ToString()), - ResolvedType = new NonNullGraphType(new StringGraphType()), - Description = $"The user that has updated the {schemaName} content last." - }); - - AddField(new FieldType - { - Name = "url", - Resolver = context.ResolveContentUrl(schema), - ResolvedType = new NonNullGraphType(new StringGraphType()), - Description = $"The url to the the {schemaName} content." - }); - - var dataType = new ContentDataGraphType(schema.SchemaDef, context); - - if (dataType.Fields.Any()) - { - AddField(new FieldType - { - Name = "data", - Resolver = Resolver(x => x.Data), - ResolvedType = new NonNullGraphType(dataType), - Description = $"The data of the {schemaName} content." - }); - } - - Description = $"The structure of a {schemaName} content type."; - } - - private static IFieldResolver Resolver(Func action) - { - return new FuncFieldResolver(c => action(c.Source)); - } - } -} diff --git a/src/Squidex.Domain.Apps.Read/Contents/GraphQL/Types/ContentQueryGraphType.cs b/src/Squidex.Domain.Apps.Read/Contents/GraphQL/Types/ContentQueryGraphType.cs deleted file mode 100644 index b0e3fb5ba..000000000 --- a/src/Squidex.Domain.Apps.Read/Contents/GraphQL/Types/ContentQueryGraphType.cs +++ /dev/null @@ -1,192 +0,0 @@ -// ========================================================================== -// GraphModelType.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using System; -using System.Collections.Generic; -using System.Linq; -using GraphQL.Resolvers; -using GraphQL.Types; -using Squidex.Domain.Apps.Read.Schemas; -using Squidex.Infrastructure; - -namespace Squidex.Domain.Apps.Read.Contents.GraphQL.Types -{ - public sealed class ContentQueryGraphType : ObjectGraphType - { - public ContentQueryGraphType(IGraphQLContext graphQLContext, IEnumerable schemas) - { - AddAssetFind(graphQLContext); - AddAssetsQuery(graphQLContext); - - foreach (var schema in schemas) - { - var schemaName = schema.SchemaDef.Properties.Label.WithFallback(schema.SchemaDef.Name); - var schemaType = graphQLContext.GetSchemaType(schema.Id); - - AddContentFind(schema, schemaType, schemaName); - AddContentQuery(schema, schemaType, schemaName); - } - - Description = "The app queries."; - } - - private void AddAssetFind(IGraphQLContext graphQLContext) - { - AddField(new FieldType - { - Name = "findAsset", - Arguments = new QueryArguments - { - new QueryArgument(typeof(StringGraphType)) - { - Name = "id", - Description = "The id of the asset.", - DefaultValue = string.Empty - } - }, - ResolvedType = graphQLContext.GetAssetType(), - Resolver = new FuncFieldResolver(c => - { - var context = (GraphQLQueryContext)c.UserContext; - var contentId = Guid.Parse(c.GetArgument("id", Guid.Empty.ToString())); - - return context.FindAssetAsync(contentId); - }), - Description = "Find an asset by id." - }); - } - - private void AddContentFind(ISchemaEntity schema, IGraphType schemaType, string schemaName) - { - AddField(new FieldType - { - Name = $"find{schema.Name.ToPascalCase()}Content", - Arguments = new QueryArguments - { - new QueryArgument(typeof(StringGraphType)) - { - Name = "id", - Description = $"The id of the {schemaName} content.", - DefaultValue = string.Empty - } - }, - ResolvedType = schemaType, - Resolver = new FuncFieldResolver(c => - { - var context = (GraphQLQueryContext)c.UserContext; - var contentId = Guid.Parse(c.GetArgument("id", Guid.Empty.ToString())); - - return context.FindContentAsync(schema.Id, contentId); - }), - Description = $"Find an {schemaName} content by id." - }); - } - - private void AddAssetsQuery(IGraphQLContext graphQLContext) - { - AddField(new FieldType - { - Name = "queryAssets", - Arguments = new QueryArguments - { - new QueryArgument(typeof(IntGraphType)) - { - Name = "top", - Description = "Optional number of assets to take.", - DefaultValue = 20 - }, - new QueryArgument(typeof(IntGraphType)) - { - Name = "skip", - Description = "Optional number of assets to skip.", - DefaultValue = 0 - }, - new QueryArgument(typeof(StringGraphType)) - { - Name = "search", - Description = "Optional query.", - DefaultValue = string.Empty - } - }, - ResolvedType = new ListGraphType(new NonNullGraphType(graphQLContext.GetAssetType())), - Resolver = new FuncFieldResolver(c => - { - var context = (GraphQLQueryContext)c.UserContext; - - var argTop = c.GetArgument("top", 20); - var argSkip = c.GetArgument("skip", 0); - var argQuery = c.GetArgument("search", string.Empty); - - return context.QueryAssetsAsync(argQuery, argSkip, argTop); - }), - Description = "Query assets items." - }); - } - - private void AddContentQuery(ISchemaEntity schema, IGraphType schemaType, string schemaName) - { - AddField(new FieldType - { - Name = $"query{schema.Name.ToPascalCase()}Contents", - Arguments = new QueryArguments - { - new QueryArgument(typeof(IntGraphType)) - { - Name = "top", - Description = "Optional number of contents to take.", - DefaultValue = 20 - }, - new QueryArgument(typeof(IntGraphType)) - { - Name = "skip", - Description = "Optional number of contents to skip.", - DefaultValue = 0 - }, - new QueryArgument(typeof(StringGraphType)) - { - Name = "filter", - Description = "Optional OData filter.", - DefaultValue = string.Empty - }, - new QueryArgument(typeof(StringGraphType)) - { - Name = "search", - Description = "Optional OData full text search.", - DefaultValue = string.Empty - }, - new QueryArgument(typeof(StringGraphType)) - { - Name = "orderby", - Description = "Optional OData order definition.", - DefaultValue = string.Empty - } - }, - ResolvedType = new ListGraphType(new NonNullGraphType(schemaType)), - Resolver = new FuncFieldResolver(c => - { - var context = (GraphQLQueryContext)c.UserContext; - var contentQuery = BuildODataQuery(c); - - return context.QueryContentsAsync(schema.Id.ToString(), contentQuery); - }), - Description = $"Query {schemaName} content items." - }); - } - - private static string BuildODataQuery(ResolveFieldContext c) - { - var odataQuery = "?" + - string.Join("&", - c.Arguments - .Select(x => new { x.Key, Value = x.Value.ToString() }).Where(x => !string.IsNullOrWhiteSpace(x.Value)) - .Select(x => $"${x.Key}={x.Value}")); - - return odataQuery; - } - } -} diff --git a/src/Squidex.Domain.Apps.Read/Contents/GraphQL/Types/NoopGraphType.cs b/src/Squidex.Domain.Apps.Read/Contents/GraphQL/Types/NoopGraphType.cs deleted file mode 100644 index 36218f6eb..000000000 --- a/src/Squidex.Domain.Apps.Read/Contents/GraphQL/Types/NoopGraphType.cs +++ /dev/null @@ -1,37 +0,0 @@ -// ========================================================================== -// NoopGraphType.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using System; -using GraphQL.Language.AST; -using GraphQL.Types; - -namespace Squidex.Domain.Apps.Read.Contents.GraphQL.Types -{ - public sealed class NoopGraphType : ScalarGraphType - { - public NoopGraphType(string name) - { - Name = name; - } - - public override object Serialize(object value) - { - return value; - } - - public override object ParseValue(object value) - { - return value; - } - - public override object ParseLiteral(IValue value) - { - throw new NotSupportedException(); - } - } -} diff --git a/src/Squidex.Domain.Apps.Read/Contents/IContentEntity.cs b/src/Squidex.Domain.Apps.Read/Contents/IContentEntity.cs deleted file mode 100644 index 380335382..000000000 --- a/src/Squidex.Domain.Apps.Read/Contents/IContentEntity.cs +++ /dev/null @@ -1,25 +0,0 @@ -// ========================================================================== -// IContentEntity.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== -// ========================================================================== - -using Squidex.Domain.Apps.Core.Contents; - -namespace Squidex.Domain.Apps.Read.Contents -{ - public interface IContentEntity : - IEntity, - IEntityWithAppRef, - IEntityWithCreatedBy, - IEntityWithLastModifiedBy, - IEntityWithVersion - { - Status Status { get; } - - NamedContentData Data { get; } - } -} diff --git a/src/Squidex.Domain.Apps.Read/Contents/IContentQueryService.cs b/src/Squidex.Domain.Apps.Read/Contents/IContentQueryService.cs deleted file mode 100644 index 0af89adcf..000000000 --- a/src/Squidex.Domain.Apps.Read/Contents/IContentQueryService.cs +++ /dev/null @@ -1,28 +0,0 @@ -// ========================================================================== -// IContentQueryService.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using System; -using System.Collections.Generic; -using System.Security.Claims; -using System.Threading.Tasks; -using Squidex.Domain.Apps.Read.Apps; -using Squidex.Domain.Apps.Read.Schemas; - -namespace Squidex.Domain.Apps.Read.Contents -{ - public interface IContentQueryService - { - Task<(ISchemaEntity Schema, long Total, IReadOnlyList Items)> QueryWithCountAsync(IAppEntity app, string schemaIdOrName, ClaimsPrincipal user, bool archived, HashSet ids); - - Task<(ISchemaEntity Schema, long Total, IReadOnlyList Items)> QueryWithCountAsync(IAppEntity app, string schemaIdOrName, ClaimsPrincipal user, bool archived, string query); - - Task<(ISchemaEntity Schema, IContentEntity Content)> FindContentAsync(IAppEntity app, string schemaIdOrName, ClaimsPrincipal user, Guid id); - - Task FindSchemaAsync(IAppEntity app, string schemaIdOrName); - } -} diff --git a/src/Squidex.Domain.Apps.Read/Contents/QueryContext.cs b/src/Squidex.Domain.Apps.Read/Contents/QueryContext.cs deleted file mode 100644 index 195808e11..000000000 --- a/src/Squidex.Domain.Apps.Read/Contents/QueryContext.cs +++ /dev/null @@ -1,146 +0,0 @@ -// ========================================================================== -// QueryContext.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Linq; -using System.Security.Claims; -using System.Threading.Tasks; -using Squidex.Domain.Apps.Read.Apps; -using Squidex.Domain.Apps.Read.Assets; -using Squidex.Domain.Apps.Read.Assets.Repositories; -using Squidex.Infrastructure; - -namespace Squidex.Domain.Apps.Read.Contents -{ - public class QueryContext - { - private readonly ConcurrentDictionary cachedContents = new ConcurrentDictionary(); - private readonly ConcurrentDictionary cachedAssets = new ConcurrentDictionary(); - private readonly IContentQueryService contentQuery; - private readonly IAssetRepository assetRepository; - private readonly IAppEntity app; - private readonly ClaimsPrincipal user; - - public QueryContext( - IAppEntity app, - IAssetRepository assetRepository, - IContentQueryService contentQuery, - ClaimsPrincipal user) - { - Guard.NotNull(assetRepository, nameof(assetRepository)); - Guard.NotNull(contentQuery, nameof(contentQuery)); - Guard.NotNull(app, nameof(app)); - Guard.NotNull(user, nameof(user)); - - this.assetRepository = assetRepository; - this.contentQuery = contentQuery; - - this.user = user; - - this.app = app; - } - - public async Task FindAssetAsync(Guid id) - { - var asset = cachedAssets.GetOrDefault(id); - - if (asset == null) - { - asset = await assetRepository.FindAssetAsync(id); - - if (asset != null) - { - cachedAssets[asset.Id] = asset; - } - } - - return asset; - } - - public async Task FindContentAsync(Guid schemaId, Guid id) - { - var content = cachedContents.GetOrDefault(id); - - if (content == null) - { - content = (await contentQuery.FindContentAsync(app, schemaId.ToString(), user, id)).Content; - - if (content != null) - { - cachedContents[content.Id] = content; - } - } - - return content; - } - - public async Task> QueryAssetsAsync(string query, int skip = 0, int take = 10) - { - var assets = await assetRepository.QueryAsync(app.Id, null, null, query, take, skip); - - foreach (var asset in assets) - { - cachedAssets[asset.Id] = asset; - } - - return assets; - } - - public async Task> QueryContentsAsync(string schemaIdOrName, string query) - { - var contents = await contentQuery.QueryWithCountAsync(app, schemaIdOrName, user, false, query); - - foreach (var content in contents.Items) - { - cachedContents[content.Id] = content; - } - - return contents.Items; - } - - public async Task> GetReferencedAssetsAsync(ICollection ids) - { - Guard.NotNull(ids, nameof(ids)); - - var notLoadedAssets = new HashSet(ids.Where(id => !cachedAssets.ContainsKey(id))); - - if (notLoadedAssets.Count > 0) - { - var assets = await assetRepository.QueryAsync(app.Id, null, notLoadedAssets, null, int.MaxValue); - - foreach (var asset in assets) - { - cachedAssets[asset.Id] = asset; - } - } - - return ids.Select(id => cachedAssets.GetOrDefault(id)).Where(x => x != null).ToList(); - } - - public async Task> GetReferencedContentsAsync(Guid schemaId, ICollection ids) - { - Guard.NotNull(ids, nameof(ids)); - - var notLoadedContents = new HashSet(ids.Where(id => !cachedContents.ContainsKey(id))); - - if (notLoadedContents.Count > 0) - { - var contents = await contentQuery.QueryWithCountAsync(app, schemaId.ToString(), user, false, notLoadedContents); - - foreach (var content in contents.Items) - { - cachedContents[content.Id] = content; - } - } - - return ids.Select(id => cachedContents.GetOrDefault(id)).Where(x => x != null).ToList(); - } - } -} diff --git a/src/Squidex.Domain.Apps.Read/Contents/Repositories/IContentRepository.cs b/src/Squidex.Domain.Apps.Read/Contents/Repositories/IContentRepository.cs deleted file mode 100644 index 85887ce9a..000000000 --- a/src/Squidex.Domain.Apps.Read/Contents/Repositories/IContentRepository.cs +++ /dev/null @@ -1,33 +0,0 @@ -// ========================================================================== -// IContentRepository.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using System; -using System.Collections.Generic; -using System.Threading.Tasks; -using Microsoft.OData.UriParser; -using Squidex.Domain.Apps.Core.Contents; -using Squidex.Domain.Apps.Read.Apps; -using Squidex.Domain.Apps.Read.Schemas; - -namespace Squidex.Domain.Apps.Read.Contents.Repositories -{ - public interface IContentRepository - { - Task> QueryAsync(IAppEntity app, ISchemaEntity schema, Status[] status, HashSet ids); - - Task> QueryAsync(IAppEntity app, ISchemaEntity schema, Status[] status, ODataUriParser odataQuery); - - Task> QueryNotFoundAsync(Guid appId, Guid schemaId, IList contentIds); - - Task CountAsync(IAppEntity app, ISchemaEntity schema, Status[] status, HashSet ids); - - Task CountAsync(IAppEntity app, ISchemaEntity schema, Status[] status, ODataUriParser odataQuery); - - Task FindContentAsync(IAppEntity app, ISchemaEntity schema, Guid id); - } -} diff --git a/src/Squidex.Domain.Apps.Read/EntityMapper.cs b/src/Squidex.Domain.Apps.Read/EntityMapper.cs deleted file mode 100644 index 9dfe40a6d..000000000 --- a/src/Squidex.Domain.Apps.Read/EntityMapper.cs +++ /dev/null @@ -1,90 +0,0 @@ -// ========================================================================== -// EntityMapper.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using System; -using Squidex.Domain.Apps.Events; -using Squidex.Infrastructure.EventSourcing; - -namespace Squidex.Domain.Apps.Read -{ - public static class EntityMapper - { - public static T Create(SquidexEvent @event, EnvelopeHeaders headers, Action updater = null) where T : IEntity, new() - { - var entity = new T(); - - SetId(headers, entity); - - SetVersion(headers, entity); - SetCreated(headers, entity); - SetCreatedBy(@event, entity); - - SetAppId(@event, entity); - - return entity.Update(@event, headers, updater); - } - - public static T Update(this T entity, SquidexEvent @event, EnvelopeHeaders headers, Action updater = null) where T : IEntity, new() - { - SetVersion(headers, entity); - SetLastModified(headers, entity); - SetLastModifiedBy(@event, entity); - - updater?.Invoke(entity); - - return entity; - } - - private static void SetId(EnvelopeHeaders headers, IEntity entity) - { - entity.Id = headers.AggregateId(); - } - - private static void SetCreated(EnvelopeHeaders headers, IEntity entity) - { - entity.Created = headers.Timestamp(); - } - - private static void SetLastModified(EnvelopeHeaders headers, IEntity entity) - { - entity.LastModified = headers.Timestamp(); - } - - private static void SetVersion(EnvelopeHeaders headers, IEntity entity) - { - if (entity is IUpdateableEntityWithVersion withVersion) - { - withVersion.Version = headers.EventStreamNumber(); - } - } - - private static void SetCreatedBy(SquidexEvent @event, IEntity entity) - { - if (entity is IUpdateableEntityWithCreatedBy withCreatedBy && withCreatedBy) - { - withCreatedBy.CreatedBy = @event.Actor; - } - } - - private static void SetLastModifiedBy(SquidexEvent @event, IEntity entity) - { - if (entity is IUpdateableEntityWithLastModifiedBy withModifiedBy) - { - withModifiedBy.LastModifiedBy = @event.Actor; - } - } - - private static void SetAppId(SquidexEvent @event, IEntity entity) - { - if (entity is IUpdateableEntityWithAppRef app && @event is AppEvent appEvent) - { - app.AppId = appEvent.AppId.Id; - } - } - } -} diff --git a/src/Squidex.Domain.Apps.Read/History/HistoryEventToStore.cs b/src/Squidex.Domain.Apps.Read/History/HistoryEventToStore.cs deleted file mode 100644 index 1ca32b31a..000000000 --- a/src/Squidex.Domain.Apps.Read/History/HistoryEventToStore.cs +++ /dev/null @@ -1,44 +0,0 @@ -// ========================================================================== -// HistoryEventToStore.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using System.Collections.Generic; -using Squidex.Infrastructure; - -namespace Squidex.Domain.Apps.Read.History -{ - public sealed class HistoryEventToStore - { - private readonly Dictionary parameters = new Dictionary(); - - public string Channel { get; } - - public string Message { get; } - - public IReadOnlyDictionary Parameters - { - get { return parameters; } - } - - public HistoryEventToStore(string channel, string message) - { - Guard.NotNullOrEmpty(channel, nameof(channel)); - Guard.NotNullOrEmpty(message, nameof(message)); - - Channel = channel; - - Message = message; - } - - public HistoryEventToStore AddParameter(string key, object value) - { - parameters[key] = value.ToString(); - - return this; - } - } -} diff --git a/src/Squidex.Domain.Apps.Read/History/HistoryEventsCreatorBase.cs b/src/Squidex.Domain.Apps.Read/History/HistoryEventsCreatorBase.cs deleted file mode 100644 index a267d1572..000000000 --- a/src/Squidex.Domain.Apps.Read/History/HistoryEventsCreatorBase.cs +++ /dev/null @@ -1,66 +0,0 @@ -// ========================================================================== -// HistoryEventsCreatorBase.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using System.Collections.Generic; -using System.Threading.Tasks; -using Squidex.Infrastructure; -using Squidex.Infrastructure.EventSourcing; - -namespace Squidex.Domain.Apps.Read.History -{ - public abstract class HistoryEventsCreatorBase : IHistoryEventsCreator - { - private readonly Dictionary texts = new Dictionary(); - private readonly TypeNameRegistry typeNameRegistry; - - public IReadOnlyDictionary Texts - { - get { return texts; } - } - - protected HistoryEventsCreatorBase(TypeNameRegistry typeNameRegistry) - { - Guard.NotNull(typeNameRegistry, nameof(typeNameRegistry)); - - this.typeNameRegistry = typeNameRegistry; - } - - protected void AddEventMessage(string message) where TEvent : IEvent - { - Guard.NotNullOrEmpty(message, nameof(message)); - - texts[typeNameRegistry.GetName()] = message; - } - - protected bool HasEventText(IEvent @event) - { - var message = typeNameRegistry.GetName(@event.GetType()); - - return texts.ContainsKey(message); - } - - protected HistoryEventToStore ForEvent(IEvent @event, string channel) - { - var message = typeNameRegistry.GetName(@event.GetType()); - - return new HistoryEventToStore(channel, message); - } - - public Task CreateEventAsync(Envelope @event) - { - if (HasEventText(@event.Payload)) - { - return CreateEventCoreAsync(@event); - } - - return Task.FromResult(null); - } - - protected abstract Task CreateEventCoreAsync(Envelope @event); - } -} diff --git a/src/Squidex.Domain.Apps.Read/History/IHistoryEventEntity.cs b/src/Squidex.Domain.Apps.Read/History/IHistoryEventEntity.cs deleted file mode 100644 index a9b213b5c..000000000 --- a/src/Squidex.Domain.Apps.Read/History/IHistoryEventEntity.cs +++ /dev/null @@ -1,24 +0,0 @@ -// ========================================================================== -// IHistoryEventEntity.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using System; -using Squidex.Infrastructure; - -namespace Squidex.Domain.Apps.Read.History -{ - public interface IHistoryEventEntity : IEntity - { - Guid EventId { get; } - - RefToken Actor { get; } - - string Message { get; } - - long Version { get; } - } -} diff --git a/src/Squidex.Domain.Apps.Read/History/IHistoryEventsCreator.cs b/src/Squidex.Domain.Apps.Read/History/IHistoryEventsCreator.cs deleted file mode 100644 index 91d37234e..000000000 --- a/src/Squidex.Domain.Apps.Read/History/IHistoryEventsCreator.cs +++ /dev/null @@ -1,21 +0,0 @@ -// ========================================================================== -// IHistoryEventsCreator.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using System.Collections.Generic; -using System.Threading.Tasks; -using Squidex.Infrastructure.EventSourcing; - -namespace Squidex.Domain.Apps.Read.History -{ - public interface IHistoryEventsCreator - { - IReadOnlyDictionary Texts { get; } - - Task CreateEventAsync(Envelope @event); - } -} diff --git a/src/Squidex.Domain.Apps.Read/History/Repositories/IHistoryEventRepository.cs b/src/Squidex.Domain.Apps.Read/History/Repositories/IHistoryEventRepository.cs deleted file mode 100644 index b0875f5d2..000000000 --- a/src/Squidex.Domain.Apps.Read/History/Repositories/IHistoryEventRepository.cs +++ /dev/null @@ -1,19 +0,0 @@ -// ========================================================================== -// IHistoryEventRepository.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using System; -using System.Collections.Generic; -using System.Threading.Tasks; - -namespace Squidex.Domain.Apps.Read.History.Repositories -{ - public interface IHistoryEventRepository - { - Task> QueryByChannelAsync(Guid appId, string channelPrefix, int count); - } -} diff --git a/src/Squidex.Domain.Apps.Read/IAppProvider.cs b/src/Squidex.Domain.Apps.Read/IAppProvider.cs deleted file mode 100644 index 296f8ff2d..000000000 --- a/src/Squidex.Domain.Apps.Read/IAppProvider.cs +++ /dev/null @@ -1,34 +0,0 @@ -// ========================================================================== -// IApps.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using System; -using System.Collections.Generic; -using System.Threading.Tasks; -using Squidex.Domain.Apps.Read.Apps; -using Squidex.Domain.Apps.Read.Rules; -using Squidex.Domain.Apps.Read.Schemas; - -namespace Squidex.Domain.Apps.Read -{ - public interface IAppProvider - { - Task<(IAppEntity, ISchemaEntity)> GetAppWithSchemaAsync(string appName, Guid id); - - Task GetAppAsync(string appName); - - Task GetSchemaAsync(string appName, Guid id, bool provideDeleted = false); - - Task GetSchemaAsync(string appName, string name, bool provideDeleted = false); - - Task> GetSchemasAsync(string appName); - - Task> GetRulesAsync(string appName); - - Task> GetUserApps(string userId); - } -} diff --git a/src/Squidex.Domain.Apps.Read/IEntity.cs b/src/Squidex.Domain.Apps.Read/IEntity.cs deleted file mode 100644 index 89aea8bed..000000000 --- a/src/Squidex.Domain.Apps.Read/IEntity.cs +++ /dev/null @@ -1,22 +0,0 @@ -// ========================================================================== -// IEntity.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using System; -using NodaTime; - -namespace Squidex.Domain.Apps.Read -{ - public interface IEntity - { - Guid Id { get; set; } - - Instant Created { get; set; } - - Instant LastModified { get; set; } - } -} \ No newline at end of file diff --git a/src/Squidex.Domain.Apps.Read/IEntityWithAppRef.cs b/src/Squidex.Domain.Apps.Read/IEntityWithAppRef.cs deleted file mode 100644 index fdd81b0e1..000000000 --- a/src/Squidex.Domain.Apps.Read/IEntityWithAppRef.cs +++ /dev/null @@ -1,17 +0,0 @@ -// ========================================================================== -// IEntityWithAppRef.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using System; - -namespace Squidex.Domain.Apps.Read -{ - public interface IEntityWithAppRef - { - Guid AppId { get; } - } -} \ No newline at end of file diff --git a/src/Squidex.Domain.Apps.Read/IEntityWithCreatedBy.cs b/src/Squidex.Domain.Apps.Read/IEntityWithCreatedBy.cs deleted file mode 100644 index 4661a15ee..000000000 --- a/src/Squidex.Domain.Apps.Read/IEntityWithCreatedBy.cs +++ /dev/null @@ -1,17 +0,0 @@ -// ========================================================================== -// IEntityWithCreatedBy.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using Squidex.Infrastructure; - -namespace Squidex.Domain.Apps.Read -{ - public interface IEntityWithCreatedBy - { - RefToken CreatedBy { get; } - } -} diff --git a/src/Squidex.Domain.Apps.Read/IEntityWithLastModifiedBy.cs b/src/Squidex.Domain.Apps.Read/IEntityWithLastModifiedBy.cs deleted file mode 100644 index eb42b4e93..000000000 --- a/src/Squidex.Domain.Apps.Read/IEntityWithLastModifiedBy.cs +++ /dev/null @@ -1,17 +0,0 @@ -// ========================================================================== -// IEntityWithLastModifiedBy.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using Squidex.Infrastructure; - -namespace Squidex.Domain.Apps.Read -{ - public interface IEntityWithLastModifiedBy - { - RefToken LastModifiedBy { get; set; } - } -} diff --git a/src/Squidex.Domain.Apps.Read/IEntityWithVersion.cs b/src/Squidex.Domain.Apps.Read/IEntityWithVersion.cs deleted file mode 100644 index 860918deb..000000000 --- a/src/Squidex.Domain.Apps.Read/IEntityWithVersion.cs +++ /dev/null @@ -1,15 +0,0 @@ -// ========================================================================== -// IEntityWithVersion.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -namespace Squidex.Domain.Apps.Read -{ - public interface IEntityWithVersion - { - long Version { get; } - } -} diff --git a/src/Squidex.Domain.Apps.Read/IUpdateableEntityWithAppRef.cs b/src/Squidex.Domain.Apps.Read/IUpdateableEntityWithAppRef.cs deleted file mode 100644 index 316962a96..000000000 --- a/src/Squidex.Domain.Apps.Read/IUpdateableEntityWithAppRef.cs +++ /dev/null @@ -1,17 +0,0 @@ -// ========================================================================== -// IUpdateableEntityWithAppRef.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using System; - -namespace Squidex.Domain.Apps.Read -{ - public interface IUpdateableEntityWithAppRef - { - Guid AppId { get; set; } - } -} diff --git a/src/Squidex.Domain.Apps.Read/IUpdateableEntityWithCreatedBy.cs b/src/Squidex.Domain.Apps.Read/IUpdateableEntityWithCreatedBy.cs deleted file mode 100644 index 3675937c4..000000000 --- a/src/Squidex.Domain.Apps.Read/IUpdateableEntityWithCreatedBy.cs +++ /dev/null @@ -1,17 +0,0 @@ -// ========================================================================== -// IUpdateableEntityWithCreatedBy.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using Squidex.Infrastructure; - -namespace Squidex.Domain.Apps.Read -{ - public interface IUpdateableEntityWithCreatedBy - { - RefToken CreatedBy { get; set; } - } -} diff --git a/src/Squidex.Domain.Apps.Read/IUpdateableEntityWithLastModifiedBy.cs b/src/Squidex.Domain.Apps.Read/IUpdateableEntityWithLastModifiedBy.cs deleted file mode 100644 index d1aedc9f4..000000000 --- a/src/Squidex.Domain.Apps.Read/IUpdateableEntityWithLastModifiedBy.cs +++ /dev/null @@ -1,17 +0,0 @@ -// ========================================================================== -// IUpdateableEntityWithLastModifiedBy.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using Squidex.Infrastructure; - -namespace Squidex.Domain.Apps.Read -{ - public interface IUpdateableEntityWithLastModifiedBy - { - RefToken LastModifiedBy { get; set; } - } -} diff --git a/src/Squidex.Domain.Apps.Read/IUpdateableEntityWithVersion.cs b/src/Squidex.Domain.Apps.Read/IUpdateableEntityWithVersion.cs deleted file mode 100644 index 8d08b4c6a..000000000 --- a/src/Squidex.Domain.Apps.Read/IUpdateableEntityWithVersion.cs +++ /dev/null @@ -1,15 +0,0 @@ -// ========================================================================== -// IUpdateableEntityWithVersion.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -namespace Squidex.Domain.Apps.Read -{ - public interface IUpdateableEntityWithVersion - { - long Version { get; set; } - } -} diff --git a/src/Squidex.Domain.Apps.Read/Rules/IRuleEntity.cs b/src/Squidex.Domain.Apps.Read/Rules/IRuleEntity.cs deleted file mode 100644 index b9f1aeaa2..000000000 --- a/src/Squidex.Domain.Apps.Read/Rules/IRuleEntity.cs +++ /dev/null @@ -1,22 +0,0 @@ -// ========================================================================== -// IRuleEntity.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using Squidex.Domain.Apps.Core.Rules; - -namespace Squidex.Domain.Apps.Read.Rules -{ - public interface IRuleEntity : - IEntity, - IEntityWithAppRef, - IEntityWithCreatedBy, - IEntityWithLastModifiedBy, - IEntityWithVersion - { - Rule RuleDef { get; } - } -} diff --git a/src/Squidex.Domain.Apps.Read/Rules/IRuleEventEntity.cs b/src/Squidex.Domain.Apps.Read/Rules/IRuleEventEntity.cs deleted file mode 100644 index 631ad2322..000000000 --- a/src/Squidex.Domain.Apps.Read/Rules/IRuleEventEntity.cs +++ /dev/null @@ -1,29 +0,0 @@ -// ========================================================================== -// IRuleEventEntity.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using NodaTime; -using Squidex.Domain.Apps.Core.HandleRules; -using Squidex.Domain.Apps.Core.Rules; - -namespace Squidex.Domain.Apps.Read.Rules -{ - public interface IRuleEventEntity : IEntity - { - RuleJob Job { get; } - - Instant? NextAttempt { get; } - - RuleJobResult JobResult { get; } - - RuleResult Result { get; } - - int NumCalls { get; } - - string LastDump { get; } - } -} diff --git a/src/Squidex.Domain.Apps.Read/Rules/Repositories/IRuleEventRepository.cs b/src/Squidex.Domain.Apps.Read/Rules/Repositories/IRuleEventRepository.cs deleted file mode 100644 index 2b05e6741..000000000 --- a/src/Squidex.Domain.Apps.Read/Rules/Repositories/IRuleEventRepository.cs +++ /dev/null @@ -1,35 +0,0 @@ -// ========================================================================== -// IRuleEventRepository.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using System; -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; -using NodaTime; -using Squidex.Domain.Apps.Core.HandleRules; -using Squidex.Domain.Apps.Core.Rules; - -namespace Squidex.Domain.Apps.Read.Rules.Repositories -{ - public interface IRuleEventRepository - { - Task EnqueueAsync(RuleJob job, Instant nextAttempt); - - Task EnqueueAsync(Guid id, Instant nextAttempt); - - Task MarkSentAsync(Guid jobId, string dump, RuleResult result, RuleJobResult jobResult, TimeSpan elapsed, Instant? nextCall); - - Task QueryPendingAsync(Instant now, Func callback, CancellationToken cancellationToken = default(CancellationToken)); - - Task CountByAppAsync(Guid appId); - - Task> QueryByAppAsync(Guid appId, int skip = 0, int take = 20); - - Task FindAsync(Guid id); - } -} diff --git a/src/Squidex.Domain.Apps.Read/Rules/RuleDequeuer.cs b/src/Squidex.Domain.Apps.Read/Rules/RuleDequeuer.cs deleted file mode 100644 index b738dfeef..000000000 --- a/src/Squidex.Domain.Apps.Read/Rules/RuleDequeuer.cs +++ /dev/null @@ -1,157 +0,0 @@ -// ========================================================================== -// RuleDequeuer.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using System; -using System.Collections.Concurrent; -using System.Threading; -using System.Threading.Tasks; -using System.Threading.Tasks.Dataflow; -using NodaTime; -using Squidex.Domain.Apps.Core.HandleRules; -using Squidex.Domain.Apps.Core.Rules; -using Squidex.Domain.Apps.Read.Rules.Repositories; -using Squidex.Infrastructure; -using Squidex.Infrastructure.Log; -using Squidex.Infrastructure.Timers; - -namespace Squidex.Domain.Apps.Read.Rules -{ - public sealed class RuleDequeuer : DisposableObjectBase, IExternalSystem - { - private readonly ActionBlock requestBlock; - private readonly IRuleEventRepository ruleEventRepository; - private readonly RuleService ruleService; - private readonly CompletionTimer timer; - private readonly ConcurrentDictionary executing = new ConcurrentDictionary(); - private readonly IClock clock; - private readonly ISemanticLog log; - - public RuleDequeuer(RuleService ruleService, IRuleEventRepository ruleEventRepository, ISemanticLog log, IClock clock) - { - Guard.NotNull(ruleEventRepository, nameof(ruleEventRepository)); - Guard.NotNull(ruleService, nameof(ruleService)); - Guard.NotNull(clock, nameof(clock)); - Guard.NotNull(log, nameof(log)); - - this.ruleEventRepository = ruleEventRepository; - this.ruleService = ruleService; - - this.clock = clock; - - this.log = log; - - requestBlock = - new ActionBlock(HandleAsync, - new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = 32, BoundedCapacity = 32 }); - - timer = new CompletionTimer(5000, QueryAsync); - } - - protected override void DisposeObject(bool disposing) - { - if (disposing) - { - timer.StopAsync().Wait(); - - requestBlock.Complete(); - requestBlock.Completion.Wait(); - } - } - - public void Connect() - { - } - - public void Next() - { - timer.SkipCurrentDelay(); - } - - private async Task QueryAsync(CancellationToken cancellationToken) - { - try - { - var now = clock.GetCurrentInstant(); - - await ruleEventRepository.QueryPendingAsync(now, requestBlock.SendAsync, cancellationToken); - } - catch (Exception ex) - { - log.LogError(ex, w => w - .WriteProperty("action", "QueueWebhookEvents") - .WriteProperty("status", "Failed")); - } - } - - public async Task HandleAsync(IRuleEventEntity @event) - { - if (!executing.TryAdd(@event.Id, false)) - { - return; - } - - try - { - var job = @event.Job; - - var response = await ruleService.InvokeAsync(job.ActionName, job.ActionData); - - var jobInvoke = ComputeJobInvoke(response.Result, @event, job); - var jobResult = ComputeJobResult(response.Result, jobInvoke); - - await ruleEventRepository.MarkSentAsync(@event.Id, response.Dump, response.Result, jobResult, response.Elapsed, jobInvoke); - } - catch (Exception ex) - { - log.LogError(ex, w => w - .WriteProperty("action", "SendWebhookEvent") - .WriteProperty("status", "Failed")); - } - finally - { - executing.TryRemove(@event.Id, out var value); - } - } - - private static RuleJobResult ComputeJobResult(RuleResult result, Instant? nextCall) - { - if (result != RuleResult.Success && !nextCall.HasValue) - { - return RuleJobResult.Failed; - } - else if (result != RuleResult.Success && nextCall.HasValue) - { - return RuleJobResult.Retry; - } - else - { - return RuleJobResult.Success; - } - } - - private static Instant? ComputeJobInvoke(RuleResult result, IRuleEventEntity @event, RuleJob job) - { - if (result != RuleResult.Success) - { - switch (@event.NumCalls) - { - case 0: - return job.Created.Plus(Duration.FromMinutes(5)); - case 1: - return job.Created.Plus(Duration.FromHours(1)); - case 2: - return job.Created.Plus(Duration.FromHours(6)); - case 3: - return job.Created.Plus(Duration.FromHours(12)); - } - } - - return null; - } - } -} diff --git a/src/Squidex.Domain.Apps.Read/Rules/RuleEnqueuer.cs b/src/Squidex.Domain.Apps.Read/Rules/RuleEnqueuer.cs deleted file mode 100644 index 867b13937..000000000 --- a/src/Squidex.Domain.Apps.Read/Rules/RuleEnqueuer.cs +++ /dev/null @@ -1,73 +0,0 @@ -// ========================================================================== -// RuleEnqueuer.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using System.Threading.Tasks; -using Squidex.Domain.Apps.Core.HandleRules; -using Squidex.Domain.Apps.Events; -using Squidex.Domain.Apps.Read.Rules.Repositories; -using Squidex.Infrastructure; -using Squidex.Infrastructure.EventSourcing; -using Squidex.Infrastructure.Tasks; - -namespace Squidex.Domain.Apps.Read.Rules -{ - public sealed class RuleEnqueuer : IEventConsumer - { - private readonly IRuleEventRepository ruleEventRepository; - private readonly IAppProvider appProvider; - private readonly RuleService ruleService; - - public string Name - { - get { return GetType().Name; } - } - - public string EventsFilter - { - get { return ".*"; } - } - - public RuleEnqueuer( - IRuleEventRepository ruleEventRepository, IAppProvider appProvider, - RuleService ruleService) - { - Guard.NotNull(ruleEventRepository, nameof(ruleEventRepository)); - Guard.NotNull(ruleService, nameof(ruleService)); - - Guard.NotNull(appProvider, nameof(appProvider)); - - this.ruleEventRepository = ruleEventRepository; - this.ruleService = ruleService; - - this.appProvider = appProvider; - } - - public Task ClearAsync() - { - return TaskHelper.Done; - } - - public async Task On(Envelope @event) - { - if (@event.Payload is AppEvent appEvent) - { - var rules = await appProvider.GetRulesAsync(appEvent.AppId.Name); - - foreach (var ruleEntity in rules) - { - var job = ruleService.CreateJob(ruleEntity.RuleDef, @event); - - if (job != null) - { - await ruleEventRepository.EnqueueAsync(job, job.Created); - } - } - } - } - } -} \ No newline at end of file diff --git a/src/Squidex.Domain.Apps.Read/Rules/RuleJobResult.cs b/src/Squidex.Domain.Apps.Read/Rules/RuleJobResult.cs deleted file mode 100644 index d8fb997e7..000000000 --- a/src/Squidex.Domain.Apps.Read/Rules/RuleJobResult.cs +++ /dev/null @@ -1,18 +0,0 @@ -// ========================================================================== -// RuleJobResult.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -namespace Squidex.Domain.Apps.Read.Rules -{ - public enum RuleJobResult - { - Pending, - Success, - Retry, - Failed - } -} diff --git a/src/Squidex.Domain.Apps.Read/Schemas/ISchemaEntity.cs b/src/Squidex.Domain.Apps.Read/Schemas/ISchemaEntity.cs deleted file mode 100644 index 3cb98ef78..000000000 --- a/src/Squidex.Domain.Apps.Read/Schemas/ISchemaEntity.cs +++ /dev/null @@ -1,38 +0,0 @@ -// ========================================================================== -// ISchemaEntity.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using Squidex.Domain.Apps.Core.Schemas; - -namespace Squidex.Domain.Apps.Read.Schemas -{ - public interface ISchemaEntity : - IEntity, - IEntityWithAppRef, - IEntityWithCreatedBy, - IEntityWithLastModifiedBy, - IEntityWithVersion - { - string Name { get; } - - bool IsPublished { get; } - - bool IsDeleted { get; } - - string ScriptQuery { get; } - - string ScriptCreate { get; } - - string ScriptUpdate { get; } - - string ScriptDelete { get; } - - string ScriptChange { get; } - - Schema SchemaDef { get; } - } -} diff --git a/src/Squidex.Domain.Apps.Read/Schemas/SchemaHistoryEventsCreator.cs b/src/Squidex.Domain.Apps.Read/Schemas/SchemaHistoryEventsCreator.cs deleted file mode 100644 index 426d97473..000000000 --- a/src/Squidex.Domain.Apps.Read/Schemas/SchemaHistoryEventsCreator.cs +++ /dev/null @@ -1,88 +0,0 @@ -// ========================================================================== -// SchemaHistoryEventsCreator.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using System.Threading.Tasks; -using Squidex.Domain.Apps.Events; -using Squidex.Domain.Apps.Events.Schemas; -using Squidex.Domain.Apps.Read.History; -using Squidex.Infrastructure; -using Squidex.Infrastructure.EventSourcing; - -namespace Squidex.Domain.Apps.Read.Schemas -{ - public sealed class SchemaHistoryEventsCreator : HistoryEventsCreatorBase - { - public SchemaHistoryEventsCreator(TypeNameRegistry typeNameRegistry) - : base(typeNameRegistry) - { - AddEventMessage( - "created schema {[Name]}"); - - AddEventMessage( - "updated schema {[Name]}"); - - AddEventMessage( - "deleted schema {[Name]}"); - - AddEventMessage( - "published schema {[Name]}"); - - AddEventMessage( - "unpublished schema {[Name]}"); - - AddEventMessage( - "reordered fields of schema {[Name]}"); - - AddEventMessage( - "added field {[Field]} to schema {[Name]}"); - - AddEventMessage( - "deleted field {[Field]} from schema {[Name]}"); - - AddEventMessage( - "has locked field {[Field]} of schema {[Name]}"); - - AddEventMessage( - "has hidden field {[Field]} of schema {[Name]}"); - - AddEventMessage( - "has shown field {[Field]} of schema {[Name]}"); - - AddEventMessage( - "disabled field {[Field]} of schema {[Name]}"); - - AddEventMessage( - "disabled field {[Field]} of schema {[Name]}"); - - AddEventMessage( - "has updated field {[Field]} of schema {[Name]}"); - - AddEventMessage( - "deleted field {[Field]} of schema {[Name]}"); - } - - protected override Task CreateEventCoreAsync(Envelope @event) - { - if (@event.Payload is SchemaEvent schemaEvent) - { - var channel = $"schemas.{schemaEvent.SchemaId.Name}"; - - var result = ForEvent(@event.Payload, channel).AddParameter("Name", schemaEvent.SchemaId.Name); - - if (schemaEvent is FieldEvent fieldEvent) - { - result.AddParameter("Field", fieldEvent.FieldId.Name); - } - - return Task.FromResult(result); - } - - return Task.FromResult(null); - } - } -} \ No newline at end of file diff --git a/src/Squidex.Domain.Apps.Read/Squidex.Domain.Apps.Read.csproj b/src/Squidex.Domain.Apps.Read/Squidex.Domain.Apps.Read.csproj deleted file mode 100644 index 58922eba3..000000000 --- a/src/Squidex.Domain.Apps.Read/Squidex.Domain.Apps.Read.csproj +++ /dev/null @@ -1,27 +0,0 @@ - - - netstandard2.0 - - - full - True - - - - - - - - - - - - - - - - - - ..\..\Squidex.ruleset - - diff --git a/src/Squidex.Domain.Apps.Read/State/AppProvider.cs b/src/Squidex.Domain.Apps.Read/State/AppProvider.cs deleted file mode 100644 index 9a4a155d1..000000000 --- a/src/Squidex.Domain.Apps.Read/State/AppProvider.cs +++ /dev/null @@ -1,87 +0,0 @@ -// ========================================================================== -// AppProvider.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.Read.Apps; -using Squidex.Domain.Apps.Read.Rules; -using Squidex.Domain.Apps.Read.Schemas; -using Squidex.Domain.Apps.Read.State.Grains; -using Squidex.Infrastructure; -using Squidex.Infrastructure.States; - -namespace Squidex.Domain.Apps.Read.State -{ - public sealed class AppProvider : IAppProvider - { - private readonly IStateFactory factory; - - public AppProvider(IStateFactory factory) - { - Guard.NotNull(factory, nameof(factory)); - - this.factory = factory; - } - - public async Task GetAppAsync(string appName) - { - var app = await factory.GetSynchronizedAsync(appName); - - return await app.GetAppAsync(); - } - - public async Task<(IAppEntity, ISchemaEntity)> GetAppWithSchemaAsync(string appName, Guid id) - { - var app = await factory.GetSynchronizedAsync(appName); - - return await app.GetAppWithSchemaAsync(id); - } - - public async Task> GetRulesAsync(string appName) - { - var app = await factory.GetSynchronizedAsync(appName); - - return await app.GetRulesAsync(); - } - - public async Task GetSchemaAsync(string appName, Guid id, bool provideDeleted = false) - { - var app = await factory.GetSynchronizedAsync(appName); - - return await app.GetSchemaAsync(id, provideDeleted); - } - - public async Task GetSchemaAsync(string appName, string name, bool provideDeleted = false) - { - var app = await factory.GetSynchronizedAsync(appName); - - return await app.GetSchemaAsync(name, provideDeleted); - } - - public async Task> GetSchemasAsync(string appName) - { - var app = await factory.GetSynchronizedAsync(appName); - - return await app.GetSchemasAsync(); - } - - public async Task> GetUserApps(string userId) - { - var appUser = await factory.GetSynchronizedAsync(userId); - var appNames = await appUser.GetAppNamesAsync(); - - var tasks = appNames.Select(x => GetAppAsync(x)); - - var apps = await Task.WhenAll(tasks); - - return apps.Where(a => a != null && a.Contributors.ContainsKey(userId)).ToList(); - } - } -} diff --git a/src/Squidex.Domain.Apps.Read/State/AppStateEventConsumer.cs b/src/Squidex.Domain.Apps.Read/State/AppStateEventConsumer.cs deleted file mode 100644 index fd142607b..000000000 --- a/src/Squidex.Domain.Apps.Read/State/AppStateEventConsumer.cs +++ /dev/null @@ -1,70 +0,0 @@ -// ========================================================================== -// AppStateEventConsumer.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using System.Threading.Tasks; -using Squidex.Domain.Apps.Events; -using Squidex.Domain.Apps.Events.Apps; -using Squidex.Domain.Apps.Read.State.Grains; -using Squidex.Infrastructure; -using Squidex.Infrastructure.EventSourcing; -using Squidex.Infrastructure.States; -using Squidex.Infrastructure.Tasks; - -namespace Squidex.Domain.Apps.Read.State -{ - public sealed class AppStateEventConsumer : IEventConsumer - { - private readonly IStateFactory factory; - - public string Name - { - get { return typeof(AppStateEventConsumer).Name; } - } - - public string EventsFilter - { - get { return @"(^app-)|(^schema-)|(^rule\-)"; } - } - - public AppStateEventConsumer(IStateFactory factory) - { - Guard.NotNull(factory, nameof(factory)); - - this.factory = factory; - } - - public Task ClearAsync() - { - return TaskHelper.Done; - } - - public async Task On(Envelope @event) - { - if (@event.Payload is AppEvent appEvent) - { - var appGrain = await factory.GetSynchronizedAsync(appEvent.AppId.Name); - - await appGrain.HandleAsync(@event); - } - - if (@event.Payload is AppContributorAssigned contributorAssigned) - { - var userGrain = await factory.GetSynchronizedAsync(contributorAssigned.ContributorId); - - await userGrain.AddAppAsync(contributorAssigned.AppId.Name); - } - - if (@event.Payload is AppContributorRemoved contributorRemoved) - { - var userGrain = await factory.GetSynchronizedAsync(contributorRemoved.ContributorId); - - await userGrain.RemoveAppAsync(contributorRemoved.AppId.Name); - } - } - } -} diff --git a/src/Squidex.Domain.Apps.Read/State/Grains/AppStateGrain.cs b/src/Squidex.Domain.Apps.Read/State/Grains/AppStateGrain.cs deleted file mode 100644 index bca5cd380..000000000 --- a/src/Squidex.Domain.Apps.Read/State/Grains/AppStateGrain.cs +++ /dev/null @@ -1,134 +0,0 @@ -// ========================================================================== -// AppStateGrain.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using System; -using System.Collections.Generic; -using System.Threading.Tasks; -using Squidex.Domain.Apps.Core.Schemas; -using Squidex.Domain.Apps.Events; -using Squidex.Domain.Apps.Events.Apps; -using Squidex.Domain.Apps.Read.Apps; -using Squidex.Domain.Apps.Read.Rules; -using Squidex.Domain.Apps.Read.Schemas; -using Squidex.Infrastructure; -using Squidex.Infrastructure.EventSourcing; -using Squidex.Infrastructure.States; - -namespace Squidex.Domain.Apps.Read.State.Grains -{ - public class AppStateGrain : IStatefulObject - { - private readonly FieldRegistry fieldRegistry; - private IPersistence persistence; - private Exception exception; - private AppStateGrainState state; - - public AppStateGrain(FieldRegistry fieldRegistry) - { - Guard.NotNull(fieldRegistry, nameof(fieldRegistry)); - - this.fieldRegistry = fieldRegistry; - } - - public async Task ActivateAsync(string key, IStore store) - { - persistence = store.WithSnapshots(key, s => state = s); - - try - { - await persistence.ReadAsync(); - } - catch (Exception ex) - { - exception = ex; - } - - if (state == null) - { - state = new AppStateGrainState(); - } - - state.SetRegistry(fieldRegistry); - } - - public virtual Task<(IAppEntity, ISchemaEntity)> GetAppWithSchemaAsync(Guid id) - { - var schema = state.FindSchema(x => x.Id == id && !x.IsDeleted); - - return Task.FromResult((state.GetApp(), schema)); - } - - public virtual Task GetAppAsync() - { - var result = state.GetApp(); - - return Task.FromResult(result); - } - - public virtual Task> GetRulesAsync() - { - var result = state.FindRules(); - - return Task.FromResult(result); - } - - public virtual Task> GetSchemasAsync() - { - var result = state.FindSchemas(x => !x.IsDeleted); - - return Task.FromResult(result); - } - - public virtual Task GetSchemaAsync(Guid id, bool provideDeleted = false) - { - var result = state.FindSchema(x => x.Id == id && (!x.IsDeleted || provideDeleted)); - - return Task.FromResult(result); - } - - public virtual Task GetSchemaAsync(string name, bool provideDeleted = false) - { - var result = state.FindSchema(x => string.Equals(x.Name, name, StringComparison.OrdinalIgnoreCase) && (!x.IsDeleted || provideDeleted)); - - return Task.FromResult(result); - } - - public async virtual Task HandleAsync(Envelope message) - { - if (exception != null) - { - if (message.Payload is AppCreated) - { - exception = null; - } - else - { - throw exception; - } - } - - if (message.Payload is AppEvent appEvent && (state.App == null || state.App.Id == appEvent.AppId.Id)) - { - try - { - state = state.Apply(message); - - await persistence.WriteSnapshotAsync(state); - } - catch (InconsistentStateException) - { - await persistence.ReadAsync(); - - state = state.Apply(message); - - await persistence.WriteSnapshotAsync(state); - } - } - } - } -} diff --git a/src/Squidex.Domain.Apps.Read/State/Grains/AppStateGrainState.cs b/src/Squidex.Domain.Apps.Read/State/Grains/AppStateGrainState.cs deleted file mode 100644 index 70803d76a..000000000 --- a/src/Squidex.Domain.Apps.Read/State/Grains/AppStateGrainState.cs +++ /dev/null @@ -1,75 +0,0 @@ -// ========================================================================== -// AppStateGrainState.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Linq; -using Newtonsoft.Json; -using Squidex.Domain.Apps.Core.Schemas; -using Squidex.Domain.Apps.Read.Apps; -using Squidex.Domain.Apps.Read.Rules; -using Squidex.Domain.Apps.Read.Schemas; -using Squidex.Infrastructure; -using Squidex.Infrastructure.Dispatching; -using Squidex.Infrastructure.EventSourcing; - -namespace Squidex.Domain.Apps.Read.State.Grains -{ - public sealed partial class AppStateGrainState : Cloneable - { - private FieldRegistry registry; - - [JsonProperty] - public JsonAppEntity App { get; set; } - - [JsonProperty] - public ImmutableDictionary Rules { get; set; } = ImmutableDictionary.Empty; - - [JsonProperty] - public ImmutableDictionary Schemas { get; set; } = ImmutableDictionary.Empty; - - public void SetRegistry(FieldRegistry registry) - { - this.registry = registry; - } - - public IAppEntity GetApp() - { - return App; - } - - public ISchemaEntity FindSchema(Func filter) - { - return Schemas?.Values.FirstOrDefault(filter); - } - - public List FindSchemas(Func filter) - { - return Schemas?.Values.Where(filter).OfType().ToList() ?? new List(); - } - - public List FindRules() - { - return Rules?.Values.OfType().ToList() ?? new List(); - } - - public AppStateGrainState Apply(Envelope envelope) - { - return Clone(c => - { - c.DispatchAction(envelope.Payload, envelope.Headers); - - if (c.App != null) - { - c.App.Etag = Guid.NewGuid().ToString(); - } - }); - } - } -} \ No newline at end of file diff --git a/src/Squidex.Domain.Apps.Read/State/Grains/AppStateGrainState_Apps.cs b/src/Squidex.Domain.Apps.Read/State/Grains/AppStateGrainState_Apps.cs deleted file mode 100644 index 58789f36c..000000000 --- a/src/Squidex.Domain.Apps.Read/State/Grains/AppStateGrainState_Apps.cs +++ /dev/null @@ -1,117 +0,0 @@ -// ========================================================================== -// AppStateGrainState_Apps.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using System; -using Squidex.Domain.Apps.Core.Apps; -using Squidex.Domain.Apps.Events; -using Squidex.Domain.Apps.Events.Apps; -using Squidex.Domain.Apps.Events.Apps.Utils; -using Squidex.Infrastructure; -using Squidex.Infrastructure.EventSourcing; -using Squidex.Infrastructure.Reflection; - -namespace Squidex.Domain.Apps.Read.State.Grains -{ - public sealed partial class AppStateGrainState - { - public void On(AppCreated @event, EnvelopeHeaders headers) - { - App = EntityMapper.Create(@event, headers, a => - { - SimpleMapper.Map(@event, a); - - a.LanguagesConfig = LanguagesConfig.Build(Language.EN); - }); - } - - public void On(AppLanguageAdded @event, EnvelopeHeaders headers) - { - UpdateApp(@event, headers, a => - { - a.LanguagesConfig = a.LanguagesConfig.Apply(@event); - }); - } - - public void On(AppLanguageRemoved @event, EnvelopeHeaders headers) - { - UpdateApp(@event, headers, a => - { - a.LanguagesConfig = a.LanguagesConfig.Apply(@event); - }); - } - - public void On(AppLanguageUpdated @event, EnvelopeHeaders headers) - { - UpdateApp(@event, headers, a => - { - a.LanguagesConfig = a.LanguagesConfig.Apply(@event); - }); - } - - public void On(AppContributorAssigned @event, EnvelopeHeaders headers) - { - UpdateApp(@event, headers, a => - { - a.Contributors = a.Contributors.Apply(@event); - }); - } - - public void On(AppContributorRemoved @event, EnvelopeHeaders headers) - { - UpdateApp(@event, headers, a => - { - a.Contributors = a.Contributors.Apply(@event); - }); - } - - public void On(AppClientAttached @event, EnvelopeHeaders headers) - { - UpdateApp(@event, headers, a => - { - a.Clients = a.Clients.Apply(@event); - }); - } - - public void On(AppClientUpdated @event, EnvelopeHeaders headers) - { - UpdateApp(@event, headers, a => - { - a.Clients = a.Clients.Apply(@event); - }); - } - - public void On(AppClientRenamed @event, EnvelopeHeaders headers) - { - UpdateApp(@event, headers, a => - { - a.Clients = a.Clients.Apply(@event); - }); - } - - public void On(AppClientRevoked @event, EnvelopeHeaders headers) - { - UpdateApp(@event, headers, a => - { - a.Clients = a.Clients.Apply(@event); - }); - } - - public void On(AppPlanChanged @event, EnvelopeHeaders headers) - { - UpdateApp(@event, headers, a => - { - SimpleMapper.Map(@event, a); - }); - } - - private void UpdateApp(AppEvent @event, EnvelopeHeaders headers, Action updater = null) - { - App = App.Clone().Update(@event, headers, updater); - } - } -} diff --git a/src/Squidex.Domain.Apps.Read/State/Grains/AppStateGrainState_Rules.cs b/src/Squidex.Domain.Apps.Read/State/Grains/AppStateGrainState_Rules.cs deleted file mode 100644 index 2e3626843..000000000 --- a/src/Squidex.Domain.Apps.Read/State/Grains/AppStateGrainState_Rules.cs +++ /dev/null @@ -1,65 +0,0 @@ -// ========================================================================== -// AppStateGrainState_Rules.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using System; -using Squidex.Domain.Apps.Events.Rules; -using Squidex.Domain.Apps.Events.Rules.Utils; -using Squidex.Infrastructure; -using Squidex.Infrastructure.EventSourcing; - -namespace Squidex.Domain.Apps.Read.State.Grains -{ - public sealed partial class AppStateGrainState - { - public void On(RuleCreated @event, EnvelopeHeaders headers) - { - var id = @event.RuleId; - - Rules = Rules.SetItem(id, EntityMapper.Create(@event, headers, r => - { - r.RuleDef = RuleEventDispatcher.Create(@event); - })); - } - - public void On(RuleUpdated @event, EnvelopeHeaders headers) - { - UpdateRule(@event, headers, r => - { - r.RuleDef = r.RuleDef.Apply(@event); - }); - } - - public void On(RuleEnabled @event, EnvelopeHeaders headers) - { - UpdateRule(@event, headers, r => - { - r.RuleDef = r.RuleDef.Apply(@event); - }); - } - - public void On(RuleDisabled @event, EnvelopeHeaders headers) - { - UpdateRule(@event, headers, r => - { - r.RuleDef = r.RuleDef.Apply(@event); - }); - } - - public void On(RuleDeleted @event, EnvelopeHeaders headers) - { - Rules = Rules.Remove(@event.RuleId); - } - - private void UpdateRule(RuleEvent @event, EnvelopeHeaders headers, Action updater = null) - { - var id = @event.RuleId; - - Rules = Rules.SetItem(id, x => x.Clone().Update(@event, headers, updater)); - } - } -} diff --git a/src/Squidex.Domain.Apps.Read/State/Grains/AppStateGrainState_Schemas.cs b/src/Squidex.Domain.Apps.Read/State/Grains/AppStateGrainState_Schemas.cs deleted file mode 100644 index 42ce9ae30..000000000 --- a/src/Squidex.Domain.Apps.Read/State/Grains/AppStateGrainState_Schemas.cs +++ /dev/null @@ -1,162 +0,0 @@ -// ========================================================================== -// AppStateGrainState_Schemas.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using System; -using Squidex.Domain.Apps.Events; -using Squidex.Domain.Apps.Events.Schemas; -using Squidex.Domain.Apps.Events.Schemas.Old; -using Squidex.Domain.Apps.Events.Schemas.Utils; -using Squidex.Infrastructure; -using Squidex.Infrastructure.EventSourcing; -using Squidex.Infrastructure.Reflection; - -#pragma warning disable CS0612 // Type or member is obsolete - -namespace Squidex.Domain.Apps.Read.State.Grains -{ - public sealed partial class AppStateGrainState - { - public void On(SchemaCreated @event, EnvelopeHeaders headers) - { - var id = @event.SchemaId.Id; - - Schemas = Schemas.SetItem(id, EntityMapper.Create(@event, headers, s => - { - s.SchemaDef = SchemaEventDispatcher.Create(@event, registry); - - SimpleMapper.Map(@event, s); - })); - } - - public void On(SchemaPublished @event, EnvelopeHeaders headers) - { - UpdateSchema(@event, headers, s => - { - s.SchemaDef = s.SchemaDef.Apply(@event); - }); - } - - public void On(SchemaUnpublished @event, EnvelopeHeaders headers) - { - UpdateSchema(@event, headers, s => - { - s.SchemaDef = s.SchemaDef.Apply(@event); - }); - } - - public void On(ScriptsConfigured @event, EnvelopeHeaders headers) - { - UpdateSchema(@event, headers, s => - { - SimpleMapper.Map(s, @event); - }); - } - - public void On(SchemaUpdated @event, EnvelopeHeaders headers) - { - UpdateSchema(@event, headers, s => - { - s.SchemaDef = s.SchemaDef.Apply(@event); - }); - } - - public void On(SchemaFieldsReordered @event, EnvelopeHeaders headers) - { - UpdateSchema(@event, headers, s => - { - s.SchemaDef = s.SchemaDef.Apply(@event); - }); - } - - public void On(FieldAdded @event, EnvelopeHeaders headers) - { - UpdateSchema(@event, headers, s => - { - s.SchemaDef = s.SchemaDef.Apply(@event, registry); - }); - } - - public void On(FieldUpdated @event, EnvelopeHeaders headers) - { - UpdateSchema(@event, headers, s => - { - s.SchemaDef = s.SchemaDef.Apply(@event); - }); - } - - public void On(FieldLocked @event, EnvelopeHeaders headers) - { - UpdateSchema(@event, headers, s => - { - s.SchemaDef = s.SchemaDef.Apply(@event); - }); - } - - public void On(FieldDisabled @event, EnvelopeHeaders headers) - { - UpdateSchema(@event, headers, s => - { - s.SchemaDef = s.SchemaDef.Apply(@event); - }); - } - - public void On(FieldEnabled @event, EnvelopeHeaders headers) - { - UpdateSchema(@event, headers, s => - { - s.SchemaDef = s.SchemaDef.Apply(@event); - }); - } - - public void On(FieldHidden @event, EnvelopeHeaders headers) - { - UpdateSchema(@event, headers, s => - { - s.SchemaDef = s.SchemaDef.Apply(@event); - }); - } - - public void On(FieldShown @event, EnvelopeHeaders headers) - { - UpdateSchema(@event, headers, s => - { - s.SchemaDef = s.SchemaDef.Apply(@event); - }); - } - - public void On(FieldDeleted @event, EnvelopeHeaders headers) - { - UpdateSchema(@event, headers, s => - { - s.SchemaDef = s.SchemaDef.Apply(@event); - }); - } - - public void On(WebhookAdded @event, EnvelopeHeaders headers) - { - UpdateSchema(@event, headers); - } - - public void On(WebhookDeleted @event, EnvelopeHeaders headers) - { - UpdateSchema(@event, headers); - } - - public void On(SchemaDeleted @event, EnvelopeHeaders headers) - { - Schemas = Schemas.Remove(@event.SchemaId.Id); - } - - private void UpdateSchema(SchemaEvent @event, EnvelopeHeaders headers, Action updater = null) - { - var id = @event.SchemaId.Id; - - Schemas = Schemas.SetItem(id, x => x.Clone().Update(@event, headers, updater)); - } - } -} diff --git a/src/Squidex.Domain.Apps.Read/State/Grains/AppUserGrain.cs b/src/Squidex.Domain.Apps.Read/State/Grains/AppUserGrain.cs deleted file mode 100644 index 08be064e1..000000000 --- a/src/Squidex.Domain.Apps.Read/State/Grains/AppUserGrain.cs +++ /dev/null @@ -1,48 +0,0 @@ -// ========================================================================== -// AppUserGrain.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using Squidex.Infrastructure.States; -using Squidex.Infrastructure.Tasks; - -namespace Squidex.Domain.Apps.Read.State.Grains -{ - public sealed class AppUserGrain : IStatefulObject - { - private IPersistence persistence; - private AppUserGrainState state = new AppUserGrainState(); - - public Task ActivateAsync(string key, IStore store) - { - persistence = store.WithSnapshots(key, s => state = s); - - return persistence.ReadAsync(); - } - - public Task AddAppAsync(string appName) - { - state = state.AddApp(appName); - - return persistence.WriteSnapshotAsync(state); - } - - public Task RemoveAppAsync(string appName) - { - state = state.RemoveApp(appName); - - return persistence.WriteSnapshotAsync(state); - } - - public Task> GetAppNamesAsync() - { - return Task.FromResult(state.AppNames.ToList()); - } - } -} diff --git a/src/Squidex.Domain.Apps.Read/State/Grains/AppUserGrainState.cs b/src/Squidex.Domain.Apps.Read/State/Grains/AppUserGrainState.cs deleted file mode 100644 index 10da85cb0..000000000 --- a/src/Squidex.Domain.Apps.Read/State/Grains/AppUserGrainState.cs +++ /dev/null @@ -1,30 +0,0 @@ -// ========================================================================== -// AppUserGrainState.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using System.Collections.Immutable; -using Newtonsoft.Json; -using Squidex.Infrastructure; - -namespace Squidex.Domain.Apps.Read.State.Grains -{ - public sealed class AppUserGrainState : Cloneable - { - [JsonProperty] - public ImmutableHashSet AppNames { get; set; } = ImmutableHashSet.Empty; - - public AppUserGrainState AddApp(string appName) - { - return Clone(c => c.AppNames = c.AppNames.Add(appName)); - } - - public AppUserGrainState RemoveApp(string appName) - { - return Clone(c => c.AppNames = c.AppNames.Remove(appName)); - } - } -} diff --git a/src/Squidex.Domain.Apps.Read/State/Grains/JsonAppEntity.cs b/src/Squidex.Domain.Apps.Read/State/Grains/JsonAppEntity.cs deleted file mode 100644 index fbe491584..000000000 --- a/src/Squidex.Domain.Apps.Read/State/Grains/JsonAppEntity.cs +++ /dev/null @@ -1,38 +0,0 @@ -// ========================================================================== -// JsonAppEntity.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using Newtonsoft.Json; -using Squidex.Domain.Apps.Core.Apps; -using Squidex.Domain.Apps.Read.Apps; - -namespace Squidex.Domain.Apps.Read.State.Grains -{ - public sealed class JsonAppEntity : JsonEntity, IAppEntity - { - [JsonProperty] - public string Name { get; set; } - - [JsonProperty] - public string PlanId { get; set; } - - [JsonProperty] - public string Etag { get; set; } - - [JsonProperty] - public string PlanOwner { get; set; } - - [JsonProperty] - public AppClients Clients { get; set; } = AppClients.Empty; - - [JsonProperty] - public AppContributors Contributors { get; set; } = AppContributors.Empty; - - [JsonProperty] - public LanguagesConfig LanguagesConfig { get; set; } - } -} diff --git a/src/Squidex.Domain.Apps.Read/State/Grains/JsonEntity.cs b/src/Squidex.Domain.Apps.Read/State/Grains/JsonEntity.cs deleted file mode 100644 index 94d38176e..000000000 --- a/src/Squidex.Domain.Apps.Read/State/Grains/JsonEntity.cs +++ /dev/null @@ -1,35 +0,0 @@ -// ========================================================================== -// JsonEntity.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using System; -using Newtonsoft.Json; -using NodaTime; -using Squidex.Infrastructure; - -namespace Squidex.Domain.Apps.Read.State.Grains -{ - public abstract class JsonEntity : Cloneable, IUpdateableEntityWithVersion where T : Cloneable - { - [JsonProperty] - public Guid Id { get; set; } - - [JsonProperty] - public Instant Created { get; set; } - - [JsonProperty] - public Instant LastModified { get; set; } - - [JsonProperty] - public long Version { get; set; } - - public T Clone() - { - return Clone(x => { }); - } - } -} diff --git a/src/Squidex.Domain.Apps.Read/State/Grains/JsonRuleEntity.cs b/src/Squidex.Domain.Apps.Read/State/Grains/JsonRuleEntity.cs deleted file mode 100644 index 287d1b2ab..000000000 --- a/src/Squidex.Domain.Apps.Read/State/Grains/JsonRuleEntity.cs +++ /dev/null @@ -1,36 +0,0 @@ -// ========================================================================== -// JsonRuleEntity.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using System; -using Newtonsoft.Json; -using Squidex.Domain.Apps.Core.Rules; -using Squidex.Domain.Apps.Read.Rules; -using Squidex.Infrastructure; - -namespace Squidex.Domain.Apps.Read.State.Grains -{ - public sealed class JsonRuleEntity : - JsonEntity, - IRuleEntity, - IUpdateableEntityWithAppRef, - IUpdateableEntityWithCreatedBy, - IUpdateableEntityWithLastModifiedBy - { - [JsonProperty] - public Guid AppId { get; set; } - - [JsonProperty] - public RefToken CreatedBy { get; set; } - - [JsonProperty] - public RefToken LastModifiedBy { get; set; } - - [JsonProperty] - public Rule RuleDef { get; set; } - } -} diff --git a/src/Squidex.Domain.Apps.Read/State/Grains/JsonSchemaEntity.cs b/src/Squidex.Domain.Apps.Read/State/Grains/JsonSchemaEntity.cs deleted file mode 100644 index 004467008..000000000 --- a/src/Squidex.Domain.Apps.Read/State/Grains/JsonSchemaEntity.cs +++ /dev/null @@ -1,63 +0,0 @@ -// ========================================================================== -// JsonSchemaEntity.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using System; -using Newtonsoft.Json; -using Squidex.Domain.Apps.Core.Schemas; -using Squidex.Domain.Apps.Read.Schemas; -using Squidex.Infrastructure; - -namespace Squidex.Domain.Apps.Read.State.Grains -{ - public sealed class JsonSchemaEntity : - JsonEntity, - ISchemaEntity, - IUpdateableEntityWithAppRef, - IUpdateableEntityWithCreatedBy, - IUpdateableEntityWithLastModifiedBy - { - [JsonProperty] - public string Name { get; set; } - - [JsonProperty] - public Guid AppId { get; set; } - - [JsonProperty] - public RefToken CreatedBy { get; set; } - - [JsonProperty] - public RefToken LastModifiedBy { get; set; } - - [JsonProperty] - public bool IsDeleted { get; set; } - - [JsonProperty] - public string ScriptQuery { get; set; } - - [JsonProperty] - public string ScriptCreate { get; set; } - - [JsonProperty] - public string ScriptUpdate { get; set; } - - [JsonProperty] - public string ScriptDelete { get; set; } - - [JsonProperty] - public string ScriptChange { get; set; } - - [JsonProperty] - public Schema SchemaDef { get; set; } - - [JsonIgnore] - public bool IsPublished - { - get { return SchemaDef.IsPublished; } - } - } -} diff --git a/src/Squidex.Domain.Apps.Write/AppAggregateCommand.cs b/src/Squidex.Domain.Apps.Write/AppAggregateCommand.cs deleted file mode 100644 index cc46b1dbf..000000000 --- a/src/Squidex.Domain.Apps.Write/AppAggregateCommand.cs +++ /dev/null @@ -1,21 +0,0 @@ -// ========================================================================== -// AppAggregateCommand.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using System; -using Squidex.Infrastructure.Commands; - -namespace Squidex.Domain.Apps.Write -{ - public class AppAggregateCommand : AppCommand, IAggregateCommand - { - Guid IAggregateCommand.AggregateId - { - get { return AppId.Id; } - } - } -} diff --git a/src/Squidex.Domain.Apps.Write/AppCommand.cs b/src/Squidex.Domain.Apps.Write/AppCommand.cs deleted file mode 100644 index a948421a5..000000000 --- a/src/Squidex.Domain.Apps.Write/AppCommand.cs +++ /dev/null @@ -1,18 +0,0 @@ -// ========================================================================== -// AppCommand.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using System; -using Squidex.Infrastructure; - -namespace Squidex.Domain.Apps.Write -{ - public abstract class AppCommand : SquidexCommand - { - public NamedId AppId { get; set; } - } -} diff --git a/src/Squidex.Domain.Apps.Write/Apps/AppCommandMiddleware.cs b/src/Squidex.Domain.Apps.Write/Apps/AppCommandMiddleware.cs deleted file mode 100644 index 7c3978cc7..000000000 --- a/src/Squidex.Domain.Apps.Write/Apps/AppCommandMiddleware.cs +++ /dev/null @@ -1,174 +0,0 @@ -// ========================================================================== -// AppCommandMiddleware.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using System; -using System.Threading.Tasks; -using Squidex.Domain.Apps.Read; -using Squidex.Domain.Apps.Read.Apps.Services; -using Squidex.Domain.Apps.Write.Apps.Commands; -using Squidex.Domain.Apps.Write.Apps.Guards; -using Squidex.Infrastructure; -using Squidex.Infrastructure.Commands; -using Squidex.Infrastructure.Dispatching; -using Squidex.Shared.Users; - -namespace Squidex.Domain.Apps.Write.Apps -{ - public class AppCommandMiddleware : ICommandMiddleware - { - private readonly IAggregateHandler handler; - private readonly IAppProvider appProvider; - private readonly IAppPlansProvider appPlansProvider; - private readonly IAppPlanBillingManager appPlansBillingManager; - private readonly IUserResolver userResolver; - - public AppCommandMiddleware( - IAggregateHandler handler, - IAppProvider appProvider, - IAppPlansProvider appPlansProvider, - IAppPlanBillingManager appPlansBillingManager, - IUserResolver userResolver) - { - Guard.NotNull(handler, nameof(handler)); - Guard.NotNull(appProvider, nameof(appProvider)); - Guard.NotNull(userResolver, nameof(userResolver)); - Guard.NotNull(appPlansProvider, nameof(appPlansProvider)); - Guard.NotNull(appPlansBillingManager, nameof(appPlansBillingManager)); - - this.handler = handler; - this.userResolver = userResolver; - this.appProvider = appProvider; - this.appPlansProvider = appPlansProvider; - this.appPlansBillingManager = appPlansBillingManager; - } - - protected async Task On(CreateApp command, CommandContext context) - { - await handler.CreateAsync(context, async a => - { - await GuardApp.CanCreate(command, appProvider); - - a.Create(command); - - context.Complete(EntityCreatedResult.Create(a.Id, a.Version)); - }); - } - - protected async Task On(AssignContributor command, CommandContext context) - { - await handler.UpdateAsync(context, async a => - { - await GuardAppContributors.CanAssign(a.Contributors, command, userResolver, appPlansProvider.GetPlan(a.Plan?.PlanId)); - - a.AssignContributor(command); - }); - } - - protected Task On(RemoveContributor command, CommandContext context) - { - return handler.UpdateAsync(context, a => - { - GuardAppContributors.CanRemove(a.Contributors, command); - - a.RemoveContributor(command); - }); - } - - 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 => - { - GuardAppClients.CanUpdate(a.Clients, command); - - a.UpdateClient(command); - }); - } - - protected Task On(RevokeClient command, CommandContext context) - { - return handler.UpdateAsync(context, a => - { - GuardAppClients.CanRevoke(a.Clients, command); - - a.RevokeClient(command); - }); - } - - protected Task On(AddLanguage command, CommandContext context) - { - return handler.UpdateAsync(context, a => - { - GuardAppLanguages.CanAdd(a.LanguagesConfig, command); - - a.AddLanguage(command); - }); - } - - protected Task On(RemoveLanguage command, CommandContext context) - { - return handler.UpdateAsync(context, a => - { - GuardAppLanguages.CanRemove(a.LanguagesConfig, command); - - a.RemoveLanguage(command); - }); - } - - protected Task On(UpdateLanguage command, CommandContext context) - { - return handler.UpdateAsync(context, a => - { - GuardAppLanguages.CanUpdate(a.LanguagesConfig, command); - - a.UpdateLanguage(command); - }); - } - - protected Task On(ChangePlan command, CommandContext context) - { - return handler.UpdateAsync(context, async a => - { - GuardApp.CanChangePlan(command, a.Plan, appPlansProvider); - - if (command.FromCallback) - { - a.ChangePlan(command); - } - else - { - var result = await appPlansBillingManager.ChangePlanAsync(command.Actor.Identifier, a.Id, a.Name, command.PlanId); - - if (result is PlanChangedResult) - { - a.ChangePlan(command); - } - - context.Complete(result); - } - }); - } - - public async Task HandleAsync(CommandContext context, Func next) - { - if (!await this.DispatchActionAsync(context.Command, context)) - { - await next(); - } - } - } -} diff --git a/src/Squidex.Domain.Apps.Write/Apps/AppDomainObject.cs b/src/Squidex.Domain.Apps.Write/Apps/AppDomainObject.cs deleted file mode 100644 index 6c2a7b7bb..000000000 --- a/src/Squidex.Domain.Apps.Write/Apps/AppDomainObject.cs +++ /dev/null @@ -1,260 +0,0 @@ -// ========================================================================== -// AppDomainObject.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using System; -using Squidex.Domain.Apps.Core.Apps; -using Squidex.Domain.Apps.Events; -using Squidex.Domain.Apps.Events.Apps; -using Squidex.Domain.Apps.Events.Apps.Utils; -using Squidex.Domain.Apps.Write.Apps.Commands; -using Squidex.Infrastructure; -using Squidex.Infrastructure.Commands; -using Squidex.Infrastructure.Dispatching; -using Squidex.Infrastructure.EventSourcing; -using Squidex.Infrastructure.Reflection; - -namespace Squidex.Domain.Apps.Write.Apps -{ - public class AppDomainObject : DomainObjectBase - { - private AppContributors contributors = AppContributors.Empty; - private AppClients clients = AppClients.Empty; - private LanguagesConfig languagesConfig = LanguagesConfig.English; - private AppPlan plan; - private string name; - - public string Name - { - get { return name; } - } - - public AppPlan Plan - { - get { return plan; } - } - - public AppClients Clients - { - get { return clients; } - } - - public AppContributors Contributors - { - get { return contributors; } - } - - public LanguagesConfig LanguagesConfig - { - get { return languagesConfig; } - } - - public AppDomainObject(Guid id, int version) - : base(id, version) - { - } - - protected void On(AppCreated @event) - { - name = @event.Name; - } - - protected void On(AppContributorAssigned @event) - { - contributors = contributors.Apply(@event); - } - - protected void On(AppContributorRemoved @event) - { - contributors = contributors.Apply(@event); - } - - protected void On(AppClientAttached @event) - { - clients = clients.Apply(@event); - } - - protected void On(AppClientUpdated @event) - { - clients = clients.Apply(@event); - } - - protected void On(AppClientRenamed @event) - { - clients = clients.Apply(@event); - } - - protected void On(AppClientRevoked @event) - { - clients = clients.Apply(@event); - } - - protected void On(AppLanguageAdded @event) - { - languagesConfig = languagesConfig.Apply(@event); - } - - protected void On(AppLanguageRemoved @event) - { - languagesConfig = languagesConfig.Apply(@event); - } - - protected void On(AppLanguageUpdated @event) - { - languagesConfig = languagesConfig.Apply(@event); - } - - protected void On(AppPlanChanged @event) - { - plan = string.IsNullOrWhiteSpace(@event.PlanId) ? null : new AppPlan(@event.Actor, @event.PlanId); - } - - protected override void DispatchEvent(Envelope @event) - { - this.DispatchAction(@event.Payload); - } - - public AppDomainObject Create(CreateApp command) - { - ThrowIfCreated(); - - var appId = new NamedId(command.AppId, command.Name); - - RaiseEvent(SimpleMapper.Map(command, new AppCreated { AppId = appId })); - - RaiseEvent(SimpleMapper.Map(command, CreateInitialOwner(appId, command))); - RaiseEvent(SimpleMapper.Map(command, CreateInitialLanguage(appId))); - - return this; - } - - public AppDomainObject UpdateClient(UpdateClient command) - { - ThrowIfNotCreated(); - - if (!string.IsNullOrWhiteSpace(command.Name)) - { - RaiseEvent(SimpleMapper.Map(command, new AppClientRenamed())); - } - - if (command.Permission.HasValue) - { - RaiseEvent(SimpleMapper.Map(command, new AppClientUpdated { Permission = command.Permission.Value })); - } - - return this; - } - - public AppDomainObject AssignContributor(AssignContributor command) - { - ThrowIfNotCreated(); - - RaiseEvent(SimpleMapper.Map(command, new AppContributorAssigned())); - - return this; - } - - public AppDomainObject RemoveContributor(RemoveContributor command) - { - ThrowIfNotCreated(); - - RaiseEvent(SimpleMapper.Map(command, new AppContributorRemoved())); - - return this; - } - - public AppDomainObject AttachClient(AttachClient command) - { - ThrowIfNotCreated(); - - RaiseEvent(SimpleMapper.Map(command, new AppClientAttached())); - - return this; - } - - public AppDomainObject RevokeClient(RevokeClient command) - { - ThrowIfNotCreated(); - - RaiseEvent(SimpleMapper.Map(command, new AppClientRevoked())); - - return this; - } - - public AppDomainObject AddLanguage(AddLanguage command) - { - ThrowIfNotCreated(); - - RaiseEvent(SimpleMapper.Map(command, new AppLanguageAdded())); - - return this; - } - - public AppDomainObject RemoveLanguage(RemoveLanguage command) - { - ThrowIfNotCreated(); - - RaiseEvent(SimpleMapper.Map(command, new AppLanguageRemoved())); - - return this; - } - - public AppDomainObject UpdateLanguage(UpdateLanguage command) - { - ThrowIfNotCreated(); - - RaiseEvent(SimpleMapper.Map(command, new AppLanguageUpdated())); - - return this; - } - - public AppDomainObject ChangePlan(ChangePlan command) - { - ThrowIfNotCreated(); - - RaiseEvent(SimpleMapper.Map(command, new AppPlanChanged())); - - return this; - } - - private void RaiseEvent(AppEvent @event) - { - if (@event.AppId == null) - { - @event.AppId = new NamedId(Id, name); - } - - RaiseEvent(Envelope.Create(@event)); - } - - private static AppLanguageAdded CreateInitialLanguage(NamedId id) - { - return new AppLanguageAdded { AppId = id, Language = Language.EN }; - } - - private static AppContributorAssigned CreateInitialOwner(NamedId id, SquidexCommand command) - { - return new AppContributorAssigned { AppId = id, ContributorId = command.Actor.Identifier, Permission = AppContributorPermission.Owner }; - } - - private void ThrowIfNotCreated() - { - if (string.IsNullOrWhiteSpace(name)) - { - throw new DomainException("App has not been created."); - } - } - - private void ThrowIfCreated() - { - if (!string.IsNullOrWhiteSpace(name)) - { - throw new DomainException("App has already been created."); - } - } - } -} diff --git a/src/Squidex.Domain.Apps.Write/Apps/Commands/AddLanguage.cs b/src/Squidex.Domain.Apps.Write/Apps/Commands/AddLanguage.cs deleted file mode 100644 index 0d6f3396e..000000000 --- a/src/Squidex.Domain.Apps.Write/Apps/Commands/AddLanguage.cs +++ /dev/null @@ -1,17 +0,0 @@ -// ========================================================================== -// AddLanguage.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using Squidex.Infrastructure; - -namespace Squidex.Domain.Apps.Write.Apps.Commands -{ - public sealed class AddLanguage : AppAggregateCommand - { - public Language Language { get; set; } - } -} diff --git a/src/Squidex.Domain.Apps.Write/Apps/Commands/AssignContributor.cs b/src/Squidex.Domain.Apps.Write/Apps/Commands/AssignContributor.cs deleted file mode 100644 index 361ee348f..000000000 --- a/src/Squidex.Domain.Apps.Write/Apps/Commands/AssignContributor.cs +++ /dev/null @@ -1,19 +0,0 @@ -// ========================================================================== -// AssignContributor.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using Squidex.Domain.Apps.Core.Apps; - -namespace Squidex.Domain.Apps.Write.Apps.Commands -{ - public sealed class AssignContributor : AppAggregateCommand - { - public string ContributorId { get; set; } - - public AppContributorPermission Permission { get; set; } - } -} \ No newline at end of file diff --git a/src/Squidex.Domain.Apps.Write/Apps/Commands/AttachClient.cs b/src/Squidex.Domain.Apps.Write/Apps/Commands/AttachClient.cs deleted file mode 100644 index f69cfb384..000000000 --- a/src/Squidex.Domain.Apps.Write/Apps/Commands/AttachClient.cs +++ /dev/null @@ -1,19 +0,0 @@ -// ========================================================================== -// AttachClient.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using Squidex.Infrastructure; - -namespace Squidex.Domain.Apps.Write.Apps.Commands -{ - public sealed class AttachClient : AppAggregateCommand - { - public string Id { get; set; } - - public string Secret { get; } = RandomHash.New(); - } -} diff --git a/src/Squidex.Domain.Apps.Write/Apps/Commands/ChangePlan.cs b/src/Squidex.Domain.Apps.Write/Apps/Commands/ChangePlan.cs deleted file mode 100644 index 4d84ee36c..000000000 --- a/src/Squidex.Domain.Apps.Write/Apps/Commands/ChangePlan.cs +++ /dev/null @@ -1,17 +0,0 @@ -// ========================================================================== -// ChangePlan.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -namespace Squidex.Domain.Apps.Write.Apps.Commands -{ - public sealed class ChangePlan : AppAggregateCommand - { - public bool FromCallback { get; set; } - - public string PlanId { get; set; } - } -} diff --git a/src/Squidex.Domain.Apps.Write/Apps/Commands/CreateApp.cs b/src/Squidex.Domain.Apps.Write/Apps/Commands/CreateApp.cs deleted file mode 100644 index 9ef163160..000000000 --- a/src/Squidex.Domain.Apps.Write/Apps/Commands/CreateApp.cs +++ /dev/null @@ -1,30 +0,0 @@ -// ========================================================================== -// CreateApp.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using System; -using Squidex.Infrastructure.Commands; - -namespace Squidex.Domain.Apps.Write.Apps.Commands -{ - public sealed class CreateApp : SquidexCommand, IAggregateCommand - { - public string Name { get; set; } - - public Guid AppId { get; set; } - - Guid IAggregateCommand.AggregateId - { - get { return AppId; } - } - - public CreateApp() - { - AppId = Guid.NewGuid(); - } - } -} \ No newline at end of file diff --git a/src/Squidex.Domain.Apps.Write/Apps/Commands/RemoveContributor.cs b/src/Squidex.Domain.Apps.Write/Apps/Commands/RemoveContributor.cs deleted file mode 100644 index c579247a3..000000000 --- a/src/Squidex.Domain.Apps.Write/Apps/Commands/RemoveContributor.cs +++ /dev/null @@ -1,15 +0,0 @@ -// ========================================================================== -// RemoveContributor.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -namespace Squidex.Domain.Apps.Write.Apps.Commands -{ - public sealed class RemoveContributor : AppAggregateCommand - { - public string ContributorId { get; set; } - } -} \ No newline at end of file diff --git a/src/Squidex.Domain.Apps.Write/Apps/Commands/RemoveLanguage.cs b/src/Squidex.Domain.Apps.Write/Apps/Commands/RemoveLanguage.cs deleted file mode 100644 index 8a08d3c93..000000000 --- a/src/Squidex.Domain.Apps.Write/Apps/Commands/RemoveLanguage.cs +++ /dev/null @@ -1,17 +0,0 @@ -// ========================================================================== -// RemoveLanguage.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using Squidex.Infrastructure; - -namespace Squidex.Domain.Apps.Write.Apps.Commands -{ - public sealed class RemoveLanguage : AppAggregateCommand - { - public Language Language { get; set; } - } -} diff --git a/src/Squidex.Domain.Apps.Write/Apps/Commands/RevokeClient.cs b/src/Squidex.Domain.Apps.Write/Apps/Commands/RevokeClient.cs deleted file mode 100644 index 68abb555e..000000000 --- a/src/Squidex.Domain.Apps.Write/Apps/Commands/RevokeClient.cs +++ /dev/null @@ -1,15 +0,0 @@ -// ========================================================================== -// RevokeClient.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -namespace Squidex.Domain.Apps.Write.Apps.Commands -{ - public sealed class RevokeClient : AppAggregateCommand - { - public string Id { get; set; } - } -} diff --git a/src/Squidex.Domain.Apps.Write/Apps/Commands/UpdateClient.cs b/src/Squidex.Domain.Apps.Write/Apps/Commands/UpdateClient.cs deleted file mode 100644 index 5cbe2496e..000000000 --- a/src/Squidex.Domain.Apps.Write/Apps/Commands/UpdateClient.cs +++ /dev/null @@ -1,21 +0,0 @@ -// ========================================================================== -// RenameClient.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using Squidex.Domain.Apps.Core.Apps; - -namespace Squidex.Domain.Apps.Write.Apps.Commands -{ - public sealed class UpdateClient : AppAggregateCommand - { - public string Id { get; set; } - - public string Name { get; set; } - - public AppClientPermission? Permission { get; set; } - } -} diff --git a/src/Squidex.Domain.Apps.Write/Apps/Commands/UpdateLanguage.cs b/src/Squidex.Domain.Apps.Write/Apps/Commands/UpdateLanguage.cs deleted file mode 100644 index 22092874f..000000000 --- a/src/Squidex.Domain.Apps.Write/Apps/Commands/UpdateLanguage.cs +++ /dev/null @@ -1,24 +0,0 @@ -// ========================================================================== -// UpdateLanguage.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using System.Collections.Generic; -using Squidex.Infrastructure; - -namespace Squidex.Domain.Apps.Write.Apps.Commands -{ - public sealed class UpdateLanguage : AppAggregateCommand - { - public Language Language { get; set; } - - public bool IsOptional { get; set; } - - public bool IsMaster { get; set; } - - public List Fallback { get; set; } - } -} diff --git a/src/Squidex.Domain.Apps.Write/Apps/Guards/GuardApp.cs b/src/Squidex.Domain.Apps.Write/Apps/Guards/GuardApp.cs deleted file mode 100644 index 89540ff13..000000000 --- a/src/Squidex.Domain.Apps.Write/Apps/Guards/GuardApp.cs +++ /dev/null @@ -1,66 +0,0 @@ -// ========================================================================== -// GuardApp.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using System; -using System.Threading.Tasks; -using Squidex.Domain.Apps.Core.Apps; -using Squidex.Domain.Apps.Read; -using Squidex.Domain.Apps.Read.Apps.Services; -using Squidex.Domain.Apps.Write.Apps.Commands; -using Squidex.Infrastructure; - -namespace Squidex.Domain.Apps.Write.Apps.Guards -{ - public static class GuardApp - { - public static Task CanCreate(CreateApp command, IAppProvider appProvider) - { - Guard.NotNull(command, nameof(command)); - - return Validate.It(() => "Cannot create app.", async error => - { - if (await appProvider.GetAppAsync(command.Name) != null) - { - error(new ValidationError($"An app with name '{command.Name}' already exists", nameof(command.Name))); - } - - if (!command.Name.IsSlug()) - { - error(new ValidationError("Name must be a valid slug.", nameof(command.Name))); - } - }); - } - - public static void CanChangePlan(ChangePlan command, AppPlan plan, IAppPlansProvider appPlans) - { - Guard.NotNull(command, nameof(command)); - - Validate.It(() => "Cannot change plan.", error => - { - if (string.IsNullOrWhiteSpace(command.PlanId)) - { - error(new ValidationError("PlanId is not defined.", nameof(command.PlanId))); - } - else if (appPlans.GetPlan(command.PlanId) == null) - { - error(new ValidationError("Plan id not available.", nameof(command.PlanId))); - } - - if (!string.IsNullOrWhiteSpace(command.PlanId) && plan != null && !plan.Owner.Equals(command.Actor)) - { - error(new ValidationError("Plan can only be changed from current user.")); - } - - if (string.Equals(command.PlanId, plan?.PlanId, StringComparison.OrdinalIgnoreCase)) - { - error(new ValidationError("App has already this plan.")); - } - }); - } - } -} diff --git a/src/Squidex.Domain.Apps.Write/Apps/Guards/GuardAppClients.cs b/src/Squidex.Domain.Apps.Write/Apps/Guards/GuardAppClients.cs deleted file mode 100644 index 3a19fe5ea..000000000 --- a/src/Squidex.Domain.Apps.Write/Apps/Guards/GuardAppClients.cs +++ /dev/null @@ -1,102 +0,0 @@ -// ========================================================================== -// 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 deleted file mode 100644 index 64ecb94f1..000000000 --- a/src/Squidex.Domain.Apps.Write/Apps/Guards/GuardAppContributors.cs +++ /dev/null @@ -1,82 +0,0 @@ -// ========================================================================== -// GuardApp.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using System.Linq; -using System.Threading.Tasks; -using Squidex.Domain.Apps.Core.Apps; -using Squidex.Domain.Apps.Read.Apps.Services; -using Squidex.Domain.Apps.Write.Apps.Commands; -using Squidex.Infrastructure; -using Squidex.Shared.Users; - -namespace Squidex.Domain.Apps.Write.Apps.Guards -{ - public static class GuardAppContributors - { - public static Task CanAssign(AppContributors contributors, AssignContributor command, IUserResolver users, IAppLimitsPlan plan) - { - Guard.NotNull(command, nameof(command)); - - return Validate.It(() => "Cannot assign contributor.", async error => - { - if (!command.Permission.IsEnumValue()) - { - error(new ValidationError("Permission is not valid.", nameof(command.Permission))); - } - - if (string.IsNullOrWhiteSpace(command.ContributorId)) - { - error(new ValidationError("Contributor id not assigned.", nameof(command.ContributorId))); - } - else - { - if (await users.FindByIdAsync(command.ContributorId) == null) - { - error(new ValidationError("Cannot find contributor id.", nameof(command.ContributorId))); - } - 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.Count) - { - error(new ValidationError("You have reached the maximum number of contributors for your plan.")); - } - } - }); - } - - public static void CanRemove(AppContributors contributors, RemoveContributor command) - { - Guard.NotNull(command, nameof(command)); - - Validate.It(() => "Cannot remove contributor.", error => - { - if (string.IsNullOrWhiteSpace(command.ContributorId)) - { - error(new ValidationError("Contributor id not assigned.", nameof(command.ContributorId))); - } - - var ownerIds = contributors.Where(x => x.Value == AppContributorPermission.Owner).Select(x => x.Key).ToList(); - - if (ownerIds.Count == 1 && ownerIds.Contains(command.ContributorId)) - { - error(new ValidationError("Cannot remove the only owner.", nameof(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 deleted file mode 100644 index 1ac39c4b2..000000000 --- a/src/Squidex.Domain.Apps.Write/Apps/Guards/GuardAppLanguages.cs +++ /dev/null @@ -1,100 +0,0 @@ -// ========================================================================== -// GuardApp.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 GuardAppLanguages - { - public static void CanAdd(LanguagesConfig languages, AddLanguage command) - { - Guard.NotNull(command, nameof(command)); - - Validate.It(() => "Cannot add language.", error => - { - if (command.Language == null) - { - error(new ValidationError("Language cannot be null.", nameof(command.Language))); - } - else if (languages.Contains(command.Language)) - { - error(new ValidationError("Language already added.", nameof(command.Language))); - } - }); - } - - public static void CanRemove(LanguagesConfig languages, RemoveLanguage command) - { - Guard.NotNull(command, nameof(command)); - - var languageConfig = GetLanguageConfigOrThrow(languages, command.Language); - - 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))); - } - }); - } - - public static void CanUpdate(LanguagesConfig languages, UpdateLanguage command) - { - Guard.NotNull(command, nameof(command)); - - var languageConfig = GetLanguageConfigOrThrow(languages, command.Language); - - 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))); - } - - if (command.Fallback != null) - { - foreach (var fallback in command.Fallback) - { - if (!languages.Contains(fallback)) - { - error(new ValidationError($"Config does not contain fallback language {fallback}.", nameof(command.Fallback))); - } - } - } - }); - } - - private static LanguageConfig GetLanguageConfigOrThrow(LanguagesConfig languages, Language language) - { - if (language == null) - { - return null; - } - - if (!languages.TryGetConfig(language, out var languageConfig)) - { - throw new DomainObjectNotFoundException(language, "Languages", typeof(AppDomainObject)); - } - - return languageConfig; - } - } -} diff --git a/src/Squidex.Domain.Apps.Write/Assets/AssetCommandMiddleware.cs b/src/Squidex.Domain.Apps.Write/Assets/AssetCommandMiddleware.cs deleted file mode 100644 index de46cceda..000000000 --- a/src/Squidex.Domain.Apps.Write/Assets/AssetCommandMiddleware.cs +++ /dev/null @@ -1,117 +0,0 @@ -// ========================================================================== -// AssetCommandMiddleware.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using System; -using System.Threading.Tasks; -using Squidex.Domain.Apps.Write.Assets.Commands; -using Squidex.Domain.Apps.Write.Assets.Guards; -using Squidex.Infrastructure; -using Squidex.Infrastructure.Assets; -using Squidex.Infrastructure.Commands; -using Squidex.Infrastructure.Dispatching; - -namespace Squidex.Domain.Apps.Write.Assets -{ - public class AssetCommandMiddleware : ICommandMiddleware - { - private readonly IAggregateHandler handler; - private readonly IAssetStore assetStore; - private readonly IAssetThumbnailGenerator assetThumbnailGenerator; - - public AssetCommandMiddleware( - IAggregateHandler handler, - IAssetStore assetStore, - IAssetThumbnailGenerator assetThumbnailGenerator) - { - Guard.NotNull(handler, nameof(handler)); - Guard.NotNull(assetStore, nameof(assetStore)); - Guard.NotNull(assetThumbnailGenerator, nameof(assetThumbnailGenerator)); - - this.handler = handler; - this.assetStore = assetStore; - this.assetThumbnailGenerator = assetThumbnailGenerator; - } - - protected async Task On(CreateAsset command, CommandContext context) - { - command.ImageInfo = await assetThumbnailGenerator.GetImageInfoAsync(command.File.OpenRead()); - try - { - var asset = await handler.CreateAsync(context, async a => - { - GuardAsset.CanCreate(command); - - a.Create(command); - - await assetStore.UploadTemporaryAsync(context.ContextId.ToString(), command.File.OpenRead()); - - context.Complete(EntityCreatedResult.Create(a.Id, a.Version)); - }); - - await assetStore.CopyTemporaryAsync(context.ContextId.ToString(), asset.Id.ToString(), asset.FileVersion, null); - } - finally - { - await assetStore.DeleteTemporaryAsync(context.ContextId.ToString()); - } - } - - protected async Task On(UpdateAsset command, CommandContext context) - { - command.ImageInfo = await assetThumbnailGenerator.GetImageInfoAsync(command.File.OpenRead()); - - try - { - var asset = await handler.UpdateAsync(context, async a => - { - GuardAsset.CanUpdate(command); - - a.Update(command); - - await assetStore.UploadTemporaryAsync(context.ContextId.ToString(), command.File.OpenRead()); - - context.Complete(new AssetSavedResult(a.Version, a.FileVersion)); - }); - - await assetStore.CopyTemporaryAsync(context.ContextId.ToString(), asset.Id.ToString(), asset.FileVersion, null); - } - finally - { - await assetStore.DeleteTemporaryAsync(context.ContextId.ToString()); - } - } - - protected Task On(RenameAsset command, CommandContext context) - { - return handler.UpdateAsync(context, a => - { - GuardAsset.CanRename(command, a.FileName); - - a.Rename(command); - }); - } - - protected Task On(DeleteAsset command, CommandContext context) - { - return handler.UpdateAsync(context, a => - { - GuardAsset.CanDelete(command); - - a.Delete(command); - }); - } - - public async Task HandleAsync(CommandContext context, Func next) - { - if (!await this.DispatchActionAsync(context.Command, context)) - { - await next(); - } - } - } -} diff --git a/src/Squidex.Domain.Apps.Write/Assets/AssetDomainObject.cs b/src/Squidex.Domain.Apps.Write/Assets/AssetDomainObject.cs deleted file mode 100644 index 6fa06c5a7..000000000 --- a/src/Squidex.Domain.Apps.Write/Assets/AssetDomainObject.cs +++ /dev/null @@ -1,150 +0,0 @@ -// ========================================================================== -// AssetDomainObject.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using System; -using Squidex.Domain.Apps.Events.Assets; -using Squidex.Domain.Apps.Write.Assets.Commands; -using Squidex.Infrastructure; -using Squidex.Infrastructure.Commands; -using Squidex.Infrastructure.Dispatching; -using Squidex.Infrastructure.EventSourcing; -using Squidex.Infrastructure.Reflection; - -namespace Squidex.Domain.Apps.Write.Assets -{ - public class AssetDomainObject : DomainObjectBase - { - private bool isDeleted; - private long fileVersion = -1; - private long totalSize; - private string fileName; - - public bool IsDeleted - { - get { return isDeleted; } - } - - public long FileVersion - { - get { return fileVersion; } - } - - public string FileName - { - get { return fileName; } - } - - public AssetDomainObject(Guid id, int version) - : base(id, version) - { - } - - protected void On(AssetCreated @event) - { - fileVersion = @event.FileVersion; - fileName = @event.FileName; - - totalSize += @event.FileSize; - } - - protected void On(AssetUpdated @event) - { - fileVersion = @event.FileVersion; - - totalSize += @event.FileSize; - } - - protected void On(AssetRenamed @event) - { - fileName = @event.FileName; - } - - protected void On(AssetDeleted @event) - { - isDeleted = true; - } - - public AssetDomainObject Create(CreateAsset command) - { - VerifyNotCreated(); - - var @event = SimpleMapper.Map(command, new AssetCreated - { - FileName = command.File.FileName, - FileSize = command.File.FileSize, - FileVersion = fileVersion + 1, - MimeType = command.File.MimeType, - PixelWidth = command.ImageInfo?.PixelWidth, - PixelHeight = command.ImageInfo?.PixelHeight, - IsImage = command.ImageInfo != null - }); - - RaiseEvent(@event); - - return this; - } - - public AssetDomainObject Update(UpdateAsset command) - { - VerifyCreatedAndNotDeleted(); - - var @event = SimpleMapper.Map(command, new AssetUpdated - { - FileVersion = fileVersion + 1, - FileSize = command.File.FileSize, - MimeType = command.File.MimeType, - PixelWidth = command.ImageInfo?.PixelWidth, - PixelHeight = command.ImageInfo?.PixelHeight, - IsImage = command.ImageInfo != null - }); - - RaiseEvent(@event); - - return this; - } - - public AssetDomainObject Delete(DeleteAsset command) - { - VerifyCreatedAndNotDeleted(); - - RaiseEvent(SimpleMapper.Map(command, new AssetDeleted { DeletedSize = totalSize })); - - return this; - } - - public AssetDomainObject Rename(RenameAsset command) - { - VerifyCreatedAndNotDeleted(); - - RaiseEvent(SimpleMapper.Map(command, new AssetRenamed())); - - return this; - } - - private void VerifyNotCreated() - { - if (!string.IsNullOrWhiteSpace(fileName)) - { - throw new DomainException("Asset has already been created."); - } - } - - private void VerifyCreatedAndNotDeleted() - { - if (isDeleted || string.IsNullOrWhiteSpace(fileName)) - { - throw new DomainException("Asset has already been deleted or not created yet."); - } - } - - protected override void DispatchEvent(Envelope @event) - { - this.DispatchAction(@event.Payload); - } - } -} diff --git a/src/Squidex.Domain.Apps.Write/Assets/AssetSavedResult.cs b/src/Squidex.Domain.Apps.Write/Assets/AssetSavedResult.cs deleted file mode 100644 index 5d38142c6..000000000 --- a/src/Squidex.Domain.Apps.Write/Assets/AssetSavedResult.cs +++ /dev/null @@ -1,23 +0,0 @@ -// ========================================================================== -// AssetSavedResult.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using Squidex.Infrastructure.Commands; - -namespace Squidex.Domain.Apps.Write.Assets -{ - public class AssetSavedResult : EntitySavedResult - { - public long FileVersion { get; } - - public AssetSavedResult(long version, long fileVersion) - : base(version) - { - FileVersion = fileVersion; - } - } -} diff --git a/src/Squidex.Domain.Apps.Write/Assets/Commands/AssetAggregateCommand.cs b/src/Squidex.Domain.Apps.Write/Assets/Commands/AssetAggregateCommand.cs deleted file mode 100644 index b62d9dee9..000000000 --- a/src/Squidex.Domain.Apps.Write/Assets/Commands/AssetAggregateCommand.cs +++ /dev/null @@ -1,23 +0,0 @@ -// ========================================================================== -// AssetAggregateCommand.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using System; -using Squidex.Infrastructure.Commands; - -namespace Squidex.Domain.Apps.Write.Assets.Commands -{ - public abstract class AssetAggregateCommand : AppCommand, IAggregateCommand - { - public Guid AssetId { get; set; } - - Guid IAggregateCommand.AggregateId - { - get { return AssetId; } - } - } -} diff --git a/src/Squidex.Domain.Apps.Write/Assets/Commands/CreateAsset.cs b/src/Squidex.Domain.Apps.Write/Assets/Commands/CreateAsset.cs deleted file mode 100644 index 7e11b36e6..000000000 --- a/src/Squidex.Domain.Apps.Write/Assets/Commands/CreateAsset.cs +++ /dev/null @@ -1,25 +0,0 @@ -// ========================================================================== -// CreateAsset.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using System; -using Squidex.Infrastructure.Assets; - -namespace Squidex.Domain.Apps.Write.Assets.Commands -{ - public sealed class CreateAsset : AssetAggregateCommand - { - public AssetFile File { get; set; } - - public ImageInfo ImageInfo { get; set; } - - public CreateAsset() - { - AssetId = Guid.NewGuid(); - } - } -} diff --git a/src/Squidex.Domain.Apps.Write/Assets/Commands/DeleteAsset.cs b/src/Squidex.Domain.Apps.Write/Assets/Commands/DeleteAsset.cs deleted file mode 100644 index a9cfd5cfe..000000000 --- a/src/Squidex.Domain.Apps.Write/Assets/Commands/DeleteAsset.cs +++ /dev/null @@ -1,14 +0,0 @@ -// ========================================================================== -// DeleteAsset.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -namespace Squidex.Domain.Apps.Write.Assets.Commands -{ - public sealed class DeleteAsset : AssetAggregateCommand - { - } -} diff --git a/src/Squidex.Domain.Apps.Write/Assets/Commands/RenameAsset.cs b/src/Squidex.Domain.Apps.Write/Assets/Commands/RenameAsset.cs deleted file mode 100644 index 493acc979..000000000 --- a/src/Squidex.Domain.Apps.Write/Assets/Commands/RenameAsset.cs +++ /dev/null @@ -1,15 +0,0 @@ -// ========================================================================== -// RenameAsset.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -namespace Squidex.Domain.Apps.Write.Assets.Commands -{ - public sealed class RenameAsset : AssetAggregateCommand - { - public string FileName { get; set; } - } -} diff --git a/src/Squidex.Domain.Apps.Write/Assets/Commands/UpdateAsset.cs b/src/Squidex.Domain.Apps.Write/Assets/Commands/UpdateAsset.cs deleted file mode 100644 index 32b8b3935..000000000 --- a/src/Squidex.Domain.Apps.Write/Assets/Commands/UpdateAsset.cs +++ /dev/null @@ -1,19 +0,0 @@ -// ========================================================================== -// UpdateAsset.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using Squidex.Infrastructure.Assets; - -namespace Squidex.Domain.Apps.Write.Assets.Commands -{ - public sealed class UpdateAsset : AssetAggregateCommand - { - public AssetFile File { get; set; } - - public ImageInfo ImageInfo { get; set; } - } -} diff --git a/src/Squidex.Domain.Apps.Write/Assets/Guards/GuardAsset.cs b/src/Squidex.Domain.Apps.Write/Assets/Guards/GuardAsset.cs deleted file mode 100644 index 1e3a7a57d..000000000 --- a/src/Squidex.Domain.Apps.Write/Assets/Guards/GuardAsset.cs +++ /dev/null @@ -1,49 +0,0 @@ -// ========================================================================== -// GuardAsset.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using Squidex.Domain.Apps.Write.Assets.Commands; -using Squidex.Infrastructure; - -namespace Squidex.Domain.Apps.Write.Assets.Guards -{ - public static class GuardAsset - { - public static void CanRename(RenameAsset command, string oldName) - { - Guard.NotNull(command, nameof(command)); - - Validate.It(() => "Cannot rename asset.", error => - { - if (string.IsNullOrWhiteSpace(command.FileName)) - { - error(new ValidationError("Name must be defined.", nameof(command.FileName))); - } - - if (string.Equals(command.FileName, oldName)) - { - error(new ValidationError("Name is equal to old name.", nameof(command.FileName))); - } - }); - } - - public static void CanCreate(CreateAsset command) - { - Guard.NotNull(command, nameof(command)); - } - - public static void CanUpdate(UpdateAsset command) - { - Guard.NotNull(command, nameof(command)); - } - - public static void CanDelete(DeleteAsset command) - { - Guard.NotNull(command, nameof(command)); - } - } -} diff --git a/src/Squidex.Domain.Apps.Write/Contents/Commands/ChangeContentStatus.cs b/src/Squidex.Domain.Apps.Write/Contents/Commands/ChangeContentStatus.cs deleted file mode 100644 index 292f257ee..000000000 --- a/src/Squidex.Domain.Apps.Write/Contents/Commands/ChangeContentStatus.cs +++ /dev/null @@ -1,17 +0,0 @@ -// ========================================================================== -// ChangeContentStatus.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================= - -using Squidex.Domain.Apps.Core.Contents; - -namespace Squidex.Domain.Apps.Write.Contents.Commands -{ - public sealed class ChangeContentStatus : ContentCommand - { - public Status Status { get; set; } - } -} diff --git a/src/Squidex.Domain.Apps.Write/Contents/Commands/ContentCommand.cs b/src/Squidex.Domain.Apps.Write/Contents/Commands/ContentCommand.cs deleted file mode 100644 index edf62f437..000000000 --- a/src/Squidex.Domain.Apps.Write/Contents/Commands/ContentCommand.cs +++ /dev/null @@ -1,26 +0,0 @@ -// ========================================================================== -// ContentCommand.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using System; -using System.Security.Claims; -using Squidex.Infrastructure.Commands; - -namespace Squidex.Domain.Apps.Write.Contents.Commands -{ - public abstract class ContentCommand : SchemaCommand, IAggregateCommand - { - public ClaimsPrincipal User { get; set; } - - public Guid ContentId { get; set; } - - Guid IAggregateCommand.AggregateId - { - get { return ContentId; } - } - } -} diff --git a/src/Squidex.Domain.Apps.Write/Contents/Commands/ContentDataCommand.cs b/src/Squidex.Domain.Apps.Write/Contents/Commands/ContentDataCommand.cs deleted file mode 100644 index 02c147574..000000000 --- a/src/Squidex.Domain.Apps.Write/Contents/Commands/ContentDataCommand.cs +++ /dev/null @@ -1,17 +0,0 @@ -// ========================================================================== -// ContentDataCommand.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using Squidex.Domain.Apps.Core.Contents; - -namespace Squidex.Domain.Apps.Write.Contents.Commands -{ - public abstract class ContentDataCommand : ContentCommand - { - public NamedContentData Data { get; set; } - } -} diff --git a/src/Squidex.Domain.Apps.Write/Contents/Commands/CreateContent.cs b/src/Squidex.Domain.Apps.Write/Contents/Commands/CreateContent.cs deleted file mode 100644 index 3065c0202..000000000 --- a/src/Squidex.Domain.Apps.Write/Contents/Commands/CreateContent.cs +++ /dev/null @@ -1,15 +0,0 @@ -// ========================================================================== -// CreateContent.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -namespace Squidex.Domain.Apps.Write.Contents.Commands -{ - public sealed class CreateContent : ContentDataCommand - { - public bool Publish { get; set; } - } -} diff --git a/src/Squidex.Domain.Apps.Write/Contents/Commands/DeleteContent.cs b/src/Squidex.Domain.Apps.Write/Contents/Commands/DeleteContent.cs deleted file mode 100644 index 23638c95b..000000000 --- a/src/Squidex.Domain.Apps.Write/Contents/Commands/DeleteContent.cs +++ /dev/null @@ -1,14 +0,0 @@ -// ========================================================================== -// DeleteContent.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -namespace Squidex.Domain.Apps.Write.Contents.Commands -{ - public sealed class DeleteContent : ContentCommand - { - } -} diff --git a/src/Squidex.Domain.Apps.Write/Contents/Commands/PatchContent.cs b/src/Squidex.Domain.Apps.Write/Contents/Commands/PatchContent.cs deleted file mode 100644 index ff38a5638..000000000 --- a/src/Squidex.Domain.Apps.Write/Contents/Commands/PatchContent.cs +++ /dev/null @@ -1,14 +0,0 @@ -// ========================================================================== -// PatchContent.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -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 deleted file mode 100644 index be9546173..000000000 --- a/src/Squidex.Domain.Apps.Write/Contents/Commands/UpdateContent.cs +++ /dev/null @@ -1,14 +0,0 @@ -// ========================================================================== -// UpdateContent.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -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 deleted file mode 100644 index 5c111c5bd..000000000 --- a/src/Squidex.Domain.Apps.Write/Contents/ContentCommandMiddleware.cs +++ /dev/null @@ -1,159 +0,0 @@ -// ========================================================================== -// ContentCommandMiddleware.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using System; -using System.Threading.Tasks; -using Squidex.Domain.Apps.Core.Scripting; -using Squidex.Domain.Apps.Read; -using Squidex.Domain.Apps.Read.Assets.Repositories; -using Squidex.Domain.Apps.Read.Contents.Repositories; -using Squidex.Domain.Apps.Write.Contents.Commands; -using Squidex.Domain.Apps.Write.Contents.Guards; -using Squidex.Infrastructure; -using Squidex.Infrastructure.Commands; -using Squidex.Infrastructure.Dispatching; - -namespace Squidex.Domain.Apps.Write.Contents -{ - public class ContentCommandMiddleware : ICommandMiddleware - { - private readonly IAggregateHandler handler; - private readonly IAppProvider appProvider; - private readonly IAssetRepository assetRepository; - private readonly IContentRepository contentRepository; - private readonly IScriptEngine scriptEngine; - - public ContentCommandMiddleware( - IAggregateHandler handler, - IAppProvider appProvider, - IAssetRepository assetRepository, - IScriptEngine scriptEngine, - IContentRepository contentRepository) - { - Guard.NotNull(handler, nameof(handler)); - Guard.NotNull(appProvider, nameof(appProvider)); - Guard.NotNull(scriptEngine, nameof(scriptEngine)); - Guard.NotNull(assetRepository, nameof(assetRepository)); - Guard.NotNull(contentRepository, nameof(contentRepository)); - - this.handler = handler; - this.appProvider = appProvider; - this.scriptEngine = scriptEngine; - this.assetRepository = assetRepository; - this.contentRepository = contentRepository; - } - - protected async Task On(CreateContent command, CommandContext context) - { - await handler.CreateAsync(context, async content => - { - GuardContent.CanCreate(command); - - var operationContext = await CreateContext(command, content, () => "Failed to create content."); - - if (command.Publish) - { - await operationContext.ExecuteScriptAsync(x => x.ScriptChange, "Published"); - } - - await operationContext.ExecuteScriptAndTransformAsync(x => x.ScriptCreate, "Create"); - await operationContext.EnrichAsync(); - await operationContext.ValidateAsync(false); - - content.Create(command); - - context.Complete(EntityCreatedResult.Create(command.Data, content.Version)); - }); - } - - protected async Task On(UpdateContent command, CommandContext context) - { - await handler.UpdateAsync(context, async content => - { - GuardContent.CanUpdate(command); - - var operationContext = await CreateContext(command, content, () => "Failed to update content."); - - await operationContext.ValidateAsync(true); - await operationContext.ExecuteScriptAndTransformAsync(x => x.ScriptUpdate, "Update"); - - content.Update(command); - - context.Complete(new ContentDataChangedResult(content.Data, content.Version)); - }); - } - - protected async Task On(PatchContent command, CommandContext context) - { - await handler.UpdateAsync(context, async content => - { - GuardContent.CanPatch(command); - - var operationContext = await CreateContext(command, content, () => "Failed to patch content."); - - await operationContext.ValidateAsync(true); - await operationContext.ExecuteScriptAndTransformAsync(x => x.ScriptUpdate, "Patch"); - - content.Patch(command); - - context.Complete(new ContentDataChangedResult(content.Data, content.Version)); - }); - } - - protected Task On(ChangeContentStatus command, CommandContext context) - { - return handler.UpdateAsync(context, async content => - { - GuardContent.CanChangeContentStatus(content.Status, command); - - var operationContext = await CreateContext(command, content, () => "Failed to patch content."); - - await operationContext.ExecuteScriptAsync(x => x.ScriptChange, command.Status); - - content.ChangeStatus(command); - }); - } - - protected Task On(DeleteContent command, CommandContext context) - { - return handler.UpdateAsync(context, async content => - { - GuardContent.CanDelete(command); - - var operationContext = await CreateContext(command, content, () => "Failed to delete content."); - - await operationContext.ExecuteScriptAsync(x => x.ScriptDelete, "Delete"); - - content.Delete(command); - }); - } - - public async Task HandleAsync(CommandContext context, Func next) - { - if (!await this.DispatchActionAsync(context.Command, context)) - { - await next(); - } - } - - private async Task CreateContext(ContentCommand command, ContentDomainObject content, Func message) - { - var operationContext = - await ContentOperationContext.CreateAsync( - contentRepository, - content, - command, - appProvider, - assetRepository, - scriptEngine, - message); - - return operationContext; - } - } -} diff --git a/src/Squidex.Domain.Apps.Write/Contents/ContentDataChangedResult.cs b/src/Squidex.Domain.Apps.Write/Contents/ContentDataChangedResult.cs deleted file mode 100644 index 9eb6b0432..000000000 --- a/src/Squidex.Domain.Apps.Write/Contents/ContentDataChangedResult.cs +++ /dev/null @@ -1,24 +0,0 @@ -// ========================================================================== -// ContentChangedResult.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using Squidex.Domain.Apps.Core.Contents; -using Squidex.Infrastructure.Commands; - -namespace Squidex.Domain.Apps.Write.Contents -{ - public sealed class ContentDataChangedResult : EntitySavedResult - { - public NamedContentData Data { get; } - - public ContentDataChangedResult(NamedContentData data, long version) - : base(version) - { - Data = data; - } - } -} diff --git a/src/Squidex.Domain.Apps.Write/Contents/ContentDomainObject.cs b/src/Squidex.Domain.Apps.Write/Contents/ContentDomainObject.cs deleted file mode 100644 index d4c66bec2..000000000 --- a/src/Squidex.Domain.Apps.Write/Contents/ContentDomainObject.cs +++ /dev/null @@ -1,149 +0,0 @@ -// ========================================================================== -// ContentDomainObject.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using System; -using Squidex.Domain.Apps.Core.Contents; -using Squidex.Domain.Apps.Events.Contents; -using Squidex.Domain.Apps.Write.Contents.Commands; -using Squidex.Infrastructure; -using Squidex.Infrastructure.Commands; -using Squidex.Infrastructure.Dispatching; -using Squidex.Infrastructure.EventSourcing; -using Squidex.Infrastructure.Reflection; - -namespace Squidex.Domain.Apps.Write.Contents -{ - public class ContentDomainObject : DomainObjectBase - { - private bool isDeleted; - private bool isCreated; - private Status status; - private NamedContentData data; - - public bool IsDeleted - { - get { return isDeleted; } - } - - public Status Status - { - get { return status; } - } - - public NamedContentData Data - { - get { return data; } - } - - public ContentDomainObject(Guid id, int version) - : base(id, version) - { - } - - protected void On(ContentCreated @event) - { - isCreated = true; - - data = @event.Data; - } - - protected void On(ContentUpdated @event) - { - data = @event.Data; - } - - protected void On(ContentStatusChanged @event) - { - status = @event.Status; - } - - protected void On(ContentDeleted @event) - { - isDeleted = true; - } - - public ContentDomainObject Create(CreateContent command) - { - VerifyNotCreated(); - - RaiseEvent(SimpleMapper.Map(command, new ContentCreated())); - - if (command.Publish) - { - RaiseEvent(SimpleMapper.Map(command, new ContentStatusChanged { Status = Status.Published })); - } - - return this; - } - - public ContentDomainObject Delete(DeleteContent command) - { - VerifyCreatedAndNotDeleted(); - - RaiseEvent(SimpleMapper.Map(command, new ContentDeleted())); - - return this; - } - - public ContentDomainObject ChangeStatus(ChangeContentStatus command) - { - VerifyCreatedAndNotDeleted(); - - RaiseEvent(SimpleMapper.Map(command, new ContentStatusChanged())); - - return this; - } - - public ContentDomainObject Update(UpdateContent command) - { - VerifyCreatedAndNotDeleted(); - - if (!command.Data.Equals(Data)) - { - RaiseEvent(SimpleMapper.Map(command, new ContentUpdated())); - } - - return this; - } - - public ContentDomainObject Patch(PatchContent command) - { - VerifyCreatedAndNotDeleted(); - - var newData = Data.MergeInto(command.Data); - - if (!newData.Equals(Data)) - { - RaiseEvent(SimpleMapper.Map(command, new ContentUpdated { Data = newData })); - } - - return this; - } - - private void VerifyNotCreated() - { - if (isCreated) - { - throw new DomainException("Content has already been created."); - } - } - - private void VerifyCreatedAndNotDeleted() - { - if (isDeleted || !isCreated) - { - throw new DomainException("Content has already been deleted or not created yet."); - } - } - - protected override void DispatchEvent(Envelope @event) - { - this.DispatchAction(@event.Payload); - } - } -} diff --git a/src/Squidex.Domain.Apps.Write/Contents/ContentOperationContext.cs b/src/Squidex.Domain.Apps.Write/Contents/ContentOperationContext.cs deleted file mode 100644 index 530c7505e..000000000 --- a/src/Squidex.Domain.Apps.Write/Contents/ContentOperationContext.cs +++ /dev/null @@ -1,141 +0,0 @@ -// ========================================================================== -// 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; -using Squidex.Domain.Apps.Read.Apps; -using Squidex.Domain.Apps.Read.Assets.Repositories; -using Squidex.Domain.Apps.Read.Contents.Repositories; -using Squidex.Domain.Apps.Read.Schemas; -using Squidex.Domain.Apps.Write.Contents.Commands; -using Squidex.Infrastructure; -using Squidex.Infrastructure.Tasks; - -#pragma warning disable IDE0017 // Simplify object initialization - -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, - IAssetRepository assetRepository, - IScriptEngine scriptEngine, - Func message) - { - var (appEntity, schemaEntity) = await appProvider.GetAppWithSchemaAsync(command.AppId.Name, command.SchemaId.Id); - - var context = new ContentOperationContext(); - - context.appEntity = appEntity; - context.assetRepository = assetRepository; - context.contentRepository = contentRepository; - context.content = content; - context.command = command; - context.message = message; - context.schemaEntity = schemaEntity; - 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 QueryContentsAsync(appId, schemaId, contentIds); - }, - assetIds => - { - return QueryAssetsAsync(appId, assetIds); - }); - - 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()); - } - } - } - - private async Task> QueryAssetsAsync(Guid appId, IEnumerable assetIds) - { - return await assetRepository.QueryAsync(appId, null, new HashSet(assetIds), null, int.MaxValue, 0); - } - - private async Task> QueryContentsAsync(Guid appId, Guid schemaId, IEnumerable contentIds) - { - return await contentRepository.QueryNotFoundAsync(appId, schemaId, contentIds.ToList()); - } - - 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/ContentVersionLoader.cs b/src/Squidex.Domain.Apps.Write/Contents/ContentVersionLoader.cs deleted file mode 100644 index 7e6203d5d..000000000 --- a/src/Squidex.Domain.Apps.Write/Contents/ContentVersionLoader.cs +++ /dev/null @@ -1,87 +0,0 @@ -// ========================================================================== -// ContentVersionLoader.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using System; -using System.Linq; -using System.Threading.Tasks; -using Squidex.Domain.Apps.Core.Contents; -using Squidex.Domain.Apps.Events.Contents; -using Squidex.Infrastructure; -using Squidex.Infrastructure.EventSourcing; -using Squidex.Infrastructure.States; - -namespace Squidex.Domain.Apps.Write.Contents -{ - public sealed class ContentVersionLoader : IContentVersionLoader - { - private readonly IStreamNameResolver nameResolver; - private readonly IEventStore eventStore; - private readonly IEventDataFormatter formatter; - - public ContentVersionLoader(IEventStore eventStore, IStreamNameResolver nameResolver, IEventDataFormatter formatter) - { - Guard.NotNull(formatter, nameof(formatter)); - Guard.NotNull(eventStore, nameof(eventStore)); - Guard.NotNull(nameResolver, nameof(nameResolver)); - - this.formatter = formatter; - this.eventStore = eventStore; - this.nameResolver = nameResolver; - } - - public async Task LoadAsync(Guid appId, Guid id, long version) - { - var streamName = nameResolver.GetStreamName(typeof(ContentDomainObject), id.ToString()); - - var events = await eventStore.GetEventsAsync(streamName); - - if (events.Count == 0 || events.Count < version - 1) - { - throw new DomainObjectNotFoundException(id.ToString(), typeof(ContentDomainObject)); - } - - NamedContentData contentData = null; - - foreach (var storedEvent in events.Where(x => x.EventStreamNumber <= version)) - { - var envelope = ParseKnownEvent(storedEvent); - - if (envelope != null) - { - if (envelope.Payload is ContentCreated contentCreated) - { - if (contentCreated.AppId.Id != appId) - { - throw new DomainObjectNotFoundException(id.ToString(), typeof(ContentDomainObject)); - } - - contentData = contentCreated.Data; - } - else if (envelope.Payload is ContentUpdated contentUpdated) - { - contentData = contentUpdated.Data; - } - } - } - - return contentData; - } - - private Envelope ParseKnownEvent(StoredEvent storedEvent) - { - try - { - return formatter.Parse(storedEvent.Data); - } - catch (TypeNameNotFoundException) - { - return null; - } - } - } -} diff --git a/src/Squidex.Domain.Apps.Write/Contents/Guards/GuardContent.cs b/src/Squidex.Domain.Apps.Write/Contents/Guards/GuardContent.cs deleted file mode 100644 index 06178cdb1..000000000 --- a/src/Squidex.Domain.Apps.Write/Contents/Guards/GuardContent.cs +++ /dev/null @@ -1,74 +0,0 @@ -// ========================================================================== -// GuardContent.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.Infrastructure; - -namespace Squidex.Domain.Apps.Write.Contents.Guards -{ - public static class GuardContent - { - public static void CanCreate(CreateContent command) - { - Guard.NotNull(command, nameof(command)); - - Validate.It(() => "Cannot created content.", error => - { - if (command.Data == null) - { - error(new ValidationError("Data cannot be null.", nameof(command.Data))); - } - }); - } - - public static void CanUpdate(UpdateContent command) - { - Guard.NotNull(command, nameof(command)); - - Validate.It(() => "Cannot update content.", error => - { - if (command.Data == null) - { - error(new ValidationError("Data cannot be null.", nameof(command.Data))); - } - }); - } - - public static void CanPatch(PatchContent command) - { - Guard.NotNull(command, nameof(command)); - - Validate.It(() => "Cannot patch content.", error => - { - if (command.Data == null) - { - error(new ValidationError("Data cannot be null.", nameof(command.Data))); - } - }); - } - - public static void CanChangeContentStatus(Status status, ChangeContentStatus command) - { - Guard.NotNull(command, nameof(command)); - - Validate.It(() => "Cannot change status.", error => - { - if (!StatusFlow.Exists(command.Status) || !StatusFlow.CanChange(status, command.Status)) - { - error(new ValidationError($"Content cannot be changed from status {status} to {command.Status}.", nameof(command.Status))); - } - }); - } - - public static void CanDelete(DeleteContent command) - { - Guard.NotNull(command, nameof(command)); - } - } -} diff --git a/src/Squidex.Domain.Apps.Write/Contents/IContentVersionLoader.cs b/src/Squidex.Domain.Apps.Write/Contents/IContentVersionLoader.cs deleted file mode 100644 index e3968fbfc..000000000 --- a/src/Squidex.Domain.Apps.Write/Contents/IContentVersionLoader.cs +++ /dev/null @@ -1,19 +0,0 @@ -// ========================================================================== -// IContentVersionLoader.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using System; -using System.Threading.Tasks; -using Squidex.Domain.Apps.Core.Contents; - -namespace Squidex.Domain.Apps.Write.Contents -{ - public interface IContentVersionLoader - { - Task LoadAsync(Guid appId, Guid id, long version); - } -} diff --git a/src/Squidex.Domain.Apps.Write/Rules/Commands/CreateRule.cs b/src/Squidex.Domain.Apps.Write/Rules/Commands/CreateRule.cs deleted file mode 100644 index 1c6bafd7e..000000000 --- a/src/Squidex.Domain.Apps.Write/Rules/Commands/CreateRule.cs +++ /dev/null @@ -1,20 +0,0 @@ -// ========================================================================== -// CreateRule.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using System; - -namespace Squidex.Domain.Apps.Write.Rules.Commands -{ - public sealed class CreateRule : RuleEditCommand - { - public CreateRule() - { - RuleId = Guid.NewGuid(); - } - } -} diff --git a/src/Squidex.Domain.Apps.Write/Rules/Commands/DeleteRule.cs b/src/Squidex.Domain.Apps.Write/Rules/Commands/DeleteRule.cs deleted file mode 100644 index c97f2c6b1..000000000 --- a/src/Squidex.Domain.Apps.Write/Rules/Commands/DeleteRule.cs +++ /dev/null @@ -1,14 +0,0 @@ -// ========================================================================== -// DeleteRule.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -namespace Squidex.Domain.Apps.Write.Rules.Commands -{ - public sealed class DeleteRule : RuleAggregateCommand - { - } -} diff --git a/src/Squidex.Domain.Apps.Write/Rules/Commands/DisableRule.cs b/src/Squidex.Domain.Apps.Write/Rules/Commands/DisableRule.cs deleted file mode 100644 index ccfa2a9be..000000000 --- a/src/Squidex.Domain.Apps.Write/Rules/Commands/DisableRule.cs +++ /dev/null @@ -1,14 +0,0 @@ -// ========================================================================== -// DisableRule.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -namespace Squidex.Domain.Apps.Write.Rules.Commands -{ - public sealed class DisableRule : RuleAggregateCommand - { - } -} diff --git a/src/Squidex.Domain.Apps.Write/Rules/Commands/EnableRule.cs b/src/Squidex.Domain.Apps.Write/Rules/Commands/EnableRule.cs deleted file mode 100644 index ac3bf7f4c..000000000 --- a/src/Squidex.Domain.Apps.Write/Rules/Commands/EnableRule.cs +++ /dev/null @@ -1,14 +0,0 @@ -// ========================================================================== -// EnableRule.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -namespace Squidex.Domain.Apps.Write.Rules.Commands -{ - public sealed class EnableRule : RuleAggregateCommand - { - } -} diff --git a/src/Squidex.Domain.Apps.Write/Rules/Commands/RuleAggregateCommand.cs b/src/Squidex.Domain.Apps.Write/Rules/Commands/RuleAggregateCommand.cs deleted file mode 100644 index d240c8957..000000000 --- a/src/Squidex.Domain.Apps.Write/Rules/Commands/RuleAggregateCommand.cs +++ /dev/null @@ -1,23 +0,0 @@ -// ========================================================================== -// RuleAggregateCommand.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using System; -using Squidex.Infrastructure.Commands; - -namespace Squidex.Domain.Apps.Write.Rules.Commands -{ - public abstract class RuleAggregateCommand : AppCommand, IAggregateCommand - { - public Guid RuleId { get; set; } - - Guid IAggregateCommand.AggregateId - { - get { return RuleId; } - } - } -} diff --git a/src/Squidex.Domain.Apps.Write/Rules/Commands/RuleEditCommand.cs b/src/Squidex.Domain.Apps.Write/Rules/Commands/RuleEditCommand.cs deleted file mode 100644 index b63be728a..000000000 --- a/src/Squidex.Domain.Apps.Write/Rules/Commands/RuleEditCommand.cs +++ /dev/null @@ -1,19 +0,0 @@ -// ========================================================================== -// RuleEditCommand.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using Squidex.Domain.Apps.Core.Rules; - -namespace Squidex.Domain.Apps.Write.Rules.Commands -{ - public abstract class RuleEditCommand : RuleAggregateCommand - { - public RuleTrigger Trigger { get; set; } - - public RuleAction Action { get; set; } - } -} diff --git a/src/Squidex.Domain.Apps.Write/Rules/Commands/UpdateRule.cs b/src/Squidex.Domain.Apps.Write/Rules/Commands/UpdateRule.cs deleted file mode 100644 index 6fe43df4d..000000000 --- a/src/Squidex.Domain.Apps.Write/Rules/Commands/UpdateRule.cs +++ /dev/null @@ -1,14 +0,0 @@ -// ========================================================================== -// UpdateRule.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -namespace Squidex.Domain.Apps.Write.Rules.Commands -{ - public sealed class UpdateRule : RuleEditCommand - { - } -} diff --git a/src/Squidex.Domain.Apps.Write/Rules/Guards/GuardRule.cs b/src/Squidex.Domain.Apps.Write/Rules/Guards/GuardRule.cs deleted file mode 100644 index 5848f9f1e..000000000 --- a/src/Squidex.Domain.Apps.Write/Rules/Guards/GuardRule.cs +++ /dev/null @@ -1,107 +0,0 @@ -// ========================================================================== -// GuardRule.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using System.Threading.Tasks; -using Squidex.Domain.Apps.Core.Rules; -using Squidex.Domain.Apps.Read; -using Squidex.Domain.Apps.Write.Rules.Commands; -using Squidex.Infrastructure; - -namespace Squidex.Domain.Apps.Write.Rules.Guards -{ - public static class GuardRule - { - public static Task CanCreate(CreateRule command, IAppProvider appProvider) - { - Guard.NotNull(command, nameof(command)); - - return Validate.It(() => "Cannot create rule.", async error => - { - if (command.Trigger == null) - { - error(new ValidationError("Trigger must be defined.", nameof(command.Trigger))); - } - else - { - var errors = await RuleTriggerValidator.ValidateAsync(command.AppId.Name, command.Trigger, appProvider); - - errors.Foreach(error); - } - - if (command.Action == null) - { - error(new ValidationError("Trigger must be defined.", nameof(command.Action))); - } - else - { - var errors = await RuleActionValidator.ValidateAsync(command.Action); - - errors.Foreach(error); - } - }); - } - - public static Task CanUpdate(UpdateRule command, IAppProvider appProvider) - { - Guard.NotNull(command, nameof(command)); - - return Validate.It(() => "Cannot update rule.", async error => - { - if (command.Trigger == null && command.Action == null) - { - error(new ValidationError("Either trigger or action must be defined.", nameof(command.Trigger), nameof(command.Action))); - } - - if (command.Trigger != null) - { - var errors = await RuleTriggerValidator.ValidateAsync(command.AppId.Name, command.Trigger, appProvider); - - errors.Foreach(error); - } - - if (command.Action != null) - { - var errors = await RuleActionValidator.ValidateAsync(command.Action); - - errors.Foreach(error); - } - }); - } - - public static void CanEnable(EnableRule command, Rule rule) - { - Guard.NotNull(command, nameof(command)); - - Validate.It(() => "Cannot enable rule.", error => - { - if (rule.IsEnabled) - { - error(new ValidationError("Rule is already enabled.")); - } - }); - } - - public static void CanDisable(DisableRule command, Rule rule) - { - Guard.NotNull(command, nameof(command)); - - Validate.It(() => "Cannot disable rule.", error => - { - if (!rule.IsEnabled) - { - error(new ValidationError("Rule is already disabled.")); - } - }); - } - - public static void CanDelete(DeleteRule command) - { - Guard.NotNull(command, nameof(command)); - } - } -} diff --git a/src/Squidex.Domain.Apps.Write/Rules/Guards/RuleActionValidator.cs b/src/Squidex.Domain.Apps.Write/Rules/Guards/RuleActionValidator.cs deleted file mode 100644 index 4ead12956..000000000 --- a/src/Squidex.Domain.Apps.Write/Rules/Guards/RuleActionValidator.cs +++ /dev/null @@ -1,40 +0,0 @@ -// ========================================================================== -// RuleActionValidator.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using System.Collections.Generic; -using System.Threading.Tasks; -using Squidex.Domain.Apps.Core.Rules; -using Squidex.Domain.Apps.Core.Rules.Actions; -using Squidex.Infrastructure; - -namespace Squidex.Domain.Apps.Write.Rules.Guards -{ - public sealed class RuleActionValidator : IRuleActionVisitor>> - { - public static Task> ValidateAsync(RuleAction action) - { - Guard.NotNull(action, nameof(action)); - - var visitor = new RuleActionValidator(); - - return action.Accept(visitor); - } - - public Task> Visit(WebhookAction action) - { - var errors = new List(); - - if (action.Url == null || !action.Url.IsAbsoluteUri) - { - errors.Add(new ValidationError("Url must be specified and absolute.", nameof(action.Url))); - } - - return Task.FromResult>(errors); - } - } -} diff --git a/src/Squidex.Domain.Apps.Write/Rules/Guards/RuleTriggerValidator.cs b/src/Squidex.Domain.Apps.Write/Rules/Guards/RuleTriggerValidator.cs deleted file mode 100644 index 48dfec259..000000000 --- a/src/Squidex.Domain.Apps.Write/Rules/Guards/RuleTriggerValidator.cs +++ /dev/null @@ -1,56 +0,0 @@ -// ========================================================================== -// RuleTriggerValidator.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.Rules; -using Squidex.Domain.Apps.Core.Rules.Triggers; -using Squidex.Domain.Apps.Read; -using Squidex.Domain.Apps.Read.Schemas; -using Squidex.Infrastructure; - -namespace Squidex.Domain.Apps.Write.Rules.Guards -{ - public sealed class RuleTriggerValidator : IRuleTriggerVisitor>> - { - public Func> SchemaProvider { get; } - - public RuleTriggerValidator(Func> schemaProvider) - { - SchemaProvider = schemaProvider; - } - - public static Task> ValidateAsync(string appName, RuleTrigger action, IAppProvider appProvider) - { - Guard.NotNull(action, nameof(action)); - Guard.NotNull(appProvider, nameof(appProvider)); - - var visitor = new RuleTriggerValidator(x => appProvider.GetSchemaAsync(appName, x)); - - return action.Accept(visitor); - } - - public async Task> Visit(ContentChangedTrigger trigger) - { - if (trigger.Schemas != null) - { - var schemaErrors = await Task.WhenAll( - trigger.Schemas.Select(async s => - await SchemaProvider(s.SchemaId) == null - ? new ValidationError($"Schema {s.SchemaId} does not exist.", nameof(trigger.Schemas)) - : null)); - - return schemaErrors.Where(x => x != null).ToList(); - } - - return new List(); - } - } -} diff --git a/src/Squidex.Domain.Apps.Write/Rules/RuleCommandMiddleware.cs b/src/Squidex.Domain.Apps.Write/Rules/RuleCommandMiddleware.cs deleted file mode 100644 index 302951f90..000000000 --- a/src/Squidex.Domain.Apps.Write/Rules/RuleCommandMiddleware.cs +++ /dev/null @@ -1,93 +0,0 @@ -// ========================================================================== -// RuleCommandMiddleware.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using System; -using System.Threading.Tasks; -using Squidex.Domain.Apps.Read; -using Squidex.Domain.Apps.Write.Rules.Commands; -using Squidex.Domain.Apps.Write.Rules.Guards; -using Squidex.Infrastructure; -using Squidex.Infrastructure.Commands; -using Squidex.Infrastructure.Dispatching; - -namespace Squidex.Domain.Apps.Write.Rules -{ - public class RuleCommandMiddleware : ICommandMiddleware - { - private readonly IAggregateHandler handler; - private readonly IAppProvider appProvider; - - public RuleCommandMiddleware(IAggregateHandler handler, IAppProvider appProvider) - { - Guard.NotNull(handler, nameof(handler)); - Guard.NotNull(appProvider, nameof(appProvider)); - - this.handler = handler; - - this.appProvider = appProvider; - } - - protected Task On(CreateRule command, CommandContext context) - { - return handler.CreateAsync(context, async w => - { - await GuardRule.CanCreate(command, appProvider); - - w.Create(command); - }); - } - - protected Task On(UpdateRule command, CommandContext context) - { - return handler.UpdateAsync(context, async c => - { - await GuardRule.CanUpdate(command, appProvider); - - c.Update(command); - }); - } - - protected Task On(EnableRule command, CommandContext context) - { - return handler.UpdateAsync(context, r => - { - GuardRule.CanEnable(command, r.Rule); - - r.Enable(command); - }); - } - - protected Task On(DisableRule command, CommandContext context) - { - return handler.UpdateAsync(context, r => - { - GuardRule.CanDisable(command, r.Rule); - - r.Disable(command); - }); - } - - protected Task On(DeleteRule command, CommandContext context) - { - return handler.UpdateAsync(context, c => - { - GuardRule.CanDelete(command); - - c.Delete(command); - }); - } - - public async Task HandleAsync(CommandContext context, Func next) - { - if (!await this.DispatchActionAsync(context.Command, context)) - { - await next(); - } - } - } -} diff --git a/src/Squidex.Domain.Apps.Write/Rules/RuleDomainObject.cs b/src/Squidex.Domain.Apps.Write/Rules/RuleDomainObject.cs deleted file mode 100644 index 82a679cc8..000000000 --- a/src/Squidex.Domain.Apps.Write/Rules/RuleDomainObject.cs +++ /dev/null @@ -1,118 +0,0 @@ -// ========================================================================== -// RuleDomainObject.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using System; -using Squidex.Domain.Apps.Core.Rules; -using Squidex.Domain.Apps.Events.Rules; -using Squidex.Domain.Apps.Events.Rules.Utils; -using Squidex.Domain.Apps.Write.Rules.Commands; -using Squidex.Infrastructure; -using Squidex.Infrastructure.Commands; -using Squidex.Infrastructure.Dispatching; -using Squidex.Infrastructure.EventSourcing; -using Squidex.Infrastructure.Reflection; - -namespace Squidex.Domain.Apps.Write.Rules -{ - public class RuleDomainObject : DomainObjectBase - { - private Rule rule; - private bool isDeleted; - - public Rule Rule - { - get { return rule; } - } - - public RuleDomainObject(Guid id, int version) - : base(id, version) - { - } - - protected void On(RuleCreated @event) - { - rule = RuleEventDispatcher.Create(@event); - } - - protected void On(RuleUpdated @event) - { - rule = rule.Apply(@event); - } - - protected void On(RuleEnabled @event) - { - rule = rule.Apply(@event); - } - - protected void On(RuleDisabled @event) - { - rule = rule.Apply(@event); - } - - protected void On(RuleDeleted @event) - { - isDeleted = true; - } - - public void Create(CreateRule command) - { - VerifyNotCreated(); - - RaiseEvent(SimpleMapper.Map(command, new RuleCreated())); - } - - public void Update(UpdateRule command) - { - VerifyCreatedAndNotDeleted(); - - RaiseEvent(SimpleMapper.Map(command, new RuleUpdated())); - } - - public void Enable(EnableRule command) - { - VerifyCreatedAndNotDeleted(); - - RaiseEvent(SimpleMapper.Map(command, new RuleEnabled())); - } - - public void Disable(DisableRule command) - { - VerifyCreatedAndNotDeleted(); - - RaiseEvent(SimpleMapper.Map(command, new RuleDisabled())); - } - - public void Delete(DeleteRule command) - { - VerifyCreatedAndNotDeleted(); - - RaiseEvent(SimpleMapper.Map(command, new RuleDeleted())); - } - - private void VerifyNotCreated() - { - if (rule != null) - { - throw new DomainException("Webhook has already been created."); - } - } - - private void VerifyCreatedAndNotDeleted() - { - if (isDeleted || rule == null) - { - throw new DomainException("Webhook has already been deleted or not created yet."); - } - } - - protected override void DispatchEvent(Envelope @event) - { - this.DispatchAction(@event.Payload); - } - } -} diff --git a/src/Squidex.Domain.Apps.Write/SchemaAggregateCommand.cs b/src/Squidex.Domain.Apps.Write/SchemaAggregateCommand.cs deleted file mode 100644 index fc5e43ae8..000000000 --- a/src/Squidex.Domain.Apps.Write/SchemaAggregateCommand.cs +++ /dev/null @@ -1,21 +0,0 @@ -// ========================================================================== -// SchemaAggregateCommand.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using System; -using Squidex.Infrastructure.Commands; - -namespace Squidex.Domain.Apps.Write -{ - public abstract class SchemaAggregateCommand : SchemaCommand, IAggregateCommand - { - Guid IAggregateCommand.AggregateId - { - get { return SchemaId.Id; } - } - } -} diff --git a/src/Squidex.Domain.Apps.Write/SchemaCommand.cs b/src/Squidex.Domain.Apps.Write/SchemaCommand.cs deleted file mode 100644 index 1d36b3a18..000000000 --- a/src/Squidex.Domain.Apps.Write/SchemaCommand.cs +++ /dev/null @@ -1,18 +0,0 @@ -// ========================================================================== -// SchemaCommand.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using System; -using Squidex.Infrastructure; - -namespace Squidex.Domain.Apps.Write -{ - public abstract class SchemaCommand : AppCommand - { - public NamedId SchemaId { get; set; } - } -} diff --git a/src/Squidex.Domain.Apps.Write/Schemas/Commands/AddField.cs b/src/Squidex.Domain.Apps.Write/Schemas/Commands/AddField.cs deleted file mode 100644 index 8b78836df..000000000 --- a/src/Squidex.Domain.Apps.Write/Schemas/Commands/AddField.cs +++ /dev/null @@ -1,21 +0,0 @@ -// ========================================================================== -// AddField.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using Squidex.Domain.Apps.Core.Schemas; - -namespace Squidex.Domain.Apps.Write.Schemas.Commands -{ - public sealed class AddField : SchemaAggregateCommand - { - public string Name { get; set; } - - public string Partitioning { get; set; } - - public FieldProperties Properties { get; set; } - } -} \ No newline at end of file diff --git a/src/Squidex.Domain.Apps.Write/Schemas/Commands/ConfigureScripts.cs b/src/Squidex.Domain.Apps.Write/Schemas/Commands/ConfigureScripts.cs deleted file mode 100644 index 08453ecb7..000000000 --- a/src/Squidex.Domain.Apps.Write/Schemas/Commands/ConfigureScripts.cs +++ /dev/null @@ -1,23 +0,0 @@ -// ========================================================================== -// ConfigureScripts.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -namespace Squidex.Domain.Apps.Write.Schemas.Commands -{ - public sealed class ConfigureScripts : SchemaAggregateCommand - { - public string ScriptQuery { get; set; } - - public string ScriptCreate { get; set; } - - public string ScriptUpdate { get; set; } - - public string ScriptDelete { get; set; } - - public string ScriptChange { get; set; } - } -} diff --git a/src/Squidex.Domain.Apps.Write/Schemas/Commands/CreateSchema.cs b/src/Squidex.Domain.Apps.Write/Schemas/Commands/CreateSchema.cs deleted file mode 100644 index b8a9bbcd0..000000000 --- a/src/Squidex.Domain.Apps.Write/Schemas/Commands/CreateSchema.cs +++ /dev/null @@ -1,36 +0,0 @@ -// ========================================================================== -// CreateSchema.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using System; -using Squidex.Domain.Apps.Core.Schemas; -using Squidex.Infrastructure.Commands; -using SchemaFields = System.Collections.Generic.List; - -namespace Squidex.Domain.Apps.Write.Schemas.Commands -{ - public sealed class CreateSchema : AppCommand, IAggregateCommand - { - public Guid SchemaId { get; set; } - - public SchemaFields Fields { get; set; } - - public SchemaProperties Properties { get; set; } - - public string Name { get; set; } - - Guid IAggregateCommand.AggregateId - { - get { return SchemaId; } - } - - public CreateSchema() - { - SchemaId = Guid.NewGuid(); - } - } -} \ No newline at end of file diff --git a/src/Squidex.Domain.Apps.Write/Schemas/Commands/CreateSchemaField.cs b/src/Squidex.Domain.Apps.Write/Schemas/Commands/CreateSchemaField.cs deleted file mode 100644 index d532a0a76..000000000 --- a/src/Squidex.Domain.Apps.Write/Schemas/Commands/CreateSchemaField.cs +++ /dev/null @@ -1,27 +0,0 @@ -// ========================================================================== -// CreateSchemaField.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using Squidex.Domain.Apps.Core.Schemas; - -namespace Squidex.Domain.Apps.Write.Schemas.Commands -{ - public sealed class CreateSchemaField - { - public string Partitioning { get; set; } - - public string Name { get; set; } - - public bool IsHidden { get; set; } - - public bool IsLocked { get; set; } - - public bool IsDisabled { get; set; } - - public FieldProperties Properties { get; set; } - } -} diff --git a/src/Squidex.Domain.Apps.Write/Schemas/Commands/DeleteField.cs b/src/Squidex.Domain.Apps.Write/Schemas/Commands/DeleteField.cs deleted file mode 100644 index 36ea19310..000000000 --- a/src/Squidex.Domain.Apps.Write/Schemas/Commands/DeleteField.cs +++ /dev/null @@ -1,14 +0,0 @@ -// ========================================================================== -// DeleteField.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -namespace Squidex.Domain.Apps.Write.Schemas.Commands -{ - public sealed class DeleteField : FieldCommand - { - } -} \ No newline at end of file diff --git a/src/Squidex.Domain.Apps.Write/Schemas/Commands/DeleteSchema.cs b/src/Squidex.Domain.Apps.Write/Schemas/Commands/DeleteSchema.cs deleted file mode 100644 index 1384453b0..000000000 --- a/src/Squidex.Domain.Apps.Write/Schemas/Commands/DeleteSchema.cs +++ /dev/null @@ -1,14 +0,0 @@ -// ========================================================================== -// DeleteSchema.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -namespace Squidex.Domain.Apps.Write.Schemas.Commands -{ - public sealed class DeleteSchema : SchemaAggregateCommand - { - } -} \ No newline at end of file diff --git a/src/Squidex.Domain.Apps.Write/Schemas/Commands/DisableField.cs b/src/Squidex.Domain.Apps.Write/Schemas/Commands/DisableField.cs deleted file mode 100644 index 95dc2d327..000000000 --- a/src/Squidex.Domain.Apps.Write/Schemas/Commands/DisableField.cs +++ /dev/null @@ -1,14 +0,0 @@ -// ========================================================================== -// DisableField.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -namespace Squidex.Domain.Apps.Write.Schemas.Commands -{ - public sealed class DisableField : FieldCommand - { - } -} diff --git a/src/Squidex.Domain.Apps.Write/Schemas/Commands/EnableField.cs b/src/Squidex.Domain.Apps.Write/Schemas/Commands/EnableField.cs deleted file mode 100644 index 1ac8930b6..000000000 --- a/src/Squidex.Domain.Apps.Write/Schemas/Commands/EnableField.cs +++ /dev/null @@ -1,14 +0,0 @@ -// ========================================================================== -// EnableField.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -namespace Squidex.Domain.Apps.Write.Schemas.Commands -{ - public sealed class EnableField : FieldCommand - { - } -} diff --git a/src/Squidex.Domain.Apps.Write/Schemas/Commands/FieldCommand.cs b/src/Squidex.Domain.Apps.Write/Schemas/Commands/FieldCommand.cs deleted file mode 100644 index 4fe5f6b6f..000000000 --- a/src/Squidex.Domain.Apps.Write/Schemas/Commands/FieldCommand.cs +++ /dev/null @@ -1,15 +0,0 @@ -// ========================================================================== -// FieldCommand.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -namespace Squidex.Domain.Apps.Write.Schemas.Commands -{ - public class FieldCommand : SchemaAggregateCommand - { - public long FieldId { get; set; } - } -} diff --git a/src/Squidex.Domain.Apps.Write/Schemas/Commands/HideField.cs b/src/Squidex.Domain.Apps.Write/Schemas/Commands/HideField.cs deleted file mode 100644 index b8fcde46f..000000000 --- a/src/Squidex.Domain.Apps.Write/Schemas/Commands/HideField.cs +++ /dev/null @@ -1,14 +0,0 @@ -// ========================================================================== -// HideField.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -namespace Squidex.Domain.Apps.Write.Schemas.Commands -{ - public sealed class HideField : FieldCommand - { - } -} diff --git a/src/Squidex.Domain.Apps.Write/Schemas/Commands/LockField.cs b/src/Squidex.Domain.Apps.Write/Schemas/Commands/LockField.cs deleted file mode 100644 index 3109fcb6e..000000000 --- a/src/Squidex.Domain.Apps.Write/Schemas/Commands/LockField.cs +++ /dev/null @@ -1,14 +0,0 @@ -// ========================================================================== -// LockField.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -namespace Squidex.Domain.Apps.Write.Schemas.Commands -{ - public sealed class LockField : FieldCommand - { - } -} diff --git a/src/Squidex.Domain.Apps.Write/Schemas/Commands/PublishSchema.cs b/src/Squidex.Domain.Apps.Write/Schemas/Commands/PublishSchema.cs deleted file mode 100644 index a0385926d..000000000 --- a/src/Squidex.Domain.Apps.Write/Schemas/Commands/PublishSchema.cs +++ /dev/null @@ -1,14 +0,0 @@ -// ========================================================================== -// PublishSchema.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -namespace Squidex.Domain.Apps.Write.Schemas.Commands -{ - public sealed class PublishSchema : SchemaAggregateCommand - { - } -} diff --git a/src/Squidex.Domain.Apps.Write/Schemas/Commands/ReorderFields.cs b/src/Squidex.Domain.Apps.Write/Schemas/Commands/ReorderFields.cs deleted file mode 100644 index 2d3805fb1..000000000 --- a/src/Squidex.Domain.Apps.Write/Schemas/Commands/ReorderFields.cs +++ /dev/null @@ -1,17 +0,0 @@ -// ========================================================================== -// ReorderFields.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using System.Collections.Generic; - -namespace Squidex.Domain.Apps.Write.Schemas.Commands -{ - public sealed class ReorderFields : SchemaAggregateCommand - { - public List FieldIds { get; set; } - } -} diff --git a/src/Squidex.Domain.Apps.Write/Schemas/Commands/ShowField.cs b/src/Squidex.Domain.Apps.Write/Schemas/Commands/ShowField.cs deleted file mode 100644 index 024148139..000000000 --- a/src/Squidex.Domain.Apps.Write/Schemas/Commands/ShowField.cs +++ /dev/null @@ -1,14 +0,0 @@ -// ========================================================================== -// ShowField.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -namespace Squidex.Domain.Apps.Write.Schemas.Commands -{ - public sealed class ShowField : FieldCommand - { - } -} diff --git a/src/Squidex.Domain.Apps.Write/Schemas/Commands/UnpublishSchema.cs b/src/Squidex.Domain.Apps.Write/Schemas/Commands/UnpublishSchema.cs deleted file mode 100644 index f8e83ce02..000000000 --- a/src/Squidex.Domain.Apps.Write/Schemas/Commands/UnpublishSchema.cs +++ /dev/null @@ -1,14 +0,0 @@ -// ========================================================================== -// UnpublishSchema.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -namespace Squidex.Domain.Apps.Write.Schemas.Commands -{ - public sealed class UnpublishSchema : SchemaAggregateCommand - { - } -} diff --git a/src/Squidex.Domain.Apps.Write/Schemas/Commands/UpdateField.cs b/src/Squidex.Domain.Apps.Write/Schemas/Commands/UpdateField.cs deleted file mode 100644 index 1f70668cb..000000000 --- a/src/Squidex.Domain.Apps.Write/Schemas/Commands/UpdateField.cs +++ /dev/null @@ -1,17 +0,0 @@ -// ========================================================================== -// UpdateField.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using Squidex.Domain.Apps.Core.Schemas; - -namespace Squidex.Domain.Apps.Write.Schemas.Commands -{ - public sealed class UpdateField : FieldCommand - { - public FieldProperties Properties { get; set; } - } -} \ No newline at end of file diff --git a/src/Squidex.Domain.Apps.Write/Schemas/Commands/UpdateSchema.cs b/src/Squidex.Domain.Apps.Write/Schemas/Commands/UpdateSchema.cs deleted file mode 100644 index ba711a5a0..000000000 --- a/src/Squidex.Domain.Apps.Write/Schemas/Commands/UpdateSchema.cs +++ /dev/null @@ -1,17 +0,0 @@ -// ========================================================================== -// UpdateSchema.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using Squidex.Domain.Apps.Core.Schemas; - -namespace Squidex.Domain.Apps.Write.Schemas.Commands -{ - public sealed class UpdateSchema : SchemaAggregateCommand - { - public SchemaProperties Properties { get; set; } - } -} \ No newline at end of file diff --git a/src/Squidex.Domain.Apps.Write/Schemas/Guards/FieldPropertiesValidator.cs b/src/Squidex.Domain.Apps.Write/Schemas/Guards/FieldPropertiesValidator.cs deleted file mode 100644 index f08405643..000000000 --- a/src/Squidex.Domain.Apps.Write/Schemas/Guards/FieldPropertiesValidator.cs +++ /dev/null @@ -1,232 +0,0 @@ -// ========================================================================== -// FieldPropertiesValidator.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using System.Collections.Generic; -using System.Linq; -using Squidex.Domain.Apps.Core.Schemas; -using Squidex.Infrastructure; - -namespace Squidex.Domain.Apps.Write.Schemas.Guards -{ - public sealed class FieldPropertiesValidator : IFieldPropertiesVisitor> - { - private static readonly FieldPropertiesValidator Instance = new FieldPropertiesValidator(); - - private FieldPropertiesValidator() - { - } - - public static IEnumerable Validate(FieldProperties properties) - { - return properties?.Accept(Instance) ?? Enumerable.Empty(); - } - - public IEnumerable Visit(AssetsFieldProperties properties) - { - if (properties.MaxItems.HasValue && properties.MinItems.HasValue && properties.MinItems.Value >= properties.MaxItems.Value) - { - yield return new ValidationError("Max items must be greater than min items.", - nameof(properties.MinItems), - nameof(properties.MaxItems)); - } - - if (properties.MaxHeight.HasValue && properties.MinHeight.HasValue && properties.MinHeight.Value >= properties.MaxHeight.Value) - { - yield return new ValidationError("Max height must be greater than min height.", - nameof(properties.MaxHeight), - nameof(properties.MinHeight)); - } - - if (properties.MaxWidth.HasValue && properties.MinWidth.HasValue && properties.MinWidth.Value >= properties.MaxWidth.Value) - { - yield return new ValidationError("Max width must be greater than min width.", - nameof(properties.MaxWidth), - nameof(properties.MinWidth)); - } - - if (properties.MaxSize.HasValue && properties.MinSize.HasValue && properties.MinSize.Value >= properties.MaxSize.Value) - { - yield return new ValidationError("Max size must be greater than min size.", - nameof(properties.MaxSize), - nameof(properties.MinSize)); - } - - if (properties.AspectWidth.HasValue != properties.AspectHeight.HasValue) - { - yield return new ValidationError("Aspect width and height must be defined.", - nameof(properties.AspectWidth), - nameof(properties.AspectHeight)); - } - } - - public IEnumerable Visit(BooleanFieldProperties properties) - { - if (!properties.Editor.IsEnumValue()) - { - yield return new ValidationError("Editor is not a valid value.", - nameof(properties.Editor)); - } - } - - public IEnumerable Visit(DateTimeFieldProperties properties) - { - if (!properties.Editor.IsEnumValue()) - { - yield return new ValidationError("Editor is not a valid value.", - nameof(properties.Editor)); - } - - if (properties.DefaultValue.HasValue && properties.MinValue.HasValue && properties.DefaultValue.Value < properties.MinValue.Value) - { - yield return new ValidationError("Default value must be greater than min value.", - nameof(properties.DefaultValue)); - } - - if (properties.DefaultValue.HasValue && properties.MaxValue.HasValue && properties.DefaultValue.Value > properties.MaxValue.Value) - { - yield return new ValidationError("Default value must be less than max value.", - nameof(properties.DefaultValue)); - } - - if (properties.MaxValue.HasValue && properties.MinValue.HasValue && properties.MinValue.Value >= properties.MaxValue.Value) - { - yield return new ValidationError("Max value must be greater than min value.", - nameof(properties.MinValue), - nameof(properties.MaxValue)); - } - - if (properties.CalculatedDefaultValue.HasValue) - { - if (!properties.CalculatedDefaultValue.Value.IsEnumValue()) - { - yield return new ValidationError("Calculated default value is not valid.", - nameof(properties.CalculatedDefaultValue)); - } - - if (properties.DefaultValue.HasValue) - { - yield return new ValidationError("Calculated default value and default value cannot be used together.", - nameof(properties.CalculatedDefaultValue), - nameof(properties.DefaultValue)); - } - } - } - - public IEnumerable Visit(GeolocationFieldProperties properties) - { - if (!properties.Editor.IsEnumValue()) - { - yield return new ValidationError("Editor is not a valid value.", - nameof(properties.Editor)); - } - } - - public IEnumerable Visit(JsonFieldProperties properties) - { - yield break; - } - - public IEnumerable Visit(NumberFieldProperties properties) - { - if (!properties.Editor.IsEnumValue()) - { - yield return new ValidationError("Editor is not a valid value.", - nameof(properties.Editor)); - } - - if ((properties.Editor == NumberFieldEditor.Radio || properties.Editor == NumberFieldEditor.Dropdown) && (properties.AllowedValues == null || properties.AllowedValues.Count == 0)) - { - yield return new ValidationError("Radio buttons or dropdown list need allowed values.", - nameof(properties.AllowedValues)); - } - - if (properties.DefaultValue.HasValue && properties.MinValue.HasValue && properties.DefaultValue.Value < properties.MinValue.Value) - { - yield return new ValidationError("Default value must be greater than min value.", - nameof(properties.DefaultValue)); - } - - if (properties.DefaultValue.HasValue && properties.MaxValue.HasValue && properties.DefaultValue.Value > properties.MaxValue.Value) - { - yield return new ValidationError("Default value must be less than max value.", - nameof(properties.DefaultValue)); - } - - if (properties.MaxValue.HasValue && properties.MinValue.HasValue && properties.MinValue.Value >= properties.MaxValue.Value) - { - yield return new ValidationError("Max value must be greater than min value.", - nameof(properties.MinValue), - nameof(properties.MaxValue)); - } - - if (properties.AllowedValues != null && properties.AllowedValues.Count > 0 && (properties.MinValue.HasValue || properties.MaxValue.HasValue)) - { - yield return new ValidationError("Either allowed values or min and max value can be defined.", - nameof(properties.AllowedValues), - nameof(properties.MinValue), - nameof(properties.MaxValue)); - } - } - - public IEnumerable Visit(ReferencesFieldProperties properties) - { - if (properties.MaxItems.HasValue && properties.MinItems.HasValue && properties.MinItems.Value >= properties.MaxItems.Value) - { - yield return new ValidationError("Max items must be greater than min items.", - nameof(properties.MinItems), - nameof(properties.MaxItems)); - } - } - - public IEnumerable Visit(StringFieldProperties properties) - { - if (!properties.Editor.IsEnumValue()) - { - yield return new ValidationError("Editor is not a valid value.", - nameof(properties.Editor)); - } - - if ((properties.Editor == StringFieldEditor.Radio || properties.Editor == StringFieldEditor.Dropdown) && (properties.AllowedValues == null || properties.AllowedValues.Count == 0)) - { - yield return new ValidationError("Radio buttons or dropdown list need allowed values.", - nameof(properties.AllowedValues)); - } - - if (properties.Pattern != null && !properties.Pattern.IsValidRegex()) - { - yield return new ValidationError("Pattern is not a valid expression.", - nameof(properties.Pattern)); - } - - if (properties.MaxLength.HasValue && properties.MinLength.HasValue && properties.MinLength.Value >= properties.MaxLength.Value) - { - yield return new ValidationError("Max length must be greater than min length.", - nameof(properties.MinLength), - nameof(properties.MaxLength)); - } - - if (properties.AllowedValues != null && properties.AllowedValues.Count > 0 && (properties.MinLength.HasValue || properties.MaxLength.HasValue)) - { - yield return new ValidationError("Either allowed values or min and max length can be defined.", - nameof(properties.AllowedValues), - nameof(properties.MinLength), - nameof(properties.MaxLength)); - } - } - - public IEnumerable Visit(TagsFieldProperties properties) - { - if (properties.MaxItems.HasValue && properties.MinItems.HasValue && properties.MinItems.Value >= properties.MaxItems.Value) - { - yield return new ValidationError("Max items must be greater than min items.", - nameof(properties.MinItems), - nameof(properties.MaxItems)); - } - } - } -} diff --git a/src/Squidex.Domain.Apps.Write/Schemas/Guards/GuardSchema.cs b/src/Squidex.Domain.Apps.Write/Schemas/Guards/GuardSchema.cs deleted file mode 100644 index b9006a315..000000000 --- a/src/Squidex.Domain.Apps.Write/Schemas/Guards/GuardSchema.cs +++ /dev/null @@ -1,129 +0,0 @@ -// ========================================================================== -// GuardSchema.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using System.Linq; -using System.Threading.Tasks; -using Squidex.Domain.Apps.Core; -using Squidex.Domain.Apps.Core.Schemas; -using Squidex.Domain.Apps.Read; -using Squidex.Domain.Apps.Write.Schemas.Commands; -using Squidex.Infrastructure; - -namespace Squidex.Domain.Apps.Write.Schemas.Guards -{ - public static class GuardSchema - { - public static Task CanCreate(CreateSchema command, IAppProvider appProvider) - { - Guard.NotNull(command, nameof(command)); - - return Validate.It(() => "Cannot create schema.", async error => - { - if (!command.Name.IsSlug()) - { - error(new ValidationError("Name must be a valid slug.", nameof(command.Name))); - } - - if (await appProvider.GetSchemaAsync(command.AppId.Name, command.Name) != null) - { - error(new ValidationError($"A schema with name '{command.Name}' already exists", nameof(command.Name))); - } - - if (command.Fields != null && command.Fields.Any()) - { - var index = 0; - - foreach (var field in command.Fields) - { - var prefix = $"Fields.{index}"; - - if (!field.Partitioning.IsValidPartitioning()) - { - error(new ValidationError("Partitioning is not valid.", $"{prefix}.{nameof(field.Partitioning)}")); - } - - if (!field.Name.IsPropertyName()) - { - error(new ValidationError("Name must be a valid property name.", $"{prefix}.{nameof(field.Name)}")); - } - - if (field.Properties == null) - { - error(new ValidationError("Properties must be defined.", $"{prefix}.{nameof(field.Properties)}")); - } - - var propertyErrors = FieldPropertiesValidator.Validate(field.Properties); - - foreach (var propertyError in propertyErrors) - { - error(propertyError); - } - } - - if (command.Fields.Select(x => x.Name).Distinct().Count() != command.Fields.Count) - { - error(new ValidationError("Fields cannot have duplicate names.", nameof(command.Fields))); - } - } - }); - } - - public static void CanReorder(Schema schema, ReorderFields command) - { - Guard.NotNull(command, nameof(command)); - - Validate.It(() => "Cannot reorder schema fields.", error => - { - if (command.FieldIds == null) - { - error(new ValidationError("Field ids must be specified.", nameof(command.FieldIds))); - } - - if (command.FieldIds.Count != schema.Fields.Count || command.FieldIds.Any(x => !schema.FieldsById.ContainsKey(x))) - { - error(new ValidationError("Ids must cover all fields.", nameof(command.FieldIds))); - } - }); - } - - public static void CanPublish(Schema schema, PublishSchema command) - { - Guard.NotNull(command, nameof(command)); - - if (schema.IsPublished) - { - throw new DomainException("Schema is already published."); - } - } - - public static void CanUnpublish(Schema schema, UnpublishSchema command) - { - Guard.NotNull(command, nameof(command)); - - if (!schema.IsPublished) - { - throw new DomainException("Schema is not published."); - } - } - - public static void CanUpdate(Schema schema, UpdateSchema command) - { - Guard.NotNull(command, nameof(command)); - } - - public static void CanConfigureScripts(Schema schema, ConfigureScripts command) - { - Guard.NotNull(command, nameof(command)); - } - - public static void CanDelete(Schema schema, DeleteSchema command) - { - Guard.NotNull(command, nameof(command)); - } - } -} diff --git a/src/Squidex.Domain.Apps.Write/Schemas/Guards/GuardSchemaField.cs b/src/Squidex.Domain.Apps.Write/Schemas/Guards/GuardSchemaField.cs deleted file mode 100644 index 67a9eeb77..000000000 --- a/src/Squidex.Domain.Apps.Write/Schemas/Guards/GuardSchemaField.cs +++ /dev/null @@ -1,160 +0,0 @@ -// ========================================================================== -// SchemaFieldGuard.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using Squidex.Domain.Apps.Core; -using Squidex.Domain.Apps.Core.Schemas; -using Squidex.Domain.Apps.Write.Schemas.Commands; -using Squidex.Infrastructure; - -namespace Squidex.Domain.Apps.Write.Schemas.Guards -{ - public static class GuardSchemaField - { - public static void CanAdd(Schema schema, AddField command) - { - Guard.NotNull(command, nameof(command)); - - Validate.It(() => "Cannot add a new field.", error => - { - if (!command.Partitioning.IsValidPartitioning()) - { - error(new ValidationError("Partitioning is not valid.", nameof(command.Partitioning))); - } - - if (!command.Name.IsPropertyName()) - { - error(new ValidationError("Name must be a valid property name.", nameof(command.Name))); - } - - if (command.Properties == null) - { - error(new ValidationError("Properties must be defined.", nameof(command.Properties))); - } - - var propertyErrors = FieldPropertiesValidator.Validate(command.Properties); - - foreach (var propertyError in propertyErrors) - { - error(propertyError); - } - - if (schema.FieldsByName.ContainsKey(command.Name)) - { - error(new ValidationError($"There is already a field with name '{command.Name}'", nameof(command.Name))); - } - }); - } - - public static void CanUpdate(Schema schema, UpdateField command) - { - Guard.NotNull(command, nameof(command)); - - Validate.It(() => "Cannot update field.", error => - { - if (command.Properties == null) - { - error(new ValidationError("Properties must be defined.", nameof(command.Properties))); - } - - var propertyErrors = FieldPropertiesValidator.Validate(command.Properties); - - foreach (var propertyError in propertyErrors) - { - error(propertyError); - } - }); - - var field = GetFieldOrThrow(schema, command.FieldId); - - if (field.IsLocked) - { - throw new DomainException("Schema field is already locked."); - } - } - - public static void CanDelete(Schema schema, DeleteField command) - { - Guard.NotNull(command, nameof(command)); - - var field = GetFieldOrThrow(schema, command.FieldId); - - if (field.IsLocked) - { - throw new DomainException("Schema field is locked."); - } - } - - public static void CanHide(Schema schema, HideField command) - { - Guard.NotNull(command, nameof(command)); - - var field = GetFieldOrThrow(schema, command.FieldId); - - if (field.IsHidden) - { - throw new DomainException("Schema field is already hidden."); - } - } - - public static void CanShow(Schema schema, ShowField command) - { - Guard.NotNull(command, nameof(command)); - - var field = GetFieldOrThrow(schema, command.FieldId); - - if (!field.IsHidden) - { - throw new DomainException("Schema field is already visible."); - } - } - - public static void CanDisable(Schema schema, DisableField command) - { - Guard.NotNull(command, nameof(command)); - - var field = GetFieldOrThrow(schema, command.FieldId); - - if (field.IsDisabled) - { - throw new DomainException("Schema field is already disabled."); - } - } - - public static void CanEnable(Schema schema, EnableField command) - { - var field = GetFieldOrThrow(schema, command.FieldId); - - if (!field.IsDisabled) - { - throw new DomainException("Schema field is already enabled."); - } - } - - public static void CanLock(Schema schema, LockField command) - { - Guard.NotNull(command, nameof(command)); - - var field = GetFieldOrThrow(schema, command.FieldId); - - if (field.IsLocked) - { - throw new DomainException("Schema field is already locked."); - } - } - - private static Field GetFieldOrThrow(Schema schema, long fieldId) - { - if (!schema.FieldsById.TryGetValue(fieldId, out var field)) - { - throw new DomainObjectNotFoundException(fieldId.ToString(), "Fields", typeof(Schema)); - } - - return field; - } - } -} diff --git a/src/Squidex.Domain.Apps.Write/Schemas/SchemaCommandMiddleware.cs b/src/Squidex.Domain.Apps.Write/Schemas/SchemaCommandMiddleware.cs deleted file mode 100644 index 71837b91a..000000000 --- a/src/Squidex.Domain.Apps.Write/Schemas/SchemaCommandMiddleware.cs +++ /dev/null @@ -1,198 +0,0 @@ -// ========================================================================== -// SchemaCommandMiddleware.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using System; -using System.Linq; -using System.Threading.Tasks; -using Squidex.Domain.Apps.Read; -using Squidex.Domain.Apps.Write.Schemas.Commands; -using Squidex.Domain.Apps.Write.Schemas.Guards; -using Squidex.Infrastructure; -using Squidex.Infrastructure.Commands; -using Squidex.Infrastructure.Dispatching; - -namespace Squidex.Domain.Apps.Write.Schemas -{ - public class SchemaCommandMiddleware : ICommandMiddleware - { - private readonly IAppProvider appProvider; - private readonly IAggregateHandler handler; - - public SchemaCommandMiddleware(IAggregateHandler handler, IAppProvider appProvider) - { - Guard.NotNull(handler, nameof(handler)); - Guard.NotNull(appProvider, nameof(appProvider)); - - this.handler = handler; - - this.appProvider = appProvider; - } - - protected Task On(CreateSchema command, CommandContext context) - { - return handler.CreateAsync(context, async s => - { - await GuardSchema.CanCreate(command, appProvider); - - s.Create(command); - - context.Complete(EntityCreatedResult.Create(s.Id, s.Version)); - }); - } - - protected Task On(AddField command, CommandContext context) - { - return handler.UpdateAsync(context, s => - { - GuardSchemaField.CanAdd(s.Schema, command); - - s.Add(command); - - context.Complete(EntityCreatedResult.Create(s.Schema.FieldsById.Values.First(x => x.Name == command.Name).Id, s.Version)); - }); - } - - protected Task On(DeleteField command, CommandContext context) - { - return handler.UpdateAsync(context, s => - { - GuardSchemaField.CanDelete(s.Schema, command); - - s.DeleteField(command); - }); - } - - protected Task On(LockField command, CommandContext context) - { - return handler.UpdateAsync(context, s => - { - GuardSchemaField.CanLock(s.Schema, command); - - s.LockField(command); - }); - } - - protected Task On(HideField command, CommandContext context) - { - return handler.UpdateAsync(context, s => - { - GuardSchemaField.CanHide(s.Schema, command); - - s.HideField(command); - }); - } - - protected Task On(ShowField command, CommandContext context) - { - return handler.UpdateAsync(context, s => - { - GuardSchemaField.CanShow(s.Schema, command); - - s.ShowField(command); - }); - } - - protected Task On(DisableField command, CommandContext context) - { - return handler.UpdateAsync(context, s => - { - GuardSchemaField.CanDisable(s.Schema, command); - - s.DisableField(command); - }); - } - - protected Task On(EnableField command, CommandContext context) - { - return handler.UpdateAsync(context, s => - { - GuardSchemaField.CanEnable(s.Schema, command); - - s.EnableField(command); - }); - } - - protected Task On(UpdateField command, CommandContext context) - { - return handler.UpdateAsync(context, s => - { - GuardSchemaField.CanUpdate(s.Schema, command); - - s.UpdateField(command); - }); - } - - protected Task On(ReorderFields command, CommandContext context) - { - return handler.UpdateAsync(context, s => - { - GuardSchema.CanReorder(s.Schema, command); - - s.Reorder(command); - }); - } - - protected Task On(UpdateSchema command, CommandContext context) - { - return handler.UpdateAsync(context, s => - { - GuardSchema.CanUpdate(s.Schema, command); - - s.Update(command); - }); - } - - protected Task On(PublishSchema command, CommandContext context) - { - return handler.UpdateAsync(context, s => - { - GuardSchema.CanPublish(s.Schema, command); - - s.Publish(command); - }); - } - - protected Task On(UnpublishSchema command, CommandContext context) - { - return handler.UpdateAsync(context, s => - { - GuardSchema.CanUnpublish(s.Schema, command); - - s.Unpublish(command); - }); - } - - protected Task On(ConfigureScripts command, CommandContext context) - { - return handler.UpdateAsync(context, s => - { - GuardSchema.CanConfigureScripts(s.Schema, command); - - s.ConfigureScripts(command); - }); - } - - protected Task On(DeleteSchema command, CommandContext context) - { - return handler.UpdateAsync(context, s => - { - GuardSchema.CanDelete(s.Schema, command); - - s.Delete(command); - }); - } - - public async Task HandleAsync(CommandContext context, Func next) - { - if (!await this.DispatchActionAsync(context.Command, context)) - { - await next(); - } - } - } -} diff --git a/src/Squidex.Domain.Apps.Write/Schemas/SchemaDomainObject.cs b/src/Squidex.Domain.Apps.Write/Schemas/SchemaDomainObject.cs deleted file mode 100644 index 3c264b974..000000000 --- a/src/Squidex.Domain.Apps.Write/Schemas/SchemaDomainObject.cs +++ /dev/null @@ -1,304 +0,0 @@ -// ========================================================================== -// SchemaDomainObject.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using System; -using System.Collections.Generic; -using Squidex.Domain.Apps.Core.Schemas; -using Squidex.Domain.Apps.Events.Schemas; -using Squidex.Domain.Apps.Events.Schemas.Utils; -using Squidex.Domain.Apps.Write.Schemas.Commands; -using Squidex.Infrastructure; -using Squidex.Infrastructure.Commands; -using Squidex.Infrastructure.Dispatching; -using Squidex.Infrastructure.EventSourcing; -using Squidex.Infrastructure.Reflection; - -namespace Squidex.Domain.Apps.Write.Schemas -{ - public class SchemaDomainObject : DomainObjectBase - { - private readonly FieldRegistry registry; - private bool isDeleted; - private long totalFields; - private Schema schema; - - public Schema Schema - { - get { return schema; } - } - - public bool IsDeleted - { - get { return isDeleted; } - } - - public SchemaDomainObject(Guid id, int version, FieldRegistry registry) - : base(id, version) - { - Guard.NotNull(registry, nameof(registry)); - - this.registry = registry; - } - - protected void On(SchemaCreated @event) - { - totalFields += @event.Fields?.Count ?? 0; - - schema = SchemaEventDispatcher.Create(@event, registry); - } - - public void On(FieldAdded @event) - { - totalFields++; - - schema = schema.Apply(@event, registry); - } - - protected void On(FieldUpdated @event) - { - schema = schema.Apply(@event); - } - - protected void On(FieldLocked @event) - { - schema = schema.Apply(@event); - } - - protected void On(FieldHidden @event) - { - schema = schema.Apply(@event); - } - - protected void On(FieldShown @event) - { - schema = schema.Apply(@event); - } - - protected void On(FieldDisabled @event) - { - schema = schema.Apply(@event); - } - - protected void On(FieldEnabled @event) - { - schema = schema.Apply(@event); - } - - protected void On(SchemaUpdated @event) - { - schema = schema.Apply(@event); - } - - protected void On(FieldDeleted @event) - { - schema = schema.Apply(@event); - } - - protected void On(SchemaFieldsReordered @event) - { - schema = schema.Apply(@event); - } - - protected void On(SchemaPublished @event) - { - schema = schema.Apply(@event); - } - - protected void On(SchemaUnpublished @event) - { - schema = schema.Apply(@event); - } - - protected void On(SchemaDeleted @event) - { - isDeleted = true; - } - - public SchemaDomainObject Create(CreateSchema command) - { - VerifyNotCreated(); - - var @event = SimpleMapper.Map(command, new SchemaCreated { SchemaId = new NamedId(Id, command.Name) }); - - if (command.Fields != null) - { - @event.Fields = new List(); - - foreach (var commandField in command.Fields) - { - var eventField = SimpleMapper.Map(commandField, new SchemaCreatedField()); - - @event.Fields.Add(eventField); - } - } - - RaiseEvent(@event); - - return this; - } - - public SchemaDomainObject Add(AddField command) - { - VerifyCreatedAndNotDeleted(); - - RaiseEvent(SimpleMapper.Map(command, new FieldAdded { FieldId = new NamedId(totalFields + 1, command.Name) })); - - return this; - } - - public SchemaDomainObject UpdateField(UpdateField command) - { - VerifyCreatedAndNotDeleted(); - - RaiseEvent(command, SimpleMapper.Map(command, new FieldUpdated())); - - return this; - } - - public SchemaDomainObject LockField(LockField command) - { - VerifyCreatedAndNotDeleted(); - - RaiseEvent(command, new FieldLocked()); - - return this; - } - - public SchemaDomainObject HideField(HideField command) - { - VerifyCreatedAndNotDeleted(); - - RaiseEvent(command, new FieldHidden()); - - return this; - } - - public SchemaDomainObject ShowField(ShowField command) - { - VerifyCreatedAndNotDeleted(); - - RaiseEvent(command, new FieldShown()); - - return this; - } - - public SchemaDomainObject DisableField(DisableField command) - { - VerifyCreatedAndNotDeleted(); - - RaiseEvent(command, new FieldDisabled()); - - return this; - } - - public SchemaDomainObject EnableField(EnableField command) - { - VerifyCreatedAndNotDeleted(); - - RaiseEvent(command, new FieldEnabled()); - - return this; - } - - public SchemaDomainObject DeleteField(DeleteField command) - { - VerifyCreatedAndNotDeleted(); - - RaiseEvent(command, new FieldDeleted()); - - return this; - } - - public SchemaDomainObject Reorder(ReorderFields command) - { - VerifyCreatedAndNotDeleted(); - - RaiseEvent(SimpleMapper.Map(command, new SchemaFieldsReordered())); - - return this; - } - - public SchemaDomainObject Publish(PublishSchema command) - { - VerifyCreatedAndNotDeleted(); - - RaiseEvent(SimpleMapper.Map(command, new SchemaPublished())); - - return this; - } - - public SchemaDomainObject Unpublish(UnpublishSchema command) - { - VerifyCreatedAndNotDeleted(); - - RaiseEvent(SimpleMapper.Map(command, new SchemaUnpublished())); - - return this; - } - - public SchemaDomainObject ConfigureScripts(ConfigureScripts command) - { - VerifyCreatedAndNotDeleted(); - - RaiseEvent(SimpleMapper.Map(command, new ScriptsConfigured())); - - return this; - } - - public SchemaDomainObject Delete(DeleteSchema command) - { - VerifyCreatedAndNotDeleted(); - - RaiseEvent(SimpleMapper.Map(command, new SchemaDeleted())); - - return this; - } - - public SchemaDomainObject Update(UpdateSchema command) - { - VerifyCreatedAndNotDeleted(); - - RaiseEvent(SimpleMapper.Map(command, new SchemaUpdated())); - - return this; - } - - protected void RaiseEvent(FieldCommand fieldCommand, FieldEvent @event) - { - SimpleMapper.Map(fieldCommand, @event); - - if (schema.FieldsById.TryGetValue(fieldCommand.FieldId, out var field)) - { - @event.FieldId = new NamedId(field.Id, field.Name); - } - - RaiseEvent(@event); - } - - private void VerifyNotCreated() - { - if (schema != null) - { - throw new DomainException("Schema has already been created."); - } - } - - private void VerifyCreatedAndNotDeleted() - { - if (isDeleted || schema == null) - { - throw new DomainException("Schema has already been deleted or not created yet."); - } - } - - protected override void DispatchEvent(Envelope @event) - { - this.DispatchAction(@event.Payload); - } - } -} \ No newline at end of file diff --git a/src/Squidex.Domain.Apps.Write/Squidex.Domain.Apps.Write.csproj b/src/Squidex.Domain.Apps.Write/Squidex.Domain.Apps.Write.csproj deleted file mode 100644 index 54328c3a8..000000000 --- a/src/Squidex.Domain.Apps.Write/Squidex.Domain.Apps.Write.csproj +++ /dev/null @@ -1,26 +0,0 @@ - - - netstandard2.0 - - - full - True - - - - - - - - - - - - - - - - - ..\..\Squidex.ruleset - - diff --git a/src/Squidex.Domain.Apps.Write/SquidexCommand.cs b/src/Squidex.Domain.Apps.Write/SquidexCommand.cs deleted file mode 100644 index 09507a691..000000000 --- a/src/Squidex.Domain.Apps.Write/SquidexCommand.cs +++ /dev/null @@ -1,20 +0,0 @@ -// ========================================================================== -// SquidexCommand.cs -// Squidex Headless CMS -// ========================================================================== -// Copyright (c) Squidex Group -// All rights reserved. -// ========================================================================== - -using Squidex.Infrastructure; -using Squidex.Infrastructure.Commands; - -namespace Squidex.Domain.Apps.Write -{ - public abstract class SquidexCommand : ICommand - { - public RefToken Actor { get; set; } - - public long? ExpectedVersion { get; set; } - } -} diff --git a/src/Squidex.Infrastructure.MongoDb/Migrations/MongoMigrationStatus.cs b/src/Squidex.Infrastructure.MongoDb/Migrations/MongoMigrationStatus.cs index e81626185..b9abb0515 100644 --- a/src/Squidex.Infrastructure.MongoDb/Migrations/MongoMigrationStatus.cs +++ b/src/Squidex.Infrastructure.MongoDb/Migrations/MongoMigrationStatus.cs @@ -21,9 +21,9 @@ namespace Squidex.Infrastructure.Migrations { } - public override void Connect() + protected override string CollectionName() { - base.Connect(); + return "Migration"; } public async Task GetVersionAsync() diff --git a/src/Squidex.Infrastructure.MongoDb/MongoDb/MongoRepositoryBase.cs b/src/Squidex.Infrastructure.MongoDb/MongoDb/MongoRepositoryBase.cs index 5183bc696..056dd8595 100644 --- a/src/Squidex.Infrastructure.MongoDb/MongoDb/MongoRepositoryBase.cs +++ b/src/Squidex.Infrastructure.MongoDb/MongoDb/MongoRepositoryBase.cs @@ -106,7 +106,7 @@ namespace Squidex.Infrastructure.MongoDb } } - public virtual void Connect() + public void Connect() { try { diff --git a/src/Squidex.Infrastructure.Redis/RedisSubscription.cs b/src/Squidex.Infrastructure.Redis/RedisSubscription.cs index 1a9d72b1f..2bd3fbe75 100644 --- a/src/Squidex.Infrastructure.Redis/RedisSubscription.cs +++ b/src/Squidex.Infrastructure.Redis/RedisSubscription.cs @@ -55,7 +55,7 @@ namespace Squidex.Infrastructure { log.LogError(ex, w => w .WriteProperty("action", "PublishRedisMessage") - .WriteProperty("state", "Failed") + .WriteProperty("status", "Failed") .WriteProperty("channel", channelName)); } } @@ -78,7 +78,7 @@ namespace Squidex.Infrastructure log.LogDebug(w => w .WriteProperty("action", "ReceiveRedisMessage") .WriteProperty("channel", channelName) - .WriteProperty("state", "Received")); + .WriteProperty("status", "Received")); } } catch (Exception ex) @@ -86,7 +86,7 @@ namespace Squidex.Infrastructure log.LogError(ex, w => w .WriteProperty("action", "ReceiveRedisMessage") .WriteProperty("channel", channelName) - .WriteProperty("state", "Failed")); + .WriteProperty("status", "Failed")); } } diff --git a/src/Squidex.Infrastructure/Commands/DomainObjectBase.cs b/src/Squidex.Infrastructure/Commands/DomainObjectBase.cs index b8351396c..56149843b 100644 --- a/src/Squidex.Infrastructure/Commands/DomainObjectBase.cs +++ b/src/Squidex.Infrastructure/Commands/DomainObjectBase.cs @@ -82,6 +82,13 @@ namespace Squidex.Infrastructure.Commands { } + public Task WriteStateAsync(long version) + { + state.Version = version; + + return persistence.WriteSnapshotAsync(state); + } + public async Task WriteAsync(ISemanticLog log) { var events = uncomittedEvents.ToArray(); diff --git a/src/Squidex.Infrastructure/Commands/LogCommandMiddleware.cs b/src/Squidex.Infrastructure/Commands/LogCommandMiddleware.cs index 7356207cb..f0df32720 100644 --- a/src/Squidex.Infrastructure/Commands/LogCommandMiddleware.cs +++ b/src/Squidex.Infrastructure/Commands/LogCommandMiddleware.cs @@ -30,13 +30,13 @@ namespace Squidex.Infrastructure.Commands log.LogInformation(w => w .WriteProperty("action", "HandleCommand.") .WriteProperty("actionId", context.ContextId.ToString()) - .WriteProperty("state", "Started") + .WriteProperty("status", "Started") .WriteProperty("commandType", context.Command.GetType().Name)); using (log.MeasureInformation(w => w .WriteProperty("action", "HandleCommand.") .WriteProperty("actionId", context.ContextId.ToString()) - .WriteProperty("state", "Completed") + .WriteProperty("status", "Completed") .WriteProperty("commandType", context.Command.GetType().Name))) { await next(); @@ -45,7 +45,7 @@ namespace Squidex.Infrastructure.Commands log.LogInformation(w => w .WriteProperty("action", "HandleCommand.") .WriteProperty("actionId", context.ContextId.ToString()) - .WriteProperty("state", "Succeeded") + .WriteProperty("status", "Succeeded") .WriteProperty("commandType", context.Command.GetType().Name)); } catch (Exception ex) @@ -53,7 +53,7 @@ namespace Squidex.Infrastructure.Commands log.LogError(ex, w => w .WriteProperty("action", "HandleCommand.") .WriteProperty("actionId", context.ContextId.ToString()) - .WriteProperty("state", "Failed") + .WriteProperty("status", "Failed") .WriteProperty("commandType", context.Command.GetType().Name)); throw; @@ -64,7 +64,7 @@ namespace Squidex.Infrastructure.Commands log.LogFatal(w => w .WriteProperty("action", "HandleCommand.") .WriteProperty("actionId", context.ContextId.ToString()) - .WriteProperty("state", "Unhandled") + .WriteProperty("status", "Unhandled") .WriteProperty("commandType", context.Command.GetType().Name)); } } diff --git a/src/Squidex.Infrastructure/EventSourcing/Grains/EventConsumerGrain.cs b/src/Squidex.Infrastructure/EventSourcing/Grains/EventConsumerGrain.cs index ef4cd9978..346e69345 100644 --- a/src/Squidex.Infrastructure/EventSourcing/Grains/EventConsumerGrain.cs +++ b/src/Squidex.Infrastructure/EventSourcing/Grains/EventConsumerGrain.cs @@ -213,7 +213,7 @@ namespace Squidex.Infrastructure.EventSourcing.Grains log.LogFatal(ex, w => w .WriteProperty("action", caller) - .WriteProperty("state", "Failed") + .WriteProperty("status", "Failed") .WriteProperty("eventConsumer", eventConsumer.Name)); state = state.Failed(ex); @@ -229,13 +229,13 @@ namespace Squidex.Infrastructure.EventSourcing.Grains log.LogInformation(w => w .WriteProperty("action", "EventConsumerReset") .WriteProperty("actionId", actionId) - .WriteProperty("state", "Started") + .WriteProperty("status", "Started") .WriteProperty("eventConsumer", eventConsumer.Name)); using (log.MeasureTrace(w => w .WriteProperty("action", "EventConsumerReset") .WriteProperty("actionId", actionId) - .WriteProperty("state", "Completed") + .WriteProperty("status", "Completed") .WriteProperty("eventConsumer", eventConsumer.Name))) { await eventConsumer.ClearAsync(); @@ -250,7 +250,7 @@ namespace Squidex.Infrastructure.EventSourcing.Grains log.LogInformation(w => w .WriteProperty("action", "HandleEvent") .WriteProperty("actionId", eventId) - .WriteProperty("state", "Started") + .WriteProperty("status", "Started") .WriteProperty("eventId", eventId) .WriteProperty("eventType", eventType) .WriteProperty("eventConsumer", eventConsumer.Name)); @@ -258,7 +258,7 @@ namespace Squidex.Infrastructure.EventSourcing.Grains using (log.MeasureTrace(w => w .WriteProperty("action", "HandleEvent") .WriteProperty("actionId", eventId) - .WriteProperty("state", "Completed") + .WriteProperty("status", "Completed") .WriteProperty("eventId", eventId) .WriteProperty("eventType", eventType) .WriteProperty("eventConsumer", eventConsumer.Name))) diff --git a/src/Squidex.Infrastructure/Migrations/Migrator.cs b/src/Squidex.Infrastructure/Migrations/Migrator.cs index 0be44904a..3ba7e29ce 100644 --- a/src/Squidex.Infrastructure/Migrations/Migrator.cs +++ b/src/Squidex.Infrastructure/Migrations/Migrator.cs @@ -55,9 +55,17 @@ namespace Squidex.Infrastructure.Migrations foreach (var migrator in migrationPath) { + var name = migrator.GetType().ToString(); + + log.LogInformation(w => w + .WriteProperty("action", "Migration") + .WriteProperty("status", "Started") + .WriteProperty("migrator", name)); + using (log.MeasureInformation(w => w .WriteProperty("action", "Migration") - .WriteProperty("migrator", migrator.GetType().ToString()))) + .WriteProperty("status", "Completed") + .WriteProperty("migrator", name))) { await migrator.UpdateAsync(); diff --git a/src/Squidex/Config/Domain/InfrastructureServices.cs b/src/Squidex/Config/Domain/InfrastructureServices.cs index 5552c561a..b8cd37168 100644 --- a/src/Squidex/Config/Domain/InfrastructureServices.cs +++ b/src/Squidex/Config/Domain/InfrastructureServices.cs @@ -19,6 +19,7 @@ using Squidex.Infrastructure.Assets.ImageSharp; using Squidex.Infrastructure.Commands; using Squidex.Infrastructure.EventSourcing; using Squidex.Infrastructure.Log; +using Squidex.Infrastructure.Migrations; using Squidex.Infrastructure.States; using Squidex.Infrastructure.UsageTracking; using Squidex.Pipeline; @@ -91,6 +92,9 @@ namespace Squidex.Config.Domain services.AddSingletonAs() .As(); + + services.AddSingletonAs() + .AsSelf(); } } } diff --git a/src/Squidex/Config/Domain/ReadServices.cs b/src/Squidex/Config/Domain/ReadServices.cs index 2fd571e14..54c9958ce 100644 --- a/src/Squidex/Config/Domain/ReadServices.cs +++ b/src/Squidex/Config/Domain/ReadServices.cs @@ -109,8 +109,11 @@ namespace Squidex.Config.Domain return new EventConsumerFactory(n => allEventConsumers.FirstOrDefault(x => x.Name == n)); }); - services.AddSingletonAs(); - services.AddSingleton(); + services.AddSingletonAs() + .AsSelf(); + + services.AddSingletonAs() + .AsSelf(); } } } diff --git a/src/Squidex/Config/Domain/SerializationServices.cs b/src/Squidex/Config/Domain/SerializationServices.cs index e95127b89..fe051bd44 100644 --- a/src/Squidex/Config/Domain/SerializationServices.cs +++ b/src/Squidex/Config/Domain/SerializationServices.cs @@ -7,6 +7,7 @@ // ========================================================================== using Microsoft.Extensions.DependencyInjection; +using Migrate_01; using Newtonsoft.Json; using Newtonsoft.Json.Converters; using NodaTime; @@ -26,7 +27,12 @@ namespace Squidex.Config.Domain { public static class SerializationServices { - private static readonly TypeNameRegistry TypeNameRegistry = new TypeNameRegistry(); + private static readonly TypeNameRegistry TypeNameRegistry = + new TypeNameRegistry() + .MapUnmapped(typeof(Migration01).Assembly) + .MapUnmapped(typeof(SquidexCoreModel).Assembly) + .MapUnmapped(typeof(SquidexEvents).Assembly) + .MapUnmapped(typeof(SquidexInfrastructure).Assembly); private static readonly JsonSerializerSettings SerializerSettings = new JsonSerializerSettings(); private static readonly FieldRegistry FieldRegistry = new FieldRegistry(TypeNameRegistry); @@ -68,10 +74,6 @@ namespace Squidex.Config.Domain static SerializationServices() { - TypeNameRegistry.MapUnmapped(typeof(SquidexCoreModel).Assembly); - TypeNameRegistry.MapUnmapped(typeof(SquidexEvents).Assembly); - TypeNameRegistry.MapUnmapped(typeof(SquidexInfrastructure).Assembly); - ConfigureJson(SerializerSettings, TypeNameHandling.Auto); BsonJsonConvention.Register(JsonSerializer.Create(SerializerSettings)); diff --git a/src/Squidex/Config/Domain/StoreServices.cs b/src/Squidex/Config/Domain/StoreServices.cs index 416402e05..ce4fe184d 100644 --- a/src/Squidex/Config/Domain/StoreServices.cs +++ b/src/Squidex/Config/Domain/StoreServices.cs @@ -107,7 +107,7 @@ namespace Squidex.Config.Domain .As>() .As(); - services.AddSingletonAs(c => new MongoRuleRepository(mongoContentDatabase)) + services.AddSingletonAs(c => new MongoRuleRepository(mongoDatabase)) .As() .As>() .As(); diff --git a/src/Squidex/Config/Domain/WriteServices.cs b/src/Squidex/Config/Domain/WriteServices.cs index 6a910e333..524c3e121 100644 --- a/src/Squidex/Config/Domain/WriteServices.cs +++ b/src/Squidex/Config/Domain/WriteServices.cs @@ -7,6 +7,7 @@ // ========================================================================== using Microsoft.Extensions.DependencyInjection; +using Migrate_01; using Squidex.Domain.Apps.Core.Scripting; using Squidex.Domain.Apps.Entities.Apps; using Squidex.Domain.Apps.Entities.Assets; @@ -15,6 +16,7 @@ using Squidex.Domain.Apps.Entities.Rules; using Squidex.Domain.Apps.Entities.Schemas; using Squidex.Domain.Users; using Squidex.Infrastructure.Commands; +using Squidex.Infrastructure.Migrations; using Squidex.Pipeline.CommandMiddlewares; namespace Squidex.Config.Domain @@ -59,11 +61,23 @@ namespace Squidex.Config.Domain services.AddSingletonAs() .As(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); + services.AddTransientAs() + .As(); + + services.AddTransientAs() + .AsSelf(); + + services.AddTransientAs() + .AsSelf(); + + services.AddTransientAs() + .AsSelf(); + + services.AddTransientAs() + .AsSelf(); + + services.AddTransientAs() + .AsSelf(); } } } diff --git a/src/Squidex/Config/ServiceExtensions.cs b/src/Squidex/Config/ServiceExtensions.cs index 61050959f..f2c670304 100644 --- a/src/Squidex/Config/ServiceExtensions.cs +++ b/src/Squidex/Config/ServiceExtensions.cs @@ -25,6 +25,11 @@ namespace Squidex.Config this.services = services; } + public InterfaceRegistrator AsSelf() + { + return this; + } + public InterfaceRegistrator As() { if (typeof(TInterface) != typeof(T)) @@ -39,6 +44,20 @@ namespace Squidex.Config } } + public static InterfaceRegistrator AddTransientAs(this IServiceCollection services, Func factory) where T : class + { + services.AddTransient(typeof(T), factory); + + return new InterfaceRegistrator(services); + } + + public static InterfaceRegistrator AddTransientAs(this IServiceCollection services) where T : class + { + services.AddTransient(); + + return new InterfaceRegistrator(services); + } + public static InterfaceRegistrator AddSingletonAs(this IServiceCollection services, Func factory) where T : class { services.AddSingleton(typeof(T), factory); diff --git a/src/Squidex/Squidex.csproj b/src/Squidex/Squidex.csproj index bd330a626..2d5357db2 100644 --- a/src/Squidex/Squidex.csproj +++ b/src/Squidex/Squidex.csproj @@ -29,6 +29,7 @@ + diff --git a/src/Squidex/WebStartup.cs b/src/Squidex/WebStartup.cs index fef509b0b..d88b28055 100644 --- a/src/Squidex/WebStartup.cs +++ b/src/Squidex/WebStartup.cs @@ -39,8 +39,8 @@ namespace Squidex public void Configure(IApplicationBuilder app) { app.ApplicationServices.LogConfiguration(); - app.ApplicationServices.TestExternalSystems(); app.ApplicationServices.Migrate(); + app.ApplicationServices.TestExternalSystems(); app.UseMyCors(); app.UseMyForwardingRules(); diff --git a/tools/Migrate_01/Migrate_01.csproj b/tools/Migrate_01/Migrate_01.csproj new file mode 100644 index 000000000..c782b2dec --- /dev/null +++ b/tools/Migrate_01/Migrate_01.csproj @@ -0,0 +1,14 @@ + + + netstandard2.0 + + + + + + + + + ..\..\Squidex.ruleset + + diff --git a/tools/Migrate_01/Migration01.cs b/tools/Migrate_01/Migration01.cs new file mode 100644 index 000000000..e2b1d6d0d --- /dev/null +++ b/tools/Migrate_01/Migration01.cs @@ -0,0 +1,129 @@ +// ========================================================================== +// MigrateToEntities.cs +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex Group +// All rights reserved. +// ========================================================================== + +using System; +using System.Threading.Tasks; +using System.Timers; +using Squidex.Domain.Apps.Core.Schemas; +using Squidex.Domain.Apps.Entities.Apps; +using Squidex.Domain.Apps.Entities.Assets; +using Squidex.Domain.Apps.Entities.Contents; +using Squidex.Domain.Apps.Entities.Schemas; +using Squidex.Domain.Apps.Events; +using Squidex.Domain.Apps.Events.Assets; +using Squidex.Domain.Apps.Events.Contents; +using Squidex.Infrastructure; +using Squidex.Infrastructure.EventSourcing; +using Squidex.Infrastructure.Migrations; +using Squidex.Infrastructure.States; +using Squidex.Infrastructure.Tasks; + +namespace Migrate_01 +{ + public sealed class Migration01 : IMigration, IEventSubscriber + { + private readonly FieldRegistry fieldRegistry; + private readonly IEventStore eventStore; + private readonly IEventDataFormatter eventDataFormatter; + private readonly IStateFactory stateFactory; + private readonly Timer timer = new Timer { AutoReset = false, Interval = 5000 }; + private readonly TaskCompletionSource tcs = new TaskCompletionSource(); + + public int FromVersion { get; } = 0; + + public int ToVersion { get; } = 1; + + public Migration01( + FieldRegistry fieldRegistry, + IEventDataFormatter eventDataFormatter, + IEventStore eventStore, + IStateFactory stateFactory) + { + this.fieldRegistry = fieldRegistry; + this.eventDataFormatter = eventDataFormatter; + this.eventStore = eventStore; + this.stateFactory = stateFactory; + + timer.Elapsed += (sender, e) => + { + tcs.TrySetResult(true); + }; + } + + public async Task UpdateAsync() + { + var subscription = eventStore.CreateSubscription(this, ".*"); + + await tcs.Task; + await subscription.StopAsync(); + } + + public async Task OnEventAsync(IEventSubscription subscription, StoredEvent storedEvent) + { + var @event = ParseKnownEvent(storedEvent); + + if (@event != null) + { + var version = storedEvent.EventStreamNumber; + + if (@event.Payload is AssetEvent assetEvent) + { + var asset = await stateFactory.CreateAsync(assetEvent.AssetId); + + asset.UpdateState(asset.State.Apply(@event)); + + await asset.WriteStateAsync(version); + } + else if (@event.Payload is ContentEvent contentEvent) + { + var content = await stateFactory.CreateAsync(contentEvent.ContentId); + + content.UpdateState(content.State.Apply(@event)); + + await content.WriteStateAsync(version); + } + else if (@event.Payload is SchemaEvent schemaEvent) + { + var schema = await stateFactory.GetSingleAsync(schemaEvent.SchemaId.Id); + + schema.UpdateState(schema.State.Apply(@event, fieldRegistry)); + + await schema.WriteStateAsync(version); + } + else if (@event.Payload is AppEvent appEvent) + { + var app = await stateFactory.GetSingleAsync(appEvent.AppId.Id); + + app.UpdateState(app.State.Apply(@event)); + + await app.WriteStateAsync(version); + } + } + + timer.Stop(); + timer.Start(); + } + + public Task OnErrorAsync(IEventSubscription subscription, Exception exception) + { + return TaskHelper.Done; + } + + private Envelope ParseKnownEvent(StoredEvent storedEvent) + { + try + { + return eventDataFormatter.Parse(storedEvent.Data); + } + catch (TypeNameNotFoundException) + { + return null; + } + } + } +} diff --git a/src/Squidex.Domain.Apps.Events/Apps/Old/AppClientChanged.cs b/tools/Migrate_01/OldEvents/AppClientChanged.cs similarity index 87% rename from src/Squidex.Domain.Apps.Events/Apps/Old/AppClientChanged.cs rename to tools/Migrate_01/OldEvents/AppClientChanged.cs index 7e459b244..63df3e55a 100644 --- a/src/Squidex.Domain.Apps.Events/Apps/Old/AppClientChanged.cs +++ b/tools/Migrate_01/OldEvents/AppClientChanged.cs @@ -6,13 +6,17 @@ // All rights reserved. // ========================================================================== +using System; using Squidex.Domain.Apps.Core.Apps; +using Squidex.Domain.Apps.Events; +using Squidex.Domain.Apps.Events.Apps; using Squidex.Infrastructure.EventSourcing; using Squidex.Infrastructure.Reflection; -namespace Squidex.Domain.Apps.Events.Apps.Old +namespace Migrate_01.OldEvents { [EventType(nameof(AppClientChanged))] + [Obsolete] public sealed class AppClientChanged : AppEvent, IMigratedEvent { public string Id { get; set; } diff --git a/src/Squidex.Domain.Apps.Events/Contents/Old/ContentArchived.cs b/tools/Migrate_01/OldEvents/ContentArchived.cs similarity index 91% rename from src/Squidex.Domain.Apps.Events/Contents/Old/ContentArchived.cs rename to tools/Migrate_01/OldEvents/ContentArchived.cs index 7402dd378..797342e21 100644 --- a/src/Squidex.Domain.Apps.Events/Contents/Old/ContentArchived.cs +++ b/tools/Migrate_01/OldEvents/ContentArchived.cs @@ -8,10 +8,11 @@ using System; using Squidex.Domain.Apps.Core.Contents; +using Squidex.Domain.Apps.Events.Contents; using Squidex.Infrastructure.EventSourcing; using Squidex.Infrastructure.Reflection; -namespace Squidex.Domain.Apps.Events.Contents.Old +namespace Migrate_01.OldEvents { [EventType(nameof(ContentArchived))] [Obsolete] diff --git a/src/Squidex.Domain.Apps.Events/Contents/Old/ContentPublished.cs b/tools/Migrate_01/OldEvents/ContentPublished.cs similarity index 91% rename from src/Squidex.Domain.Apps.Events/Contents/Old/ContentPublished.cs rename to tools/Migrate_01/OldEvents/ContentPublished.cs index 578eac373..4dd3f9c26 100644 --- a/src/Squidex.Domain.Apps.Events/Contents/Old/ContentPublished.cs +++ b/tools/Migrate_01/OldEvents/ContentPublished.cs @@ -8,10 +8,11 @@ using System; using Squidex.Domain.Apps.Core.Contents; +using Squidex.Domain.Apps.Events.Contents; using Squidex.Infrastructure.EventSourcing; using Squidex.Infrastructure.Reflection; -namespace Squidex.Domain.Apps.Events.Contents.Old +namespace Migrate_01.OldEvents { [EventType(nameof(ContentPublished))] [Obsolete] diff --git a/src/Squidex.Domain.Apps.Events/Contents/Old/ContentRestored.cs b/tools/Migrate_01/OldEvents/ContentRestored.cs similarity index 91% rename from src/Squidex.Domain.Apps.Events/Contents/Old/ContentRestored.cs rename to tools/Migrate_01/OldEvents/ContentRestored.cs index 5e1526eec..e67d9288e 100644 --- a/src/Squidex.Domain.Apps.Events/Contents/Old/ContentRestored.cs +++ b/tools/Migrate_01/OldEvents/ContentRestored.cs @@ -8,10 +8,11 @@ using System; using Squidex.Domain.Apps.Core.Contents; +using Squidex.Domain.Apps.Events.Contents; using Squidex.Infrastructure.EventSourcing; using Squidex.Infrastructure.Reflection; -namespace Squidex.Domain.Apps.Events.Contents.Old +namespace Migrate_01.OldEvents { [EventType(nameof(ContentRestored))] [Obsolete] diff --git a/src/Squidex.Domain.Apps.Events/Contents/Old/ContentUnpublished.cs b/tools/Migrate_01/OldEvents/ContentUnpublished.cs similarity index 91% rename from src/Squidex.Domain.Apps.Events/Contents/Old/ContentUnpublished.cs rename to tools/Migrate_01/OldEvents/ContentUnpublished.cs index 2908f8ee2..3d22e3dd9 100644 --- a/src/Squidex.Domain.Apps.Events/Contents/Old/ContentUnpublished.cs +++ b/tools/Migrate_01/OldEvents/ContentUnpublished.cs @@ -8,10 +8,11 @@ using System; using Squidex.Domain.Apps.Core.Contents; +using Squidex.Domain.Apps.Events.Contents; using Squidex.Infrastructure.EventSourcing; using Squidex.Infrastructure.Reflection; -namespace Squidex.Domain.Apps.Events.Contents.Old +namespace Migrate_01.OldEvents { [EventType(nameof(ContentUnpublished))] [Obsolete] diff --git a/src/Squidex.Domain.Apps.Events/Schemas/Old/WebhookAdded.cs b/tools/Migrate_01/OldEvents/WebhookAdded.cs similarity index 90% rename from src/Squidex.Domain.Apps.Events/Schemas/Old/WebhookAdded.cs rename to tools/Migrate_01/OldEvents/WebhookAdded.cs index f39b91618..8735e9ab4 100644 --- a/src/Squidex.Domain.Apps.Events/Schemas/Old/WebhookAdded.cs +++ b/tools/Migrate_01/OldEvents/WebhookAdded.cs @@ -7,9 +7,10 @@ // ========================================================================== using System; +using Squidex.Domain.Apps.Events; using Squidex.Infrastructure.EventSourcing; -namespace Squidex.Domain.Apps.Events.Schemas.Old +namespace Migrate_01.OldEvents { [EventType(nameof(WebhookAdded))] [Obsolete] diff --git a/src/Squidex.Domain.Apps.Events/Schemas/Old/WebhookDeleted.cs b/tools/Migrate_01/OldEvents/WebhookDeleted.cs similarity index 89% rename from src/Squidex.Domain.Apps.Events/Schemas/Old/WebhookDeleted.cs rename to tools/Migrate_01/OldEvents/WebhookDeleted.cs index c579d224a..3615e36ce 100644 --- a/src/Squidex.Domain.Apps.Events/Schemas/Old/WebhookDeleted.cs +++ b/tools/Migrate_01/OldEvents/WebhookDeleted.cs @@ -7,9 +7,10 @@ // ========================================================================== using System; +using Squidex.Domain.Apps.Events; using Squidex.Infrastructure.EventSourcing; -namespace Squidex.Domain.Apps.Events.Schemas.Old +namespace Migrate_01.OldEvents { [EventType(nameof(WebhookDeleted))] [Obsolete]