From 41d586190297d11d0ff33d7920fd1a3be475efb7 Mon Sep 17 00:00:00 2001 From: Raphael Kuster Date: Sat, 12 Oct 2024 15:39:04 +0200 Subject: [PATCH 1/4] chore(sln): upgraded to slnx --- src/FluentCMS.sln | 265 --------------------------------------------- src/FluentCMS.slnx | 54 +++++++++ 2 files changed, 54 insertions(+), 265 deletions(-) delete mode 100644 src/FluentCMS.sln create mode 100644 src/FluentCMS.slnx diff --git a/src/FluentCMS.sln b/src/FluentCMS.sln deleted file mode 100644 index c4eb1e849..000000000 --- a/src/FluentCMS.sln +++ /dev/null @@ -1,265 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.7.34031.279 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FluentCMS", "FluentCMS\FluentCMS.csproj", "{2B2327C2-DD1F-446C-AD24-B19883A7A30D}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Backend", "Backend", "{07500646-19CF-415A-A1E5-0CDFDFE76127}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Repositories", "Repositories", "{1CC73AD2-CFC9-4FE7-96C0-0E4FEFBB66F1}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FluentCMS.Entities", "Backend\FluentCMS.Entities\FluentCMS.Entities.csproj", "{2C9B5E9D-900E-4D82-A576-106FE035CAE1}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FluentCMS.Repositories.Abstractions", "Backend\Repositories\FluentCMS.Repositories.Abstractions\FluentCMS.Repositories.Abstractions.csproj", "{F295C81A-BE85-4121-A594-3ECD741DF9E5}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FluentCMS.Repositories.LiteDb", "Backend\Repositories\FluentCMS.Repositories.LiteDb\FluentCMS.Repositories.LiteDb.csproj", "{B2A94C28-1A5C-4F75-851A-DFC4A5077FAA}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FluentCMS.Repositories.MongoDB", "Backend\Repositories\FluentCMS.Repositories.MongoDB\FluentCMS.Repositories.MongoDB.csproj", "{AB6D5218-A3FE-410F-B729-E4CB2AA54C8F}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FluentCMS.Identity", "Backend\FluentCMS.Identity\FluentCMS.Identity.csproj", "{E0873894-C1E6-4933-8519-052C9D53CD32}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FluentCMS.Services", "Backend\FluentCMS.Services\FluentCMS.Services.csproj", "{CC105757-549C-418F-B564-8C40111B9C57}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FluentCMS.Web.Api", "Backend\FluentCMS.Web.Api\FluentCMS.Web.Api.csproj", "{5A1E21A9-1014-4E1B-B7A5-B9B77ECB7045}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Frontend", "Frontend", "{5961A5E0-54A6-42F5-92A2-9A9E48DE2878}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FluentCMS.Web.ApiClients", "Frontend\FluentCMS.Web.ApiClients\FluentCMS.Web.ApiClients.csproj", "{3751A4FF-ACEC-470F-ABF0-660338EBCF0F}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FluentCMS.Web.UI.Components", "Frontend\FluentCMS.Web.UI.Components\FluentCMS.Web.UI.Components.csproj", "{D165FEE4-4EA8-46FE-B5EC-9A3178CAC615}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FluentCMS.Web.UI", "Frontend\FluentCMS.Web.UI\FluentCMS.Web.UI.csproj", "{D438CECE-FB91-4E2A-9182-D386222D8C92}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Plugins", "Plugins", "{BB5FD6A0-0840-4381-AB68-AD61499368ED}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Shared", "Shared\Shared.csproj", "{E78B903B-4307-4220-B451-3000ED3E9971}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FluentCMS.Web.Plugins.Admin", "Frontend\Plugins\FluentCMS.Web.Plugins.Admin\FluentCMS.Web.Plugins.Admin.csproj", "{70B5742E-C249-4B51-985C-2B4B7BDAB489}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FluentCMS.Web.Plugins.Contents.TextHTML", "Frontend\Plugins\FluentCMS.Web.Plugins.Contents.TextHTML\FluentCMS.Web.Plugins.Contents.TextHTML.csproj", "{818F8CD0-5218-4480-A541-BD9D59416CDE}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FluentCMS.Web.Plugins.Contents.Block", "Frontend\Plugins\FluentCMS.Web.Plugins.Contents.Block\FluentCMS.Web.Plugins.Contents.Block.csproj", "{9D8B6051-BE99-42E4-B569-43ABA3A9510D}" -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FluentCMS.Web.Plugins.Contents.RichText", "Frontend\Plugins\FluentCMS.Web.Plugins.Contents.RichText\FluentCMS.Web.Plugins.Contents.RichText.csproj", "{54DBC633-2A8D-4531-AA22-23824C6CFCD9}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Providers", "Providers", "{CA060C96-322D-4410-8D32-0AF5DA8A975C}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "EmailProviders", "EmailProviders", "{0A4945C1-1089-4331-B9F4-2AB98BCB4D39}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "FileStorageProviders", "FileStorageProviders", "{6BF48DBC-42A7-412E-8894-39E61BA7EF8A}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ApiTokenProviders", "ApiTokenProviders", "{ACD2C7B7-2227-4E25-88F8-8B45BCE89584}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "MessageBusProviders", "MessageBusProviders", "{2FF62DC2-6027-4F9F-A6A9-3DA46D2B88E2}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FluentCMS.Providers.ApiTokenProviders.Abstractions", "Providers\ApiTokenProviders\FluentCMS.Providers.ApiTokenProviders.Abstractions\FluentCMS.Providers.ApiTokenProviders.Abstractions.csproj", "{207E4FB5-2614-4E19-B593-C9F1254DF44D}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FluentCMS.Providers.ApiTokenProviders", "Providers\ApiTokenProviders\FluentCMS.Providers.ApiTokenProviders\FluentCMS.Providers.ApiTokenProviders.csproj", "{D000CB33-97FD-4074-946B-CED146812CCD}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FluentCMS.Providers.EmailProviders.Abstractions", "Providers\EmailProviders\FluentCMS.Providers.EmailProviders.Abstractions\FluentCMS.Providers.EmailProviders.Abstractions.csproj", "{1F36D46A-5D9C-42E5-BC17-44C07A4484B4}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FluentCMS.Providers.EmailProviders", "Providers\EmailProviders\FluentCMS.Providers.EmailProviders\FluentCMS.Providers.EmailProviders.csproj", "{A355D8E5-1BA2-4267-BEC5-0F21A8D41B45}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FluentCMS.Providers.FileStorageProviders.Abstractions", "Providers\FileStorageProviders\FluentCMS.Providers.FileStorageProviders.Abstractions\FluentCMS.Providers.FileStorageProviders.Abstractions.csproj", "{A0D762CD-19DF-4F35-B4B2-B2171168F00B}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FluentCMS.Providers.MessageBusProviders.Abstractions", "Providers\MessageBusProviders\FluentCMS.Providers.MessageBusProviders.Abstractions\FluentCMS.Providers.MessageBusProviders.Abstractions.csproj", "{1ADA3DC1-E56B-4648-AD6D-FE8A166ECAD0}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FluentCMS.Providers.MessageBusProviders", "Providers\MessageBusProviders\FluentCMS.Providers.MessageBusProviders\FluentCMS.Providers.MessageBusProviders.csproj", "{F24BF4C8-5E7C-41FE-8E15-1318CEE2F136}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FluentCMS.Providers.FileStorageProviders", "Providers\FileStorageProviders\FluentCMS.Providers.FileStorageProviders\FluentCMS.Providers.FileStorageProviders.csproj", "{2673EBC9-E99C-4A3F-AEA1-72FF42DEAD0C}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FluentCMS.Web.Plugins.Contents.ContentViewer", "Frontend\Plugins\FluentCMS.Web.Plugins.Contents.ContentViewer\FluentCMS.Web.Plugins.Contents.ContentViewer.csproj", "{2FB1EE8A-F07C-41F6-855C-031CA3346BFA}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "TemplateRenderingProviders", "TemplateRenderingProviders", "{7705739E-5D69-4DF4-8C77-34AD3D991683}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FluentCMS.Providers.TemplateRenderingProviders.Abstractions", "Providers\TemplateRenderingProviders\FluentCMS.Providers.TemplateRenderingProviders.Abstractions\FluentCMS.Providers.TemplateRenderingProviders.Abstractions.csproj", "{6238A269-B71B-444D-815C-2CDB340AEEE9}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FluentCMS.Providers.TemplateRenderingProviders", "Providers\TemplateRenderingProviders\FluentCMS.Providers.TemplateRenderingProviders\FluentCMS.Providers.TemplateRenderingProviders.csproj", "{6E1E6F02-6930-41C2-B03A-2BE94F167F6F}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FluentCMS.Web.Plugins.Base", "Frontend\Plugins\FluentCMS.Web.Plugins.Base\FluentCMS.Web.Plugins.Base.csproj", "{19A3D26D-9ECB-4C0A-AE1C-CE30A13A6A1A}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FluentCMS.Repositories.Caching", "Backend\Repositories\FluentCMS.Repositories.Caching\FluentCMS.Repositories.Caching.csproj", "{4D1A89DA-D736-41B5-9AFD-8F30FE5DAA76}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "CacheProviders", "CacheProviders", "{016945AB-5C4D-42A1-81B9-8C12FC6E40E6}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FluentCMS.Providers.CacheProviders", "Providers\CacheProviders\FluentCMS.Providers.CacheProviders\FluentCMS.Providers.CacheProviders.csproj", "{6FEFA4A7-CF69-44CD-BD03-AC5C702B7BA0}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FluentCMS.Providers.CacheProviders.Abstractions", "Providers\CacheProviders\FluentCMS.Providers.CacheProviders.Abstractions\FluentCMS.Providers.CacheProviders.Abstractions.csproj", "{97999608-B9AD-46B4-AF10-311B109A90BE}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {2B2327C2-DD1F-446C-AD24-B19883A7A30D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {2B2327C2-DD1F-446C-AD24-B19883A7A30D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {2B2327C2-DD1F-446C-AD24-B19883A7A30D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {2B2327C2-DD1F-446C-AD24-B19883A7A30D}.Release|Any CPU.Build.0 = Release|Any CPU - {2C9B5E9D-900E-4D82-A576-106FE035CAE1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {2C9B5E9D-900E-4D82-A576-106FE035CAE1}.Debug|Any CPU.Build.0 = Debug|Any CPU - {2C9B5E9D-900E-4D82-A576-106FE035CAE1}.Release|Any CPU.ActiveCfg = Release|Any CPU - {2C9B5E9D-900E-4D82-A576-106FE035CAE1}.Release|Any CPU.Build.0 = Release|Any CPU - {F295C81A-BE85-4121-A594-3ECD741DF9E5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {F295C81A-BE85-4121-A594-3ECD741DF9E5}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F295C81A-BE85-4121-A594-3ECD741DF9E5}.Release|Any CPU.ActiveCfg = Release|Any CPU - {F295C81A-BE85-4121-A594-3ECD741DF9E5}.Release|Any CPU.Build.0 = Release|Any CPU - {B2A94C28-1A5C-4F75-851A-DFC4A5077FAA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B2A94C28-1A5C-4F75-851A-DFC4A5077FAA}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B2A94C28-1A5C-4F75-851A-DFC4A5077FAA}.Release|Any CPU.ActiveCfg = Release|Any CPU - {B2A94C28-1A5C-4F75-851A-DFC4A5077FAA}.Release|Any CPU.Build.0 = Release|Any CPU - {AB6D5218-A3FE-410F-B729-E4CB2AA54C8F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {AB6D5218-A3FE-410F-B729-E4CB2AA54C8F}.Debug|Any CPU.Build.0 = Debug|Any CPU - {AB6D5218-A3FE-410F-B729-E4CB2AA54C8F}.Release|Any CPU.ActiveCfg = Release|Any CPU - {AB6D5218-A3FE-410F-B729-E4CB2AA54C8F}.Release|Any CPU.Build.0 = Release|Any CPU - {E0873894-C1E6-4933-8519-052C9D53CD32}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {E0873894-C1E6-4933-8519-052C9D53CD32}.Debug|Any CPU.Build.0 = Debug|Any CPU - {E0873894-C1E6-4933-8519-052C9D53CD32}.Release|Any CPU.ActiveCfg = Release|Any CPU - {E0873894-C1E6-4933-8519-052C9D53CD32}.Release|Any CPU.Build.0 = Release|Any CPU - {CC105757-549C-418F-B564-8C40111B9C57}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {CC105757-549C-418F-B564-8C40111B9C57}.Debug|Any CPU.Build.0 = Debug|Any CPU - {CC105757-549C-418F-B564-8C40111B9C57}.Release|Any CPU.ActiveCfg = Release|Any CPU - {CC105757-549C-418F-B564-8C40111B9C57}.Release|Any CPU.Build.0 = Release|Any CPU - {5A1E21A9-1014-4E1B-B7A5-B9B77ECB7045}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {5A1E21A9-1014-4E1B-B7A5-B9B77ECB7045}.Debug|Any CPU.Build.0 = Debug|Any CPU - {5A1E21A9-1014-4E1B-B7A5-B9B77ECB7045}.Release|Any CPU.ActiveCfg = Release|Any CPU - {5A1E21A9-1014-4E1B-B7A5-B9B77ECB7045}.Release|Any CPU.Build.0 = Release|Any CPU - {3751A4FF-ACEC-470F-ABF0-660338EBCF0F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {3751A4FF-ACEC-470F-ABF0-660338EBCF0F}.Debug|Any CPU.Build.0 = Debug|Any CPU - {3751A4FF-ACEC-470F-ABF0-660338EBCF0F}.Release|Any CPU.ActiveCfg = Release|Any CPU - {3751A4FF-ACEC-470F-ABF0-660338EBCF0F}.Release|Any CPU.Build.0 = Release|Any CPU - {D165FEE4-4EA8-46FE-B5EC-9A3178CAC615}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D165FEE4-4EA8-46FE-B5EC-9A3178CAC615}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D165FEE4-4EA8-46FE-B5EC-9A3178CAC615}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D165FEE4-4EA8-46FE-B5EC-9A3178CAC615}.Release|Any CPU.Build.0 = Release|Any CPU - {D438CECE-FB91-4E2A-9182-D386222D8C92}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D438CECE-FB91-4E2A-9182-D386222D8C92}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D438CECE-FB91-4E2A-9182-D386222D8C92}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D438CECE-FB91-4E2A-9182-D386222D8C92}.Release|Any CPU.Build.0 = Release|Any CPU - {E78B903B-4307-4220-B451-3000ED3E9971}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {E78B903B-4307-4220-B451-3000ED3E9971}.Debug|Any CPU.Build.0 = Debug|Any CPU - {E78B903B-4307-4220-B451-3000ED3E9971}.Release|Any CPU.ActiveCfg = Release|Any CPU - {E78B903B-4307-4220-B451-3000ED3E9971}.Release|Any CPU.Build.0 = Release|Any CPU - {70B5742E-C249-4B51-985C-2B4B7BDAB489}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {70B5742E-C249-4B51-985C-2B4B7BDAB489}.Debug|Any CPU.Build.0 = Debug|Any CPU - {70B5742E-C249-4B51-985C-2B4B7BDAB489}.Release|Any CPU.ActiveCfg = Release|Any CPU - {70B5742E-C249-4B51-985C-2B4B7BDAB489}.Release|Any CPU.Build.0 = Release|Any CPU - {818F8CD0-5218-4480-A541-BD9D59416CDE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {818F8CD0-5218-4480-A541-BD9D59416CDE}.Debug|Any CPU.Build.0 = Debug|Any CPU - {818F8CD0-5218-4480-A541-BD9D59416CDE}.Release|Any CPU.ActiveCfg = Release|Any CPU - {818F8CD0-5218-4480-A541-BD9D59416CDE}.Release|Any CPU.Build.0 = Release|Any CPU - {9D8B6051-BE99-42E4-B569-43ABA3A9510D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {9D8B6051-BE99-42E4-B569-43ABA3A9510D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {9D8B6051-BE99-42E4-B569-43ABA3A9510D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {9D8B6051-BE99-42E4-B569-43ABA3A9510D}.Release|Any CPU.Build.0 = Release|Any CPU - {54DBC633-2A8D-4531-AA22-23824C6CFCD9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {54DBC633-2A8D-4531-AA22-23824C6CFCD9}.Debug|Any CPU.Build.0 = Debug|Any CPU - {54DBC633-2A8D-4531-AA22-23824C6CFCD9}.Release|Any CPU.ActiveCfg = Release|Any CPU - {54DBC633-2A8D-4531-AA22-23824C6CFCD9}.Release|Any CPU.Build.0 = Release|Any CPU - {207E4FB5-2614-4E19-B593-C9F1254DF44D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {207E4FB5-2614-4E19-B593-C9F1254DF44D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {207E4FB5-2614-4E19-B593-C9F1254DF44D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {207E4FB5-2614-4E19-B593-C9F1254DF44D}.Release|Any CPU.Build.0 = Release|Any CPU - {D000CB33-97FD-4074-946B-CED146812CCD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D000CB33-97FD-4074-946B-CED146812CCD}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D000CB33-97FD-4074-946B-CED146812CCD}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D000CB33-97FD-4074-946B-CED146812CCD}.Release|Any CPU.Build.0 = Release|Any CPU - {1F36D46A-5D9C-42E5-BC17-44C07A4484B4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {1F36D46A-5D9C-42E5-BC17-44C07A4484B4}.Debug|Any CPU.Build.0 = Debug|Any CPU - {1F36D46A-5D9C-42E5-BC17-44C07A4484B4}.Release|Any CPU.ActiveCfg = Release|Any CPU - {1F36D46A-5D9C-42E5-BC17-44C07A4484B4}.Release|Any CPU.Build.0 = Release|Any CPU - {A355D8E5-1BA2-4267-BEC5-0F21A8D41B45}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A355D8E5-1BA2-4267-BEC5-0F21A8D41B45}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A355D8E5-1BA2-4267-BEC5-0F21A8D41B45}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A355D8E5-1BA2-4267-BEC5-0F21A8D41B45}.Release|Any CPU.Build.0 = Release|Any CPU - {A0D762CD-19DF-4F35-B4B2-B2171168F00B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A0D762CD-19DF-4F35-B4B2-B2171168F00B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A0D762CD-19DF-4F35-B4B2-B2171168F00B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A0D762CD-19DF-4F35-B4B2-B2171168F00B}.Release|Any CPU.Build.0 = Release|Any CPU - {1ADA3DC1-E56B-4648-AD6D-FE8A166ECAD0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {1ADA3DC1-E56B-4648-AD6D-FE8A166ECAD0}.Debug|Any CPU.Build.0 = Debug|Any CPU - {1ADA3DC1-E56B-4648-AD6D-FE8A166ECAD0}.Release|Any CPU.ActiveCfg = Release|Any CPU - {1ADA3DC1-E56B-4648-AD6D-FE8A166ECAD0}.Release|Any CPU.Build.0 = Release|Any CPU - {F24BF4C8-5E7C-41FE-8E15-1318CEE2F136}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {F24BF4C8-5E7C-41FE-8E15-1318CEE2F136}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F24BF4C8-5E7C-41FE-8E15-1318CEE2F136}.Release|Any CPU.ActiveCfg = Release|Any CPU - {F24BF4C8-5E7C-41FE-8E15-1318CEE2F136}.Release|Any CPU.Build.0 = Release|Any CPU - {2673EBC9-E99C-4A3F-AEA1-72FF42DEAD0C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {2673EBC9-E99C-4A3F-AEA1-72FF42DEAD0C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {2673EBC9-E99C-4A3F-AEA1-72FF42DEAD0C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {2673EBC9-E99C-4A3F-AEA1-72FF42DEAD0C}.Release|Any CPU.Build.0 = Release|Any CPU - {2FB1EE8A-F07C-41F6-855C-031CA3346BFA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {2FB1EE8A-F07C-41F6-855C-031CA3346BFA}.Debug|Any CPU.Build.0 = Debug|Any CPU - {2FB1EE8A-F07C-41F6-855C-031CA3346BFA}.Release|Any CPU.ActiveCfg = Release|Any CPU - {2FB1EE8A-F07C-41F6-855C-031CA3346BFA}.Release|Any CPU.Build.0 = Release|Any CPU - {6238A269-B71B-444D-815C-2CDB340AEEE9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6238A269-B71B-444D-815C-2CDB340AEEE9}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6238A269-B71B-444D-815C-2CDB340AEEE9}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6238A269-B71B-444D-815C-2CDB340AEEE9}.Release|Any CPU.Build.0 = Release|Any CPU - {6E1E6F02-6930-41C2-B03A-2BE94F167F6F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6E1E6F02-6930-41C2-B03A-2BE94F167F6F}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6E1E6F02-6930-41C2-B03A-2BE94F167F6F}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6E1E6F02-6930-41C2-B03A-2BE94F167F6F}.Release|Any CPU.Build.0 = Release|Any CPU - {19A3D26D-9ECB-4C0A-AE1C-CE30A13A6A1A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {19A3D26D-9ECB-4C0A-AE1C-CE30A13A6A1A}.Debug|Any CPU.Build.0 = Debug|Any CPU - {19A3D26D-9ECB-4C0A-AE1C-CE30A13A6A1A}.Release|Any CPU.ActiveCfg = Release|Any CPU - {19A3D26D-9ECB-4C0A-AE1C-CE30A13A6A1A}.Release|Any CPU.Build.0 = Release|Any CPU - {4D1A89DA-D736-41B5-9AFD-8F30FE5DAA76}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {4D1A89DA-D736-41B5-9AFD-8F30FE5DAA76}.Debug|Any CPU.Build.0 = Debug|Any CPU - {4D1A89DA-D736-41B5-9AFD-8F30FE5DAA76}.Release|Any CPU.ActiveCfg = Release|Any CPU - {4D1A89DA-D736-41B5-9AFD-8F30FE5DAA76}.Release|Any CPU.Build.0 = Release|Any CPU - {6FEFA4A7-CF69-44CD-BD03-AC5C702B7BA0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6FEFA4A7-CF69-44CD-BD03-AC5C702B7BA0}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6FEFA4A7-CF69-44CD-BD03-AC5C702B7BA0}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6FEFA4A7-CF69-44CD-BD03-AC5C702B7BA0}.Release|Any CPU.Build.0 = Release|Any CPU - {97999608-B9AD-46B4-AF10-311B109A90BE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {97999608-B9AD-46B4-AF10-311B109A90BE}.Debug|Any CPU.Build.0 = Debug|Any CPU - {97999608-B9AD-46B4-AF10-311B109A90BE}.Release|Any CPU.ActiveCfg = Release|Any CPU - {97999608-B9AD-46B4-AF10-311B109A90BE}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(NestedProjects) = preSolution - {1CC73AD2-CFC9-4FE7-96C0-0E4FEFBB66F1} = {07500646-19CF-415A-A1E5-0CDFDFE76127} - {2C9B5E9D-900E-4D82-A576-106FE035CAE1} = {07500646-19CF-415A-A1E5-0CDFDFE76127} - {F295C81A-BE85-4121-A594-3ECD741DF9E5} = {1CC73AD2-CFC9-4FE7-96C0-0E4FEFBB66F1} - {B2A94C28-1A5C-4F75-851A-DFC4A5077FAA} = {1CC73AD2-CFC9-4FE7-96C0-0E4FEFBB66F1} - {AB6D5218-A3FE-410F-B729-E4CB2AA54C8F} = {1CC73AD2-CFC9-4FE7-96C0-0E4FEFBB66F1} - {E0873894-C1E6-4933-8519-052C9D53CD32} = {07500646-19CF-415A-A1E5-0CDFDFE76127} - {CC105757-549C-418F-B564-8C40111B9C57} = {07500646-19CF-415A-A1E5-0CDFDFE76127} - {5A1E21A9-1014-4E1B-B7A5-B9B77ECB7045} = {07500646-19CF-415A-A1E5-0CDFDFE76127} - {3751A4FF-ACEC-470F-ABF0-660338EBCF0F} = {5961A5E0-54A6-42F5-92A2-9A9E48DE2878} - {D165FEE4-4EA8-46FE-B5EC-9A3178CAC615} = {5961A5E0-54A6-42F5-92A2-9A9E48DE2878} - {D438CECE-FB91-4E2A-9182-D386222D8C92} = {5961A5E0-54A6-42F5-92A2-9A9E48DE2878} - {BB5FD6A0-0840-4381-AB68-AD61499368ED} = {5961A5E0-54A6-42F5-92A2-9A9E48DE2878} - {70B5742E-C249-4B51-985C-2B4B7BDAB489} = {BB5FD6A0-0840-4381-AB68-AD61499368ED} - {818F8CD0-5218-4480-A541-BD9D59416CDE} = {BB5FD6A0-0840-4381-AB68-AD61499368ED} - {9D8B6051-BE99-42E4-B569-43ABA3A9510D} = {BB5FD6A0-0840-4381-AB68-AD61499368ED} - {54DBC633-2A8D-4531-AA22-23824C6CFCD9} = {BB5FD6A0-0840-4381-AB68-AD61499368ED} - {0A4945C1-1089-4331-B9F4-2AB98BCB4D39} = {CA060C96-322D-4410-8D32-0AF5DA8A975C} - {6BF48DBC-42A7-412E-8894-39E61BA7EF8A} = {CA060C96-322D-4410-8D32-0AF5DA8A975C} - {ACD2C7B7-2227-4E25-88F8-8B45BCE89584} = {CA060C96-322D-4410-8D32-0AF5DA8A975C} - {2FF62DC2-6027-4F9F-A6A9-3DA46D2B88E2} = {CA060C96-322D-4410-8D32-0AF5DA8A975C} - {207E4FB5-2614-4E19-B593-C9F1254DF44D} = {ACD2C7B7-2227-4E25-88F8-8B45BCE89584} - {D000CB33-97FD-4074-946B-CED146812CCD} = {ACD2C7B7-2227-4E25-88F8-8B45BCE89584} - {1F36D46A-5D9C-42E5-BC17-44C07A4484B4} = {0A4945C1-1089-4331-B9F4-2AB98BCB4D39} - {A355D8E5-1BA2-4267-BEC5-0F21A8D41B45} = {0A4945C1-1089-4331-B9F4-2AB98BCB4D39} - {A0D762CD-19DF-4F35-B4B2-B2171168F00B} = {6BF48DBC-42A7-412E-8894-39E61BA7EF8A} - {1ADA3DC1-E56B-4648-AD6D-FE8A166ECAD0} = {2FF62DC2-6027-4F9F-A6A9-3DA46D2B88E2} - {F24BF4C8-5E7C-41FE-8E15-1318CEE2F136} = {2FF62DC2-6027-4F9F-A6A9-3DA46D2B88E2} - {2673EBC9-E99C-4A3F-AEA1-72FF42DEAD0C} = {6BF48DBC-42A7-412E-8894-39E61BA7EF8A} - {2FB1EE8A-F07C-41F6-855C-031CA3346BFA} = {BB5FD6A0-0840-4381-AB68-AD61499368ED} - {7705739E-5D69-4DF4-8C77-34AD3D991683} = {CA060C96-322D-4410-8D32-0AF5DA8A975C} - {6238A269-B71B-444D-815C-2CDB340AEEE9} = {7705739E-5D69-4DF4-8C77-34AD3D991683} - {6E1E6F02-6930-41C2-B03A-2BE94F167F6F} = {7705739E-5D69-4DF4-8C77-34AD3D991683} - {19A3D26D-9ECB-4C0A-AE1C-CE30A13A6A1A} = {BB5FD6A0-0840-4381-AB68-AD61499368ED} - {4D1A89DA-D736-41B5-9AFD-8F30FE5DAA76} = {1CC73AD2-CFC9-4FE7-96C0-0E4FEFBB66F1} - {016945AB-5C4D-42A1-81B9-8C12FC6E40E6} = {CA060C96-322D-4410-8D32-0AF5DA8A975C} - {6FEFA4A7-CF69-44CD-BD03-AC5C702B7BA0} = {016945AB-5C4D-42A1-81B9-8C12FC6E40E6} - {97999608-B9AD-46B4-AF10-311B109A90BE} = {016945AB-5C4D-42A1-81B9-8C12FC6E40E6} - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {2E9F4217-7A58-48A4-9850-84CD0CDA31DA} - EndGlobalSection -EndGlobal diff --git a/src/FluentCMS.slnx b/src/FluentCMS.slnx new file mode 100644 index 000000000..61ba11aef --- /dev/null +++ b/src/FluentCMS.slnx @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file From 22ab2f5a7a74a90576907159c376628185babd42 Mon Sep 17 00:00:00 2001 From: Raphael Kuster Date: Tue, 15 Oct 2024 00:08:53 +0200 Subject: [PATCH 2/4] feat(sln): upgraded to slnx --- src/FluentCMS.slnx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/FluentCMS.slnx b/src/FluentCMS.slnx index 61ba11aef..7c2887839 100644 --- a/src/FluentCMS.slnx +++ b/src/FluentCMS.slnx @@ -10,6 +10,7 @@ + @@ -49,6 +50,9 @@ + + + \ No newline at end of file From 7d4520e93ffab6d95180af7a897d8b3c48ddca27 Mon Sep 17 00:00:00 2001 From: Raphael Kuster Date: Tue, 15 Oct 2024 00:09:17 +0200 Subject: [PATCH 3/4] feat(docker): added postgres container to debug --- src/.dockerignore | 25 +++++++++++++++++++++++++ src/dev.docker-compose.yml | 17 +++++++++++++++++ 2 files changed, 42 insertions(+) create mode 100644 src/.dockerignore create mode 100644 src/dev.docker-compose.yml diff --git a/src/.dockerignore b/src/.dockerignore new file mode 100644 index 000000000..cd967fc3a --- /dev/null +++ b/src/.dockerignore @@ -0,0 +1,25 @@ +**/.dockerignore +**/.env +**/.git +**/.gitignore +**/.project +**/.settings +**/.toolstarget +**/.vs +**/.vscode +**/.idea +**/*.*proj.user +**/*.dbmdl +**/*.jfm +**/azds.yaml +**/bin +**/charts +**/docker-compose* +**/Dockerfile* +**/node_modules +**/npm-debug.log +**/obj +**/secrets.dev.yaml +**/values.dev.yaml +LICENSE +README.md \ No newline at end of file diff --git a/src/dev.docker-compose.yml b/src/dev.docker-compose.yml new file mode 100644 index 000000000..86f50731b --- /dev/null +++ b/src/dev.docker-compose.yml @@ -0,0 +1,17 @@ +version: '3.8' + +services: + fluentcms-db: + image: postgres:latest + container_name: fluentcms-db + environment: + POSTGRES_USER: fluentcms_user + POSTGRES_PASSWORD: fluentcms_password + POSTGRES_DB: fluentcms_db + volumes: + - fluentcms_db_data:/var/lib/postgresql/data + ports: + - "5432:5432" + +volumes: + fluentcms_db_data: From 9105c112bf1eb1bd8001155ac881c2c0bf9a6919 Mon Sep 17 00:00:00 2001 From: Raphael Kuster Date: Tue, 15 Oct 2024 00:09:41 +0200 Subject: [PATCH 4/4] feat(postgres): implemented --- .../.idea.FluentCMS/.idea/dataSources.xml | 13 + .../FluentCMS.Entities/GlobalSettings.cs | 4 +- .../FluentCMS.Entities/PluginDefinition.cs | 2 +- .../FluentCMS.Services/SetupService.cs | 3 + .../Configurations/ApiTokenConfiguration.cs | 8 + .../Base/AuditableEntityConfigurationBase.cs | 12 + .../Base/EntityConfigurationBase.cs | 12 + .../Base/ShadowKeyEntityBaseConfiguration.cs | 11 + .../SiteAssociatedEntityConfigurationBase.cs | 13 + .../Configurations/ContentConfiguration.cs | 13 + .../ContentTypeConfiguration.cs | 12 + .../ContentTypeFieldConfiguration.cs | 18 + .../Configurations/FileConfiguration.cs | 15 + .../Configurations/FolderConfiguration.cs | 16 + .../GlobalSettingsConfiguration.cs | 14 + .../PluginDefinitionConfiguration.cs | 8 + .../PluginDefinitionTypeConfiguration.cs | 13 + .../Configurations/PolicyConfiguration.cs | 13 + .../Configurations/SettingsConfiguration.cs | 13 + .../BlockConfiguration.cs | 8 + .../LayoutConfiguration.cs | 8 + .../PageConfiguration.cs | 8 + .../PermissionConfiguration.cs | 8 + .../PluginConfiguration.cs | 8 + .../PluginContentConfiguration.cs | 17 + .../RoleConfiguration.cs | 13 + .../SiteConfiguration.cs | 25 + .../UserRoleConfiguration.cs | 19 + .../IdentityUserConfiguration.cs | 9 + .../IdentityUserLoginConfiguration.cs | 9 + .../IdentityUserRoleConfiguration.cs | 9 + .../IdentityUserTokenConfiguration.cs | 9 + .../UserConfiguration.cs | 11 + .../UserTwoFactorRecoveryCodeConfiguration.cs | 8 + .../MainContextDesignTimeFactory.cs | 17 + .../Extensions/PostgresServiceExtensions.cs | 40 + .../FluentCMS.Repositories.Postgres.csproj | 52 + .../GlobalUsings.cs | 11 + .../20241014214640_Init.Designer.cs | 1415 +++++++++++++++++ .../Migrations/20241014214640_Init.cs | 899 +++++++++++ .../PostgresDbContextModelSnapshot.cs | 1412 ++++++++++++++++ .../PostgresDbContext.cs | 76 + .../FluentCMS.Repositories.Postgres/README.md | 3 + .../Repositories/ApiTokenRepository.cs | 16 + .../Base/AuditableEntityRepository.cs | 7 + .../Repositories/Base/EntityRepository.cs | 101 ++ .../Repositories/Base/IService.cs | 6 + .../Repositories/BlockRepository.cs | 5 + .../Repositories/ContentRepository.cs | 11 + .../Repositories/ContentTypeRepository.cs | 10 + .../Repositories/FileRepository.cs | 4 + .../Repositories/FolderRepository.cs | 3 + .../Repositories/GlobalSettingsRepository.cs | 25 + .../Repositories/LayoutRepository.cs | 3 + .../Repositories/PageRepository.cs | 3 + .../Repositories/PermissionRepository.cs | 27 + .../Repositories/PluginContentRepository.cs | 11 + .../PluginDefinitionRepository.cs | 4 + .../Repositories/PluginRepository.cs | 43 + .../Repositories/RoleRepository.cs | 5 + .../Repositories/SettingsRepository.cs | 33 + .../Repositories/SiteAssociatedRepository.cs | 23 + .../Repositories/SiteRepository.cs | 11 + .../Repositories/UserRepository.cs | 113 ++ .../Repositories/UserRoleRepository.cs | 22 + .../Workers/DatabaseMigrator.cs | 29 + .../add-migrations.ps1 | 37 + .../appsettings.json | 6 + src/FluentCMS/Dockerfile | 54 + src/FluentCMS/FluentCMS.csproj | 2 + src/FluentCMS/Program.cs | 7 +- src/FluentCMS/appsettings.json | 71 +- 72 files changed, 4960 insertions(+), 39 deletions(-) create mode 100644 src/.idea/.idea.FluentCMS/.idea/dataSources.xml create mode 100644 src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/ApiTokenConfiguration.cs create mode 100644 src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/Base/AuditableEntityConfigurationBase.cs create mode 100644 src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/Base/EntityConfigurationBase.cs create mode 100644 src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/Base/ShadowKeyEntityBaseConfiguration.cs create mode 100644 src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/Base/SiteAssociatedEntityConfigurationBase.cs create mode 100644 src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/ContentConfiguration.cs create mode 100644 src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/ContentTypeConfiguration.cs create mode 100644 src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/ContentTypeFieldConfiguration.cs create mode 100644 src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/FileConfiguration.cs create mode 100644 src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/FolderConfiguration.cs create mode 100644 src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/GlobalSettingsConfiguration.cs create mode 100644 src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/PluginDefinitionConfiguration.cs create mode 100644 src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/PluginDefinitionTypeConfiguration.cs create mode 100644 src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/PolicyConfiguration.cs create mode 100644 src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/SettingsConfiguration.cs create mode 100644 src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/SiteAssociatedEntities/BlockConfiguration.cs create mode 100644 src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/SiteAssociatedEntities/LayoutConfiguration.cs create mode 100644 src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/SiteAssociatedEntities/PageConfiguration.cs create mode 100644 src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/SiteAssociatedEntities/PermissionConfiguration.cs create mode 100644 src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/SiteAssociatedEntities/PluginConfiguration.cs create mode 100644 src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/SiteAssociatedEntities/PluginContentConfiguration.cs create mode 100644 src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/SiteAssociatedEntities/RoleConfiguration.cs create mode 100644 src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/SiteAssociatedEntities/SiteConfiguration.cs create mode 100644 src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/SiteAssociatedEntities/UserRoleConfiguration.cs create mode 100644 src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/UserAssociatedEntities/IdentityUserConfiguration.cs create mode 100644 src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/UserAssociatedEntities/IdentityUserLoginConfiguration.cs create mode 100644 src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/UserAssociatedEntities/IdentityUserRoleConfiguration.cs create mode 100644 src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/UserAssociatedEntities/IdentityUserTokenConfiguration.cs create mode 100644 src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/UserAssociatedEntities/UserConfiguration.cs create mode 100644 src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/UserAssociatedEntities/UserTwoFactorRecoveryCodeConfiguration.cs create mode 100644 src/Backend/Repositories/FluentCMS.Repositories.Postgres/Extensions/MainContextDesignTimeFactory.cs create mode 100644 src/Backend/Repositories/FluentCMS.Repositories.Postgres/Extensions/PostgresServiceExtensions.cs create mode 100644 src/Backend/Repositories/FluentCMS.Repositories.Postgres/FluentCMS.Repositories.Postgres.csproj create mode 100644 src/Backend/Repositories/FluentCMS.Repositories.Postgres/GlobalUsings.cs create mode 100644 src/Backend/Repositories/FluentCMS.Repositories.Postgres/Migrations/20241014214640_Init.Designer.cs create mode 100644 src/Backend/Repositories/FluentCMS.Repositories.Postgres/Migrations/20241014214640_Init.cs create mode 100644 src/Backend/Repositories/FluentCMS.Repositories.Postgres/Migrations/PostgresDbContextModelSnapshot.cs create mode 100644 src/Backend/Repositories/FluentCMS.Repositories.Postgres/PostgresDbContext.cs create mode 100644 src/Backend/Repositories/FluentCMS.Repositories.Postgres/README.md create mode 100644 src/Backend/Repositories/FluentCMS.Repositories.Postgres/Repositories/ApiTokenRepository.cs create mode 100644 src/Backend/Repositories/FluentCMS.Repositories.Postgres/Repositories/Base/AuditableEntityRepository.cs create mode 100644 src/Backend/Repositories/FluentCMS.Repositories.Postgres/Repositories/Base/EntityRepository.cs create mode 100644 src/Backend/Repositories/FluentCMS.Repositories.Postgres/Repositories/Base/IService.cs create mode 100644 src/Backend/Repositories/FluentCMS.Repositories.Postgres/Repositories/BlockRepository.cs create mode 100644 src/Backend/Repositories/FluentCMS.Repositories.Postgres/Repositories/ContentRepository.cs create mode 100644 src/Backend/Repositories/FluentCMS.Repositories.Postgres/Repositories/ContentTypeRepository.cs create mode 100644 src/Backend/Repositories/FluentCMS.Repositories.Postgres/Repositories/FileRepository.cs create mode 100644 src/Backend/Repositories/FluentCMS.Repositories.Postgres/Repositories/FolderRepository.cs create mode 100644 src/Backend/Repositories/FluentCMS.Repositories.Postgres/Repositories/GlobalSettingsRepository.cs create mode 100644 src/Backend/Repositories/FluentCMS.Repositories.Postgres/Repositories/LayoutRepository.cs create mode 100644 src/Backend/Repositories/FluentCMS.Repositories.Postgres/Repositories/PageRepository.cs create mode 100644 src/Backend/Repositories/FluentCMS.Repositories.Postgres/Repositories/PermissionRepository.cs create mode 100644 src/Backend/Repositories/FluentCMS.Repositories.Postgres/Repositories/PluginContentRepository.cs create mode 100644 src/Backend/Repositories/FluentCMS.Repositories.Postgres/Repositories/PluginDefinitionRepository.cs create mode 100644 src/Backend/Repositories/FluentCMS.Repositories.Postgres/Repositories/PluginRepository.cs create mode 100644 src/Backend/Repositories/FluentCMS.Repositories.Postgres/Repositories/RoleRepository.cs create mode 100644 src/Backend/Repositories/FluentCMS.Repositories.Postgres/Repositories/SettingsRepository.cs create mode 100644 src/Backend/Repositories/FluentCMS.Repositories.Postgres/Repositories/SiteAssociatedRepository.cs create mode 100644 src/Backend/Repositories/FluentCMS.Repositories.Postgres/Repositories/SiteRepository.cs create mode 100644 src/Backend/Repositories/FluentCMS.Repositories.Postgres/Repositories/UserRepository.cs create mode 100644 src/Backend/Repositories/FluentCMS.Repositories.Postgres/Repositories/UserRoleRepository.cs create mode 100644 src/Backend/Repositories/FluentCMS.Repositories.Postgres/Workers/DatabaseMigrator.cs create mode 100644 src/Backend/Repositories/FluentCMS.Repositories.Postgres/add-migrations.ps1 create mode 100644 src/Backend/Repositories/FluentCMS.Repositories.Postgres/appsettings.json create mode 100644 src/FluentCMS/Dockerfile diff --git a/src/.idea/.idea.FluentCMS/.idea/dataSources.xml b/src/.idea/.idea.FluentCMS/.idea/dataSources.xml new file mode 100644 index 000000000..945f32669 --- /dev/null +++ b/src/.idea/.idea.FluentCMS/.idea/dataSources.xml @@ -0,0 +1,13 @@ + + + + + postgresql + true + true + org.postgresql.Driver + jdbc:postgresql://localhost:5432/fluentcms_db?password=fluentcms_password&user=fluentcms_user + $ProjectFileDir$ + + + \ No newline at end of file diff --git a/src/Backend/FluentCMS.Entities/GlobalSettings.cs b/src/Backend/FluentCMS.Entities/GlobalSettings.cs index 548480bd7..db1f94997 100644 --- a/src/Backend/FluentCMS.Entities/GlobalSettings.cs +++ b/src/Backend/FluentCMS.Entities/GlobalSettings.cs @@ -2,8 +2,8 @@ public class GlobalSettings : AuditableEntity { - public FileUploadConfig FileUpload { get; set; } = default!; - public IEnumerable SuperAdmins { get; set; } = []; + public FileUploadConfig? FileUpload { get; set; } = default!; + public List SuperAdmins { get; set; } = []; public bool Initialized { get; set; } = false; } diff --git a/src/Backend/FluentCMS.Entities/PluginDefinition.cs b/src/Backend/FluentCMS.Entities/PluginDefinition.cs index e9de37a19..3f5a473af 100644 --- a/src/Backend/FluentCMS.Entities/PluginDefinition.cs +++ b/src/Backend/FluentCMS.Entities/PluginDefinition.cs @@ -3,7 +3,7 @@ public class PluginDefinition : AuditableEntity { public string Name { get; set; } = default!; - public string Category { get; set; } = default!; + public string? Category { get; set; } = default!; public string Assembly { get; set; } = default!; public string? Description { get; set; } public IEnumerable Types { get; set; } = []; diff --git a/src/Backend/FluentCMS.Services/SetupService.cs b/src/Backend/FluentCMS.Services/SetupService.cs index 511cb33fd..2b39bd0fa 100644 --- a/src/Backend/FluentCMS.Services/SetupService.cs +++ b/src/Backend/FluentCMS.Services/SetupService.cs @@ -70,5 +70,8 @@ private static void SetIds(SetupTemplate setupTemplate) foreach (var contentType in setupTemplate.ContentTypes) contentType.Id = Guid.NewGuid(); + + foreach (var layout in setupTemplate.Site.Layouts) + layout.Id = Guid.NewGuid(); } } diff --git a/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/ApiTokenConfiguration.cs b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/ApiTokenConfiguration.cs new file mode 100644 index 000000000..23c2c15fc --- /dev/null +++ b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/ApiTokenConfiguration.cs @@ -0,0 +1,8 @@ +using FluentCMS.Repositories.Postgres.Configurations.Base; + +namespace FluentCMS.Repositories.Postgres.Configurations; + +public class ApiTokenConfiguration : AuditableEntityConfigurationBase +{ + +} diff --git a/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/Base/AuditableEntityConfigurationBase.cs b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/Base/AuditableEntityConfigurationBase.cs new file mode 100644 index 000000000..002bb552d --- /dev/null +++ b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/Base/AuditableEntityConfigurationBase.cs @@ -0,0 +1,12 @@ +namespace FluentCMS.Repositories.Postgres.Configurations.Base; + +public class AuditableEntityConfigurationBase : EntityConfigurationBase where T : AuditableEntity +{ + public override void Configure(EntityTypeBuilder entity) + { + base.Configure(entity); + + entity.Property(x => x.CreatedAt).HasColumnType("timestamp with time zone"); + entity.Property(x => x.ModifiedAt).HasColumnType("timestamp with time zone"); + } +} diff --git a/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/Base/EntityConfigurationBase.cs b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/Base/EntityConfigurationBase.cs new file mode 100644 index 000000000..4ed331673 --- /dev/null +++ b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/Base/EntityConfigurationBase.cs @@ -0,0 +1,12 @@ +namespace FluentCMS.Repositories.Postgres.Configurations.Base; + +public class EntityConfigurationBase : IEntityTypeConfiguration where T : Entity +{ + public virtual void Configure(EntityTypeBuilder builder) + { + builder.HasKey(x => x.Id); + } + + +} + diff --git a/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/Base/ShadowKeyEntityBaseConfiguration.cs b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/Base/ShadowKeyEntityBaseConfiguration.cs new file mode 100644 index 000000000..8b87978a8 --- /dev/null +++ b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/Base/ShadowKeyEntityBaseConfiguration.cs @@ -0,0 +1,11 @@ +namespace FluentCMS.Repositories.Postgres.Configurations.Base; + +public class ShadowKeyEntityBaseConfiguration : IEntityTypeConfiguration where T : class +{ + public virtual void Configure(EntityTypeBuilder builder) + { + builder.Property("Id").ValueGeneratedOnAdd(); + + builder.HasKey("Id"); + } +} diff --git a/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/Base/SiteAssociatedEntityConfigurationBase.cs b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/Base/SiteAssociatedEntityConfigurationBase.cs new file mode 100644 index 000000000..61ee45081 --- /dev/null +++ b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/Base/SiteAssociatedEntityConfigurationBase.cs @@ -0,0 +1,13 @@ +namespace FluentCMS.Repositories.Postgres.Configurations.Base; + +public class SiteAssociatedEntityConfigurationBase : AuditableEntityConfigurationBase where T : SiteAssociatedEntity +{ + public override void Configure(EntityTypeBuilder entity) + { + base.Configure(entity); + + entity.HasOne() + .WithMany() + .HasForeignKey(x => x.SiteId); + } +} diff --git a/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/ContentConfiguration.cs b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/ContentConfiguration.cs new file mode 100644 index 000000000..7b5a32ed2 --- /dev/null +++ b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/ContentConfiguration.cs @@ -0,0 +1,13 @@ +using FluentCMS.Repositories.Postgres.Configurations.Base; + +namespace FluentCMS.Repositories.Postgres.Configurations; + +public class ContentConfiguration : AuditableEntityConfigurationBase +{ + public override void Configure(EntityTypeBuilder entity) + { + base.Configure(entity); + + entity.OwnsOne(x => x.Data, builder => {builder.ToJson(); }); + } +} diff --git a/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/ContentTypeConfiguration.cs b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/ContentTypeConfiguration.cs new file mode 100644 index 000000000..e6baef53e --- /dev/null +++ b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/ContentTypeConfiguration.cs @@ -0,0 +1,12 @@ +using FluentCMS.Repositories.Postgres.Configurations.Base; + +namespace FluentCMS.Repositories.Postgres.Configurations; + +public class ContentTypeConfiguration : AuditableEntityConfigurationBase +{ + public override void Configure(EntityTypeBuilder entity) + { + base.Configure(entity); + + } +} diff --git a/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/ContentTypeFieldConfiguration.cs b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/ContentTypeFieldConfiguration.cs new file mode 100644 index 000000000..5cff8aaa0 --- /dev/null +++ b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/ContentTypeFieldConfiguration.cs @@ -0,0 +1,18 @@ +using FluentCMS.Repositories.Postgres.Configurations.Base; + +namespace FluentCMS.Repositories.Postgres.Configurations; + +public class ContentTypeFieldConfiguration : ShadowKeyEntityBaseConfiguration +{ + public override void Configure(EntityTypeBuilder entity) + { + base.Configure(entity); + + entity.Property(x => x.Settings).HasColumnType("jsonb"); + + entity.HasOne() + .WithMany() + .HasForeignKey("TypeId"); + + } +} diff --git a/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/FileConfiguration.cs b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/FileConfiguration.cs new file mode 100644 index 000000000..8a0c378b7 --- /dev/null +++ b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/FileConfiguration.cs @@ -0,0 +1,15 @@ +using FluentCMS.Repositories.Postgres.Configurations.Base; + +namespace FluentCMS.Repositories.Postgres.Configurations; + +public class FileConfiguration : AuditableEntityConfigurationBase +{ + public override void Configure(EntityTypeBuilder entity) + { + base.Configure(entity); + + entity.HasOne() + .WithMany() + .HasForeignKey(x => x.FolderId); + } +} diff --git a/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/FolderConfiguration.cs b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/FolderConfiguration.cs new file mode 100644 index 000000000..801485b2c --- /dev/null +++ b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/FolderConfiguration.cs @@ -0,0 +1,16 @@ +using FluentCMS.Repositories.Postgres.Configurations.Base; + +namespace FluentCMS.Repositories.Postgres.Configurations; + +public class FolderConfiguration : AuditableEntityConfigurationBase +{ + public override void Configure(EntityTypeBuilder entity) + { + base.Configure(entity); + + entity.HasOne() + .WithMany() + .HasForeignKey(x => x.FolderId); + + } +} diff --git a/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/GlobalSettingsConfiguration.cs b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/GlobalSettingsConfiguration.cs new file mode 100644 index 000000000..cdb63a175 --- /dev/null +++ b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/GlobalSettingsConfiguration.cs @@ -0,0 +1,14 @@ +using FluentCMS.Repositories.Postgres.Configurations.Base; + +namespace FluentCMS.Repositories.Postgres.Configurations; + +public class GlobalSettingsConfiguration : AuditableEntityConfigurationBase +{ + public override void Configure(EntityTypeBuilder entity) + { + base.Configure(entity); + + entity.OwnsOne(x => x.FileUpload, builder => { builder.ToJson(); }); + + } +} diff --git a/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/PluginDefinitionConfiguration.cs b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/PluginDefinitionConfiguration.cs new file mode 100644 index 000000000..3e19e516e --- /dev/null +++ b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/PluginDefinitionConfiguration.cs @@ -0,0 +1,8 @@ +using FluentCMS.Repositories.Postgres.Configurations.Base; + +namespace FluentCMS.Repositories.Postgres.Configurations; + +public class PluginDefinitionConfiguration : AuditableEntityConfigurationBase +{ + +} diff --git a/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/PluginDefinitionTypeConfiguration.cs b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/PluginDefinitionTypeConfiguration.cs new file mode 100644 index 000000000..aea38ab8a --- /dev/null +++ b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/PluginDefinitionTypeConfiguration.cs @@ -0,0 +1,13 @@ +namespace FluentCMS.Repositories.Postgres.Configurations; + +public class PluginDefinitionTypeConfiguration : IEntityTypeConfiguration +{ + public void Configure(EntityTypeBuilder builder) + { + builder.HasKey(x => new{x.Type, x.Name}); + + builder.HasOne() + .WithMany() + .HasForeignKey("DefinitionId"); + } +} diff --git a/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/PolicyConfiguration.cs b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/PolicyConfiguration.cs new file mode 100644 index 000000000..e9c61bb44 --- /dev/null +++ b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/PolicyConfiguration.cs @@ -0,0 +1,13 @@ +using FluentCMS.Repositories.Postgres.Configurations.Base; + +namespace FluentCMS.Repositories.Postgres.Configurations; + +public class PolicyConfiguration : ShadowKeyEntityBaseConfiguration +{ + public override void Configure(EntityTypeBuilder entity) + { + base.Configure(entity); + + entity.OwnsOne(x => x.Actions, builder => { builder.ToJson(); }); + } +} diff --git a/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/SettingsConfiguration.cs b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/SettingsConfiguration.cs new file mode 100644 index 000000000..dd1bb191a --- /dev/null +++ b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/SettingsConfiguration.cs @@ -0,0 +1,13 @@ +using FluentCMS.Repositories.Postgres.Configurations.Base; + +namespace FluentCMS.Repositories.Postgres.Configurations; + +public class SettingsConfiguration : AuditableEntityConfigurationBase +{ + public override void Configure(EntityTypeBuilder entity) + { + base.Configure(entity); + + entity.OwnsOne(x => x.Values, builder => { builder.ToJson(); }); + } +} diff --git a/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/SiteAssociatedEntities/BlockConfiguration.cs b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/SiteAssociatedEntities/BlockConfiguration.cs new file mode 100644 index 000000000..53243b520 --- /dev/null +++ b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/SiteAssociatedEntities/BlockConfiguration.cs @@ -0,0 +1,8 @@ +using FluentCMS.Repositories.Postgres.Configurations.Base; + +namespace FluentCMS.Repositories.Postgres.Configurations.SiteAssociatedEntities; + +public class BlockConfiguration : SiteAssociatedEntityConfigurationBase +{ + +} diff --git a/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/SiteAssociatedEntities/LayoutConfiguration.cs b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/SiteAssociatedEntities/LayoutConfiguration.cs new file mode 100644 index 000000000..545b19222 --- /dev/null +++ b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/SiteAssociatedEntities/LayoutConfiguration.cs @@ -0,0 +1,8 @@ +using FluentCMS.Repositories.Postgres.Configurations.Base; + +namespace FluentCMS.Repositories.Postgres.Configurations.SiteAssociatedEntities; + +public class LayoutConfiguration : SiteAssociatedEntityConfigurationBase +{ + +} diff --git a/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/SiteAssociatedEntities/PageConfiguration.cs b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/SiteAssociatedEntities/PageConfiguration.cs new file mode 100644 index 000000000..750c1aee3 --- /dev/null +++ b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/SiteAssociatedEntities/PageConfiguration.cs @@ -0,0 +1,8 @@ +using FluentCMS.Repositories.Postgres.Configurations.Base; + +namespace FluentCMS.Repositories.Postgres.Configurations.SiteAssociatedEntities; + +public class PageConfiguration : SiteAssociatedEntityConfigurationBase +{ + +} diff --git a/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/SiteAssociatedEntities/PermissionConfiguration.cs b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/SiteAssociatedEntities/PermissionConfiguration.cs new file mode 100644 index 000000000..eb7614aa5 --- /dev/null +++ b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/SiteAssociatedEntities/PermissionConfiguration.cs @@ -0,0 +1,8 @@ +using FluentCMS.Repositories.Postgres.Configurations.Base; + +namespace FluentCMS.Repositories.Postgres.Configurations.SiteAssociatedEntities; + +public class PermissionConfiguration : SiteAssociatedEntityConfigurationBase +{ + +} diff --git a/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/SiteAssociatedEntities/PluginConfiguration.cs b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/SiteAssociatedEntities/PluginConfiguration.cs new file mode 100644 index 000000000..13772e511 --- /dev/null +++ b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/SiteAssociatedEntities/PluginConfiguration.cs @@ -0,0 +1,8 @@ +using FluentCMS.Repositories.Postgres.Configurations.Base; + +namespace FluentCMS.Repositories.Postgres.Configurations.SiteAssociatedEntities; + +public class PluginConfiguration : SiteAssociatedEntityConfigurationBase +{ + +} diff --git a/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/SiteAssociatedEntities/PluginContentConfiguration.cs b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/SiteAssociatedEntities/PluginContentConfiguration.cs new file mode 100644 index 000000000..4af8a58cf --- /dev/null +++ b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/SiteAssociatedEntities/PluginContentConfiguration.cs @@ -0,0 +1,17 @@ +using FluentCMS.Repositories.Postgres.Configurations.Base; + +namespace FluentCMS.Repositories.Postgres.Configurations.SiteAssociatedEntities; + +public class PluginContentConfiguration : SiteAssociatedEntityConfigurationBase +{ + public override void Configure(EntityTypeBuilder entity) + { + base.Configure(entity); + + entity.HasOne() + .WithMany() + .HasForeignKey(x => x.PluginId); + + entity.OwnsOne(x => x.Data, builder => builder.ToJson()); + } +} diff --git a/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/SiteAssociatedEntities/RoleConfiguration.cs b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/SiteAssociatedEntities/RoleConfiguration.cs new file mode 100644 index 000000000..10946abed --- /dev/null +++ b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/SiteAssociatedEntities/RoleConfiguration.cs @@ -0,0 +1,13 @@ +using FluentCMS.Repositories.Postgres.Configurations.Base; + +namespace FluentCMS.Repositories.Postgres.Configurations.SiteAssociatedEntities; + +public class RoleConfiguration : SiteAssociatedEntityConfigurationBase +{ + public override void Configure(EntityTypeBuilder entity) + { + base.Configure(entity); + + entity.Property(x => x.Type).HasConversion(); + } +} diff --git a/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/SiteAssociatedEntities/SiteConfiguration.cs b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/SiteAssociatedEntities/SiteConfiguration.cs new file mode 100644 index 000000000..97432a38f --- /dev/null +++ b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/SiteAssociatedEntities/SiteConfiguration.cs @@ -0,0 +1,25 @@ +using FluentCMS.Repositories.Postgres.Configurations.Base; + +namespace FluentCMS.Repositories.Postgres.Configurations.SiteAssociatedEntities; + +public class SiteConfiguration : AuditableEntityConfigurationBase +{ + public override void Configure(EntityTypeBuilder entity) + { + base.Configure(entity); + + entity.OwnsOne(x => x.Urls, builder => builder.ToJson()); + + entity.HasOne() + .WithMany() + .HasForeignKey(x => x.LayoutId); + + entity.HasOne() + .WithMany() + .HasForeignKey(x => x.DetailLayoutId); + + entity.HasOne() + .WithMany() + .HasForeignKey(x => x.EditLayoutId); + } +} diff --git a/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/SiteAssociatedEntities/UserRoleConfiguration.cs b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/SiteAssociatedEntities/UserRoleConfiguration.cs new file mode 100644 index 000000000..521a587a6 --- /dev/null +++ b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/SiteAssociatedEntities/UserRoleConfiguration.cs @@ -0,0 +1,19 @@ +using FluentCMS.Repositories.Postgres.Configurations.Base; + +namespace FluentCMS.Repositories.Postgres.Configurations.SiteAssociatedEntities; + +public class UserRoleConfiguration : SiteAssociatedEntityConfigurationBase +{ + public override void Configure(EntityTypeBuilder entity) + { + base.Configure(entity); + + entity.HasOne() + .WithMany() + .HasForeignKey(x => x.UserId); + + entity.HasOne() + .WithMany() + .HasForeignKey(x => x.RoleId); + } +} diff --git a/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/UserAssociatedEntities/IdentityUserConfiguration.cs b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/UserAssociatedEntities/IdentityUserConfiguration.cs new file mode 100644 index 000000000..79960b501 --- /dev/null +++ b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/UserAssociatedEntities/IdentityUserConfiguration.cs @@ -0,0 +1,9 @@ +using FluentCMS.Repositories.Postgres.Configurations.Base; +using Microsoft.AspNetCore.Identity; + +namespace FluentCMS.Repositories.Postgres.Configurations.UserAssociatedEntities; + +public class IdentityUserConfiguration : ShadowKeyEntityBaseConfiguration> +{ + +} diff --git a/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/UserAssociatedEntities/IdentityUserLoginConfiguration.cs b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/UserAssociatedEntities/IdentityUserLoginConfiguration.cs new file mode 100644 index 000000000..13869d81a --- /dev/null +++ b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/UserAssociatedEntities/IdentityUserLoginConfiguration.cs @@ -0,0 +1,9 @@ +using FluentCMS.Repositories.Postgres.Configurations.Base; +using Microsoft.AspNetCore.Identity; + +namespace FluentCMS.Repositories.Postgres.Configurations.UserAssociatedEntities; + +public class IdentityUserLoginConfiguration : ShadowKeyEntityBaseConfiguration> +{ + +} diff --git a/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/UserAssociatedEntities/IdentityUserRoleConfiguration.cs b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/UserAssociatedEntities/IdentityUserRoleConfiguration.cs new file mode 100644 index 000000000..f6d5447c6 --- /dev/null +++ b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/UserAssociatedEntities/IdentityUserRoleConfiguration.cs @@ -0,0 +1,9 @@ +using FluentCMS.Repositories.Postgres.Configurations.Base; +using Microsoft.AspNetCore.Identity; + +namespace FluentCMS.Repositories.Postgres.Configurations.UserAssociatedEntities; + +public class IdentityUserRoleConfiguration : ShadowKeyEntityBaseConfiguration> +{ + +} diff --git a/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/UserAssociatedEntities/IdentityUserTokenConfiguration.cs b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/UserAssociatedEntities/IdentityUserTokenConfiguration.cs new file mode 100644 index 000000000..d41689883 --- /dev/null +++ b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/UserAssociatedEntities/IdentityUserTokenConfiguration.cs @@ -0,0 +1,9 @@ +using FluentCMS.Repositories.Postgres.Configurations.Base; +using Microsoft.AspNetCore.Identity; + +namespace FluentCMS.Repositories.Postgres.Configurations.UserAssociatedEntities; + +public class IdentityUserTokenConfiguration : ShadowKeyEntityBaseConfiguration> +{ + +} diff --git a/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/UserAssociatedEntities/UserConfiguration.cs b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/UserAssociatedEntities/UserConfiguration.cs new file mode 100644 index 000000000..dc0b33d76 --- /dev/null +++ b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/UserAssociatedEntities/UserConfiguration.cs @@ -0,0 +1,11 @@ +namespace FluentCMS.Repositories.Postgres.Configurations.UserAssociatedEntities; + +public class UserConfiguration : IEntityTypeConfiguration +{ + public void Configure(EntityTypeBuilder builder) + { + + builder.HasMany(x => x.RecoveryCodes) + .WithOne(); + } +} diff --git a/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/UserAssociatedEntities/UserTwoFactorRecoveryCodeConfiguration.cs b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/UserAssociatedEntities/UserTwoFactorRecoveryCodeConfiguration.cs new file mode 100644 index 000000000..bc6313889 --- /dev/null +++ b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Configurations/UserAssociatedEntities/UserTwoFactorRecoveryCodeConfiguration.cs @@ -0,0 +1,8 @@ +using FluentCMS.Repositories.Postgres.Configurations.Base; + +namespace FluentCMS.Repositories.Postgres.Configurations.UserAssociatedEntities; + +public class UserTwoFactorRecoveryCodeConfiguration : ShadowKeyEntityBaseConfiguration +{ + +} diff --git a/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Extensions/MainContextDesignTimeFactory.cs b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Extensions/MainContextDesignTimeFactory.cs new file mode 100644 index 000000000..b1de09e7d --- /dev/null +++ b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Extensions/MainContextDesignTimeFactory.cs @@ -0,0 +1,17 @@ +using FluentCMS.Web.Api; +using Microsoft.AspNetCore.Http; +using Microsoft.EntityFrameworkCore.Design; + +namespace FluentCMS.Repositories.Postgres.Extensions; + +public class MainContextDesignTimeFactory : IDesignTimeDbContextFactory +{ + public PostgresDbContext CreateDbContext(string[] args) + { + + var optionsBuilder = new DbContextOptionsBuilder(); + optionsBuilder.UseNpgsql("Host=localhost;Database=fluentcms;Username=postgres;Password=postgres"); + + return new(optionsBuilder.Options, new ApiExecutionContext(new HttpContextAccessor())); + } +} diff --git a/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Extensions/PostgresServiceExtensions.cs b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Extensions/PostgresServiceExtensions.cs new file mode 100644 index 000000000..4beba0121 --- /dev/null +++ b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Extensions/PostgresServiceExtensions.cs @@ -0,0 +1,40 @@ +using FluentCMS.Repositories.Postgres.Repositories; +using FluentCMS.Repositories.Postgres.Workers; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Npgsql; + +namespace FluentCMS.Repositories.Postgres.Extensions; + +public static class PostgresServiceExtensions +{ + public static IServiceCollection AddPostgresDbRepositories(this IServiceCollection services, string connectionStringName) + { + services.AddDbContext((provider, optionsBuilder) => + { + var configuration = provider.GetService() ?? throw new InvalidOperationException("IConfiguration is not registered."); + var connectionString = configuration.GetConnectionString(connectionStringName); + + var dataSourceBuilder = new NpgsqlDataSourceBuilder(connectionString); + dataSourceBuilder.EnableDynamicJson(); + + + optionsBuilder.UseNpgsql(dataSourceBuilder.Build()); + }); + + + + // Register repositories + services.Scan(scan => scan + .FromAssembliesOf(typeof(PostgresDbContext)) + .AddClasses(classes => classes.AssignableTo(typeof(IService))) + .AsImplementedInterfaces() + .WithTransientLifetime()); + + services.AddHostedService(); + + return services; + } + + +} diff --git a/src/Backend/Repositories/FluentCMS.Repositories.Postgres/FluentCMS.Repositories.Postgres.csproj b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/FluentCMS.Repositories.Postgres.csproj new file mode 100644 index 000000000..88e37058b --- /dev/null +++ b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/FluentCMS.Repositories.Postgres.csproj @@ -0,0 +1,52 @@ + + + + net8.0 + enable + enable + + + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + + + + + + + + + + + + + + + + + C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App\8.0.10\Microsoft.Extensions.Configuration.dll + + + + + + + + diff --git a/src/Backend/Repositories/FluentCMS.Repositories.Postgres/GlobalUsings.cs b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/GlobalUsings.cs new file mode 100644 index 000000000..6df8eadcb --- /dev/null +++ b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/GlobalUsings.cs @@ -0,0 +1,11 @@ +global using Microsoft.EntityFrameworkCore; +global using FluentCMS.Entities; +global using FluentCMS.Repositories.Abstractions; +global using System; +global using System.Collections.Generic; +global using System.Linq; +global using System.Threading; +global using System.Threading.Tasks; +global using FluentCMS.Repositories.Postgres.Repositories.Base; +global using Microsoft.EntityFrameworkCore.Metadata.Builders; +global using File = FluentCMS.Entities.File; diff --git a/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Migrations/20241014214640_Init.Designer.cs b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Migrations/20241014214640_Init.Designer.cs new file mode 100644 index 000000000..05918cb66 --- /dev/null +++ b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Migrations/20241014214640_Init.Designer.cs @@ -0,0 +1,1415 @@ +// +using System; +using System.Collections.Generic; +using FluentCMS.Repositories.Postgres; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace FluentCMS.Repositories.Postgres.Migrations +{ + [DbContext(typeof(PostgresDbContext))] + [Migration("20241014214640_Init")] + partial class Init + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.10") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("FluentCMS.Entities.ApiToken", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("text"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("Enabled") + .HasColumnType("boolean"); + + b.Property("ExpireAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Key") + .IsRequired() + .HasColumnType("text"); + + b.Property("ModifiedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ModifiedBy") + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Secret") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("ApiTokens"); + }); + + modelBuilder.Entity("FluentCMS.Entities.Block", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Category") + .IsRequired() + .HasColumnType("text"); + + b.Property("Content") + .IsRequired() + .HasColumnType("text"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("text"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("ModifiedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ModifiedBy") + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("SiteId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("SiteId"); + + b.ToTable("Blocks"); + }); + + modelBuilder.Entity("FluentCMS.Entities.Content", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("text"); + + b.Property("ModifiedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ModifiedBy") + .HasColumnType("text"); + + b.Property("TypeId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.ToTable("Contents"); + }); + + modelBuilder.Entity("FluentCMS.Entities.ContentType", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("text"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("ModifiedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ModifiedBy") + .HasColumnType("text"); + + b.Property("Slug") + .IsRequired() + .HasColumnType("text"); + + b.Property("Title") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("ContentTypes"); + }); + + modelBuilder.Entity("FluentCMS.Entities.ContentTypeField", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ContentTypeId") + .HasColumnType("uuid"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("Label") + .IsRequired() + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Required") + .HasColumnType("boolean"); + + b.Property>("Settings") + .HasColumnType("jsonb"); + + b.Property("Type") + .IsRequired() + .HasColumnType("text"); + + b.Property("TypeId") + .HasColumnType("uuid"); + + b.Property("Unique") + .HasColumnType("boolean"); + + b.HasKey("Id"); + + b.HasIndex("ContentTypeId"); + + b.HasIndex("TypeId"); + + b.ToTable("ContentTypeFields"); + }); + + modelBuilder.Entity("FluentCMS.Entities.File", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ContentType") + .IsRequired() + .HasColumnType("text"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("text"); + + b.Property("Extension") + .IsRequired() + .HasColumnType("text"); + + b.Property("FolderId") + .HasColumnType("uuid"); + + b.Property("ModifiedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ModifiedBy") + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Size") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("FolderId"); + + b.ToTable("Files"); + }); + + modelBuilder.Entity("FluentCMS.Entities.Folder", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("text"); + + b.Property("FolderId") + .HasColumnType("uuid"); + + b.Property("ModifiedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ModifiedBy") + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("FolderId"); + + b.ToTable("Folders"); + }); + + modelBuilder.Entity("FluentCMS.Entities.GlobalSettings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("text"); + + b.Property("Initialized") + .HasColumnType("boolean"); + + b.Property("ModifiedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ModifiedBy") + .HasColumnType("text"); + + b.Property>("SuperAdmins") + .IsRequired() + .HasColumnType("text[]"); + + b.HasKey("Id"); + + b.ToTable("GlobalSettings"); + }); + + modelBuilder.Entity("FluentCMS.Entities.Layout", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Body") + .IsRequired() + .HasColumnType("text"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("text"); + + b.Property("Head") + .IsRequired() + .HasColumnType("text"); + + b.Property("ModifiedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ModifiedBy") + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("SiteId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("SiteId"); + + b.ToTable("Layouts"); + }); + + modelBuilder.Entity("FluentCMS.Entities.Page", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("text"); + + b.Property("DetailLayoutId") + .HasColumnType("uuid"); + + b.Property("EditLayoutId") + .HasColumnType("uuid"); + + b.Property("LayoutId") + .HasColumnType("uuid"); + + b.Property("Locked") + .HasColumnType("boolean"); + + b.Property("ModifiedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ModifiedBy") + .HasColumnType("text"); + + b.Property("Order") + .HasColumnType("integer"); + + b.Property("ParentId") + .HasColumnType("uuid"); + + b.Property("Path") + .IsRequired() + .HasColumnType("text"); + + b.Property("SiteId") + .HasColumnType("uuid"); + + b.Property("Title") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("SiteId"); + + b.ToTable("Pages"); + }); + + modelBuilder.Entity("FluentCMS.Entities.Permission", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Action") + .IsRequired() + .HasColumnType("text"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("text"); + + b.Property("EntityId") + .HasColumnType("uuid"); + + b.Property("EntityType") + .IsRequired() + .HasColumnType("text"); + + b.Property("ModifiedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ModifiedBy") + .HasColumnType("text"); + + b.Property("RoleId") + .HasColumnType("uuid"); + + b.Property("SiteId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("SiteId"); + + b.ToTable("Permissions"); + }); + + modelBuilder.Entity("FluentCMS.Entities.Plugin", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Cols") + .HasColumnType("integer"); + + b.Property("ColsLg") + .HasColumnType("integer"); + + b.Property("ColsMd") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("text"); + + b.Property("DefinitionId") + .HasColumnType("uuid"); + + b.Property("Locked") + .HasColumnType("boolean"); + + b.Property("ModifiedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ModifiedBy") + .HasColumnType("text"); + + b.Property("Order") + .HasColumnType("integer"); + + b.Property("PageId") + .HasColumnType("uuid"); + + b.Property("Section") + .IsRequired() + .HasColumnType("text"); + + b.Property("SiteId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("SiteId"); + + b.ToTable("Plugin"); + }); + + modelBuilder.Entity("FluentCMS.Entities.PluginContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("text"); + + b.Property("ModifiedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ModifiedBy") + .HasColumnType("text"); + + b.Property("PluginId") + .HasColumnType("uuid"); + + b.Property("SiteId") + .HasColumnType("uuid"); + + b.Property("Type") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("PluginId"); + + b.HasIndex("SiteId"); + + b.ToTable("PluginContents"); + }); + + modelBuilder.Entity("FluentCMS.Entities.PluginDefinition", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Assembly") + .IsRequired() + .HasColumnType("text"); + + b.Property("Category") + .HasColumnType("text"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("text"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("Locked") + .HasColumnType("boolean"); + + b.Property("ModifiedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ModifiedBy") + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("PluginDefinitions"); + }); + + modelBuilder.Entity("FluentCMS.Entities.PluginDefinitionType", b => + { + b.Property("Type") + .HasColumnType("text"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("DefinitionId") + .HasColumnType("uuid"); + + b.Property("IsDefault") + .HasColumnType("boolean"); + + b.Property("PluginDefinitionId") + .HasColumnType("uuid"); + + b.HasKey("Type", "Name"); + + b.HasIndex("DefinitionId"); + + b.HasIndex("PluginDefinitionId"); + + b.ToTable("PluginDefinitionType"); + }); + + modelBuilder.Entity("FluentCMS.Entities.Policy", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ApiTokenId") + .HasColumnType("uuid"); + + b.Property("Area") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("ApiTokenId"); + + b.ToTable("Policy"); + }); + + modelBuilder.Entity("FluentCMS.Entities.Role", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("text"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("ModifiedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ModifiedBy") + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("SiteId") + .HasColumnType("uuid"); + + b.Property("Type") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("SiteId"); + + b.ToTable("Role"); + }); + + modelBuilder.Entity("FluentCMS.Entities.Settings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("text"); + + b.Property("ModifiedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ModifiedBy") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("Settings"); + }); + + modelBuilder.Entity("FluentCMS.Entities.Site", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("text"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("DetailLayoutId") + .HasColumnType("uuid"); + + b.Property("EditLayoutId") + .HasColumnType("uuid"); + + b.Property("LayoutId") + .HasColumnType("uuid"); + + b.Property("ModifiedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ModifiedBy") + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("DetailLayoutId"); + + b.HasIndex("EditLayoutId"); + + b.HasIndex("LayoutId"); + + b.ToTable("Sites"); + }); + + modelBuilder.Entity("FluentCMS.Entities.UserRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("text"); + + b.Property("ModifiedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ModifiedBy") + .HasColumnType("text"); + + b.Property("RoleId") + .HasColumnType("uuid"); + + b.Property("SiteId") + .HasColumnType("uuid"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.HasIndex("SiteId"); + + b.HasIndex("UserId"); + + b.ToTable("UserRole"); + }); + + modelBuilder.Entity("FluentCMS.Entities.UserTwoFactorRecoveryCode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Code") + .IsRequired() + .HasColumnType("text"); + + b.Property("Redeemed") + .HasColumnType("boolean"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserTwoFactorRecoveryCode"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .HasColumnType("text"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("NormalizedName") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("Roles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("text"); + + b.Property("ClaimValue") + .HasColumnType("text"); + + b.Property("RoleId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.ToTable("RoleClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AccessFailedCount") + .HasColumnType("integer"); + + b.Property("ConcurrencyStamp") + .HasColumnType("text"); + + b.Property("Discriminator") + .IsRequired() + .HasMaxLength(21) + .HasColumnType("character varying(21)"); + + b.Property("Email") + .HasColumnType("text"); + + b.Property("EmailConfirmed") + .HasColumnType("boolean"); + + b.Property("LockoutEnabled") + .HasColumnType("boolean"); + + b.Property("LockoutEnd") + .HasColumnType("timestamp with time zone"); + + b.Property("NormalizedEmail") + .HasColumnType("text"); + + b.Property("NormalizedUserName") + .HasColumnType("text"); + + b.Property("PasswordHash") + .HasColumnType("text"); + + b.Property("PhoneNumber") + .HasColumnType("text"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("boolean"); + + b.Property("SecurityStamp") + .HasColumnType("text"); + + b.Property("TwoFactorEnabled") + .HasColumnType("boolean"); + + b.Property("UserName") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("IdentityUser"); + + b.HasDiscriminator().HasValue("IdentityUser"); + + b.UseTphMappingStrategy(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("text"); + + b.Property("ClaimValue") + .HasColumnType("text"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("LoginProvider") + .IsRequired() + .HasColumnType("text"); + + b.Property("ProviderDisplayName") + .HasColumnType("text"); + + b.Property("ProviderKey") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserLogins"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("RoleId") + .HasColumnType("uuid"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.ToTable("UserRoles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("LoginProvider") + .IsRequired() + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.Property("Value") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserTokens"); + }); + + modelBuilder.Entity("FluentCMS.Entities.User", b => + { + b.HasBaseType("Microsoft.AspNetCore.Identity.IdentityUser"); + + b.Property("AuthenticatorKey") + .HasColumnType("text"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("text"); + + b.Property("Enabled") + .HasColumnType("boolean"); + + b.Property("FirstName") + .HasColumnType("text"); + + b.Property("LastName") + .HasColumnType("text"); + + b.Property("LoginAt") + .HasColumnType("timestamp with time zone"); + + b.Property("LoginCount") + .HasColumnType("integer"); + + b.Property("ModifiedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ModifiedBy") + .HasColumnType("text"); + + b.Property("PasswordChangedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("PasswordChangedBy") + .HasColumnType("text"); + + b.HasDiscriminator().HasValue("User"); + }); + + modelBuilder.Entity("FluentCMS.Entities.Block", b => + { + b.HasOne("FluentCMS.Entities.Site", null) + .WithMany() + .HasForeignKey("SiteId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("FluentCMS.Entities.Content", b => + { + b.OwnsOne("System.Collections.Generic.Dictionary", "Data", b1 => + { + b1.Property("ContentId") + .HasColumnType("uuid"); + + b1.HasKey("ContentId"); + + b1.ToTable("Contents"); + + b1.ToJson("Data"); + + b1.WithOwner() + .HasForeignKey("ContentId"); + }); + + b.Navigation("Data") + .IsRequired(); + }); + + modelBuilder.Entity("FluentCMS.Entities.ContentTypeField", b => + { + b.HasOne("FluentCMS.Entities.ContentType", null) + .WithMany("Fields") + .HasForeignKey("ContentTypeId"); + + b.HasOne("FluentCMS.Entities.ContentType", null) + .WithMany() + .HasForeignKey("TypeId"); + }); + + modelBuilder.Entity("FluentCMS.Entities.File", b => + { + b.HasOne("FluentCMS.Entities.Folder", null) + .WithMany() + .HasForeignKey("FolderId"); + }); + + modelBuilder.Entity("FluentCMS.Entities.Folder", b => + { + b.HasOne("FluentCMS.Entities.Folder", null) + .WithMany() + .HasForeignKey("FolderId"); + }); + + modelBuilder.Entity("FluentCMS.Entities.GlobalSettings", b => + { + b.OwnsOne("FluentCMS.Entities.FileUploadConfig", "FileUpload", b1 => + { + b1.Property("GlobalSettingsId") + .HasColumnType("uuid"); + + b1.Property("AllowedExtensions") + .IsRequired() + .HasColumnType("text"); + + b1.Property("MaxCount") + .HasColumnType("integer"); + + b1.Property("MaxSize") + .HasColumnType("bigint"); + + b1.HasKey("GlobalSettingsId"); + + b1.ToTable("GlobalSettings"); + + b1.ToJson("FileUpload"); + + b1.WithOwner() + .HasForeignKey("GlobalSettingsId"); + }); + + b.Navigation("FileUpload"); + }); + + modelBuilder.Entity("FluentCMS.Entities.Layout", b => + { + b.HasOne("FluentCMS.Entities.Site", null) + .WithMany() + .HasForeignKey("SiteId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("FluentCMS.Entities.Page", b => + { + b.HasOne("FluentCMS.Entities.Site", null) + .WithMany() + .HasForeignKey("SiteId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("FluentCMS.Entities.Permission", b => + { + b.HasOne("FluentCMS.Entities.Site", null) + .WithMany() + .HasForeignKey("SiteId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("FluentCMS.Entities.Plugin", b => + { + b.HasOne("FluentCMS.Entities.Site", null) + .WithMany() + .HasForeignKey("SiteId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("FluentCMS.Entities.PluginContent", b => + { + b.HasOne("FluentCMS.Entities.Plugin", null) + .WithMany() + .HasForeignKey("PluginId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("FluentCMS.Entities.Site", null) + .WithMany() + .HasForeignKey("SiteId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.OwnsOne("System.Collections.Generic.Dictionary", "Data", b1 => + { + b1.Property("PluginContentId") + .HasColumnType("uuid"); + + b1.HasKey("PluginContentId"); + + b1.ToTable("PluginContents"); + + b1.ToJson("Data"); + + b1.WithOwner() + .HasForeignKey("PluginContentId"); + }); + + b.Navigation("Data") + .IsRequired(); + }); + + modelBuilder.Entity("FluentCMS.Entities.PluginDefinitionType", b => + { + b.HasOne("FluentCMS.Entities.PluginDefinition", null) + .WithMany() + .HasForeignKey("DefinitionId"); + + b.HasOne("FluentCMS.Entities.PluginDefinition", null) + .WithMany("Types") + .HasForeignKey("PluginDefinitionId"); + }); + + modelBuilder.Entity("FluentCMS.Entities.Policy", b => + { + b.HasOne("FluentCMS.Entities.ApiToken", null) + .WithMany("Policies") + .HasForeignKey("ApiTokenId"); + + b.OwnsOne("FluentCMS.Entities.Policy.Actions#List", "Actions", b1 => + { + b1.Property("PolicyId") + .HasColumnType("uuid"); + + b1.Property("Capacity") + .HasColumnType("integer"); + + b1.HasKey("PolicyId"); + + b1.ToTable("Policy"); + + b1.ToJson("Actions"); + + b1.WithOwner() + .HasForeignKey("PolicyId"); + }); + + b.Navigation("Actions") + .IsRequired(); + }); + + modelBuilder.Entity("FluentCMS.Entities.Role", b => + { + b.HasOne("FluentCMS.Entities.Site", null) + .WithMany() + .HasForeignKey("SiteId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("FluentCMS.Entities.Settings", b => + { + b.OwnsOne("System.Collections.Generic.Dictionary", "Values", b1 => + { + b1.Property("SettingsId") + .HasColumnType("uuid"); + + b1.HasKey("SettingsId"); + + b1.ToTable("Settings"); + + b1.ToJson("Values"); + + b1.WithOwner() + .HasForeignKey("SettingsId"); + }); + + b.Navigation("Values") + .IsRequired(); + }); + + modelBuilder.Entity("FluentCMS.Entities.Site", b => + { + b.HasOne("FluentCMS.Entities.Layout", null) + .WithMany() + .HasForeignKey("DetailLayoutId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("FluentCMS.Entities.Layout", null) + .WithMany() + .HasForeignKey("EditLayoutId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("FluentCMS.Entities.Layout", null) + .WithMany() + .HasForeignKey("LayoutId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.OwnsOne("System.Collections.Generic.List", "Urls", b1 => + { + b1.Property("SiteId") + .HasColumnType("uuid"); + + b1.Property("Capacity") + .HasColumnType("integer"); + + b1.HasKey("SiteId"); + + b1.ToTable("Sites"); + + b1.ToJson("Urls"); + + b1.WithOwner() + .HasForeignKey("SiteId"); + }); + + b.Navigation("Urls") + .IsRequired(); + }); + + modelBuilder.Entity("FluentCMS.Entities.UserRole", b => + { + b.HasOne("FluentCMS.Entities.Role", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("FluentCMS.Entities.Site", null) + .WithMany() + .HasForeignKey("SiteId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("FluentCMS.Entities.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("FluentCMS.Entities.UserTwoFactorRecoveryCode", b => + { + b.HasOne("FluentCMS.Entities.User", null) + .WithMany("RecoveryCodes") + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("FluentCMS.Entities.User", null) + .WithMany("Claims") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("FluentCMS.Entities.User", null) + .WithMany("Logins") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("FluentCMS.Entities.User", null) + .WithMany("Tokens") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("FluentCMS.Entities.ApiToken", b => + { + b.Navigation("Policies"); + }); + + modelBuilder.Entity("FluentCMS.Entities.ContentType", b => + { + b.Navigation("Fields"); + }); + + modelBuilder.Entity("FluentCMS.Entities.PluginDefinition", b => + { + b.Navigation("Types"); + }); + + modelBuilder.Entity("FluentCMS.Entities.User", b => + { + b.Navigation("Claims"); + + b.Navigation("Logins"); + + b.Navigation("RecoveryCodes"); + + b.Navigation("Tokens"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Migrations/20241014214640_Init.cs b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Migrations/20241014214640_Init.cs new file mode 100644 index 000000000..f7dc926dd --- /dev/null +++ b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Migrations/20241014214640_Init.cs @@ -0,0 +1,899 @@ +using System; +using System.Collections.Generic; +using Microsoft.EntityFrameworkCore.Migrations; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace FluentCMS.Repositories.Postgres.Migrations +{ + /// + public partial class Init : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "ApiTokens", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + Name = table.Column(type: "text", nullable: false), + Description = table.Column(type: "text", nullable: true), + Key = table.Column(type: "text", nullable: false), + Secret = table.Column(type: "text", nullable: false), + ExpireAt = table.Column(type: "timestamp with time zone", nullable: true), + Enabled = table.Column(type: "boolean", nullable: false), + CreatedBy = table.Column(type: "text", nullable: false), + CreatedAt = table.Column(type: "timestamp with time zone", nullable: false), + ModifiedBy = table.Column(type: "text", nullable: true), + ModifiedAt = table.Column(type: "timestamp with time zone", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_ApiTokens", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "Contents", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + TypeId = table.Column(type: "uuid", nullable: false), + CreatedBy = table.Column(type: "text", nullable: false), + CreatedAt = table.Column(type: "timestamp with time zone", nullable: false), + ModifiedBy = table.Column(type: "text", nullable: true), + ModifiedAt = table.Column(type: "timestamp with time zone", nullable: true), + Data = table.Column(type: "jsonb", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Contents", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "ContentTypes", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + Slug = table.Column(type: "text", nullable: false), + Title = table.Column(type: "text", nullable: false), + Description = table.Column(type: "text", nullable: true), + CreatedBy = table.Column(type: "text", nullable: false), + CreatedAt = table.Column(type: "timestamp with time zone", nullable: false), + ModifiedBy = table.Column(type: "text", nullable: true), + ModifiedAt = table.Column(type: "timestamp with time zone", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_ContentTypes", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "Folders", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + Name = table.Column(type: "text", nullable: false), + FolderId = table.Column(type: "uuid", nullable: true), + CreatedBy = table.Column(type: "text", nullable: false), + CreatedAt = table.Column(type: "timestamp with time zone", nullable: false), + ModifiedBy = table.Column(type: "text", nullable: true), + ModifiedAt = table.Column(type: "timestamp with time zone", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Folders", x => x.Id); + table.ForeignKey( + name: "FK_Folders_Folders_FolderId", + column: x => x.FolderId, + principalTable: "Folders", + principalColumn: "Id"); + }); + + migrationBuilder.CreateTable( + name: "GlobalSettings", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + SuperAdmins = table.Column>(type: "text[]", nullable: false), + Initialized = table.Column(type: "boolean", nullable: false), + CreatedBy = table.Column(type: "text", nullable: false), + CreatedAt = table.Column(type: "timestamp with time zone", nullable: false), + ModifiedBy = table.Column(type: "text", nullable: true), + ModifiedAt = table.Column(type: "timestamp with time zone", nullable: true), + FileUpload = table.Column(type: "jsonb", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_GlobalSettings", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "IdentityUser", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + UserName = table.Column(type: "text", nullable: true), + NormalizedUserName = table.Column(type: "text", nullable: true), + Email = table.Column(type: "text", nullable: true), + NormalizedEmail = table.Column(type: "text", nullable: true), + EmailConfirmed = table.Column(type: "boolean", nullable: false), + PasswordHash = table.Column(type: "text", nullable: true), + SecurityStamp = table.Column(type: "text", nullable: true), + ConcurrencyStamp = table.Column(type: "text", nullable: true), + PhoneNumber = table.Column(type: "text", nullable: true), + PhoneNumberConfirmed = table.Column(type: "boolean", nullable: false), + TwoFactorEnabled = table.Column(type: "boolean", nullable: false), + LockoutEnd = table.Column(type: "timestamp with time zone", nullable: true), + LockoutEnabled = table.Column(type: "boolean", nullable: false), + AccessFailedCount = table.Column(type: "integer", nullable: false), + Discriminator = table.Column(type: "character varying(21)", maxLength: 21, nullable: false), + LoginAt = table.Column(type: "timestamp with time zone", nullable: true), + LoginCount = table.Column(type: "integer", nullable: true), + PasswordChangedAt = table.Column(type: "timestamp with time zone", nullable: true), + PasswordChangedBy = table.Column(type: "text", nullable: true), + Enabled = table.Column(type: "boolean", nullable: true), + CreatedBy = table.Column(type: "text", nullable: true), + CreatedAt = table.Column(type: "timestamp with time zone", nullable: true), + ModifiedBy = table.Column(type: "text", nullable: true), + ModifiedAt = table.Column(type: "timestamp with time zone", nullable: true), + AuthenticatorKey = table.Column(type: "text", nullable: true), + FirstName = table.Column(type: "text", nullable: true), + LastName = table.Column(type: "text", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_IdentityUser", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "PluginDefinitions", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + Name = table.Column(type: "text", nullable: false), + Category = table.Column(type: "text", nullable: true), + Assembly = table.Column(type: "text", nullable: false), + Description = table.Column(type: "text", nullable: true), + Locked = table.Column(type: "boolean", nullable: false), + CreatedBy = table.Column(type: "text", nullable: false), + CreatedAt = table.Column(type: "timestamp with time zone", nullable: false), + ModifiedBy = table.Column(type: "text", nullable: true), + ModifiedAt = table.Column(type: "timestamp with time zone", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_PluginDefinitions", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "RoleClaims", + columns: table => new + { + Id = table.Column(type: "integer", nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + RoleId = table.Column(type: "uuid", nullable: false), + ClaimType = table.Column(type: "text", nullable: true), + ClaimValue = table.Column(type: "text", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_RoleClaims", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "Roles", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + Name = table.Column(type: "text", nullable: true), + NormalizedName = table.Column(type: "text", nullable: true), + ConcurrencyStamp = table.Column(type: "text", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Roles", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "Settings", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + CreatedBy = table.Column(type: "text", nullable: false), + CreatedAt = table.Column(type: "timestamp with time zone", nullable: false), + ModifiedBy = table.Column(type: "text", nullable: true), + ModifiedAt = table.Column(type: "timestamp with time zone", nullable: true), + Values = table.Column(type: "jsonb", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Settings", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "UserRoles", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + UserId = table.Column(type: "uuid", nullable: false), + RoleId = table.Column(type: "uuid", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_UserRoles", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "Policy", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + Area = table.Column(type: "text", nullable: false), + ApiTokenId = table.Column(type: "uuid", nullable: true), + Actions = table.Column(type: "jsonb", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Policy", x => x.Id); + table.ForeignKey( + name: "FK_Policy_ApiTokens_ApiTokenId", + column: x => x.ApiTokenId, + principalTable: "ApiTokens", + principalColumn: "Id"); + }); + + migrationBuilder.CreateTable( + name: "ContentTypeFields", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + Name = table.Column(type: "text", nullable: false), + Description = table.Column(type: "text", nullable: false), + Type = table.Column(type: "text", nullable: false), + Required = table.Column(type: "boolean", nullable: false), + Unique = table.Column(type: "boolean", nullable: false), + Label = table.Column(type: "text", nullable: false), + Settings = table.Column>(type: "jsonb", nullable: true), + ContentTypeId = table.Column(type: "uuid", nullable: true), + TypeId = table.Column(type: "uuid", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_ContentTypeFields", x => x.Id); + table.ForeignKey( + name: "FK_ContentTypeFields_ContentTypes_ContentTypeId", + column: x => x.ContentTypeId, + principalTable: "ContentTypes", + principalColumn: "Id"); + table.ForeignKey( + name: "FK_ContentTypeFields_ContentTypes_TypeId", + column: x => x.TypeId, + principalTable: "ContentTypes", + principalColumn: "Id"); + }); + + migrationBuilder.CreateTable( + name: "Files", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + Name = table.Column(type: "text", nullable: false), + FolderId = table.Column(type: "uuid", nullable: true), + Extension = table.Column(type: "text", nullable: false), + ContentType = table.Column(type: "text", nullable: false), + Size = table.Column(type: "bigint", nullable: false), + CreatedBy = table.Column(type: "text", nullable: false), + CreatedAt = table.Column(type: "timestamp with time zone", nullable: false), + ModifiedBy = table.Column(type: "text", nullable: true), + ModifiedAt = table.Column(type: "timestamp with time zone", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Files", x => x.Id); + table.ForeignKey( + name: "FK_Files_Folders_FolderId", + column: x => x.FolderId, + principalTable: "Folders", + principalColumn: "Id"); + }); + + migrationBuilder.CreateTable( + name: "UserClaims", + columns: table => new + { + Id = table.Column(type: "integer", nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + UserId = table.Column(type: "uuid", nullable: false), + ClaimType = table.Column(type: "text", nullable: true), + ClaimValue = table.Column(type: "text", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_UserClaims", x => x.Id); + table.ForeignKey( + name: "FK_UserClaims_IdentityUser_UserId", + column: x => x.UserId, + principalTable: "IdentityUser", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "UserLogins", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + LoginProvider = table.Column(type: "text", nullable: false), + ProviderKey = table.Column(type: "text", nullable: false), + ProviderDisplayName = table.Column(type: "text", nullable: true), + UserId = table.Column(type: "uuid", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_UserLogins", x => x.Id); + table.ForeignKey( + name: "FK_UserLogins_IdentityUser_UserId", + column: x => x.UserId, + principalTable: "IdentityUser", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "UserTokens", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + UserId = table.Column(type: "uuid", nullable: false), + LoginProvider = table.Column(type: "text", nullable: false), + Name = table.Column(type: "text", nullable: false), + Value = table.Column(type: "text", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_UserTokens", x => x.Id); + table.ForeignKey( + name: "FK_UserTokens_IdentityUser_UserId", + column: x => x.UserId, + principalTable: "IdentityUser", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "UserTwoFactorRecoveryCode", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + Code = table.Column(type: "text", nullable: false), + Redeemed = table.Column(type: "boolean", nullable: false), + UserId = table.Column(type: "uuid", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_UserTwoFactorRecoveryCode", x => x.Id); + table.ForeignKey( + name: "FK_UserTwoFactorRecoveryCode_IdentityUser_UserId", + column: x => x.UserId, + principalTable: "IdentityUser", + principalColumn: "Id"); + }); + + migrationBuilder.CreateTable( + name: "PluginDefinitionType", + columns: table => new + { + Name = table.Column(type: "text", nullable: false), + Type = table.Column(type: "text", nullable: false), + IsDefault = table.Column(type: "boolean", nullable: false), + DefinitionId = table.Column(type: "uuid", nullable: true), + PluginDefinitionId = table.Column(type: "uuid", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_PluginDefinitionType", x => new { x.Type, x.Name }); + table.ForeignKey( + name: "FK_PluginDefinitionType_PluginDefinitions_DefinitionId", + column: x => x.DefinitionId, + principalTable: "PluginDefinitions", + principalColumn: "Id"); + table.ForeignKey( + name: "FK_PluginDefinitionType_PluginDefinitions_PluginDefinitionId", + column: x => x.PluginDefinitionId, + principalTable: "PluginDefinitions", + principalColumn: "Id"); + }); + + migrationBuilder.CreateTable( + name: "Blocks", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + Name = table.Column(type: "text", nullable: false), + Category = table.Column(type: "text", nullable: false), + Description = table.Column(type: "text", nullable: true), + Content = table.Column(type: "text", nullable: false), + CreatedBy = table.Column(type: "text", nullable: false), + CreatedAt = table.Column(type: "timestamp with time zone", nullable: false), + ModifiedBy = table.Column(type: "text", nullable: true), + ModifiedAt = table.Column(type: "timestamp with time zone", nullable: true), + SiteId = table.Column(type: "uuid", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Blocks", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "Layouts", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + Name = table.Column(type: "text", nullable: false), + Body = table.Column(type: "text", nullable: false), + Head = table.Column(type: "text", nullable: false), + CreatedBy = table.Column(type: "text", nullable: false), + CreatedAt = table.Column(type: "timestamp with time zone", nullable: false), + ModifiedBy = table.Column(type: "text", nullable: true), + ModifiedAt = table.Column(type: "timestamp with time zone", nullable: true), + SiteId = table.Column(type: "uuid", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Layouts", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "Sites", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + Name = table.Column(type: "text", nullable: false), + Description = table.Column(type: "text", nullable: true), + LayoutId = table.Column(type: "uuid", nullable: false), + DetailLayoutId = table.Column(type: "uuid", nullable: false), + EditLayoutId = table.Column(type: "uuid", nullable: false), + CreatedBy = table.Column(type: "text", nullable: false), + CreatedAt = table.Column(type: "timestamp with time zone", nullable: false), + ModifiedBy = table.Column(type: "text", nullable: true), + ModifiedAt = table.Column(type: "timestamp with time zone", nullable: true), + Urls = table.Column(type: "jsonb", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Sites", x => x.Id); + table.ForeignKey( + name: "FK_Sites_Layouts_DetailLayoutId", + column: x => x.DetailLayoutId, + principalTable: "Layouts", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_Sites_Layouts_EditLayoutId", + column: x => x.EditLayoutId, + principalTable: "Layouts", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_Sites_Layouts_LayoutId", + column: x => x.LayoutId, + principalTable: "Layouts", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "Pages", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + Title = table.Column(type: "text", nullable: false), + ParentId = table.Column(type: "uuid", nullable: true), + Order = table.Column(type: "integer", nullable: false), + Path = table.Column(type: "text", nullable: false), + LayoutId = table.Column(type: "uuid", nullable: true), + EditLayoutId = table.Column(type: "uuid", nullable: true), + DetailLayoutId = table.Column(type: "uuid", nullable: true), + Locked = table.Column(type: "boolean", nullable: false), + CreatedBy = table.Column(type: "text", nullable: false), + CreatedAt = table.Column(type: "timestamp with time zone", nullable: false), + ModifiedBy = table.Column(type: "text", nullable: true), + ModifiedAt = table.Column(type: "timestamp with time zone", nullable: true), + SiteId = table.Column(type: "uuid", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Pages", x => x.Id); + table.ForeignKey( + name: "FK_Pages_Sites_SiteId", + column: x => x.SiteId, + principalTable: "Sites", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "Permissions", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + EntityId = table.Column(type: "uuid", nullable: false), + EntityType = table.Column(type: "text", nullable: false), + Action = table.Column(type: "text", nullable: false), + RoleId = table.Column(type: "uuid", nullable: false), + CreatedBy = table.Column(type: "text", nullable: false), + CreatedAt = table.Column(type: "timestamp with time zone", nullable: false), + ModifiedBy = table.Column(type: "text", nullable: true), + ModifiedAt = table.Column(type: "timestamp with time zone", nullable: true), + SiteId = table.Column(type: "uuid", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Permissions", x => x.Id); + table.ForeignKey( + name: "FK_Permissions_Sites_SiteId", + column: x => x.SiteId, + principalTable: "Sites", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "Plugin", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + DefinitionId = table.Column(type: "uuid", nullable: false), + PageId = table.Column(type: "uuid", nullable: false), + Order = table.Column(type: "integer", nullable: false), + Cols = table.Column(type: "integer", nullable: false), + ColsMd = table.Column(type: "integer", nullable: false), + ColsLg = table.Column(type: "integer", nullable: false), + Section = table.Column(type: "text", nullable: false), + Locked = table.Column(type: "boolean", nullable: false), + CreatedBy = table.Column(type: "text", nullable: false), + CreatedAt = table.Column(type: "timestamp with time zone", nullable: false), + ModifiedBy = table.Column(type: "text", nullable: true), + ModifiedAt = table.Column(type: "timestamp with time zone", nullable: true), + SiteId = table.Column(type: "uuid", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Plugin", x => x.Id); + table.ForeignKey( + name: "FK_Plugin_Sites_SiteId", + column: x => x.SiteId, + principalTable: "Sites", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "Role", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + Name = table.Column(type: "text", nullable: false), + Description = table.Column(type: "text", nullable: true), + Type = table.Column(type: "text", nullable: false), + CreatedBy = table.Column(type: "text", nullable: false), + CreatedAt = table.Column(type: "timestamp with time zone", nullable: false), + ModifiedBy = table.Column(type: "text", nullable: true), + ModifiedAt = table.Column(type: "timestamp with time zone", nullable: true), + SiteId = table.Column(type: "uuid", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Role", x => x.Id); + table.ForeignKey( + name: "FK_Role_Sites_SiteId", + column: x => x.SiteId, + principalTable: "Sites", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "PluginContents", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + PluginId = table.Column(type: "uuid", nullable: false), + Type = table.Column(type: "text", nullable: false), + CreatedBy = table.Column(type: "text", nullable: false), + CreatedAt = table.Column(type: "timestamp with time zone", nullable: false), + ModifiedBy = table.Column(type: "text", nullable: true), + ModifiedAt = table.Column(type: "timestamp with time zone", nullable: true), + SiteId = table.Column(type: "uuid", nullable: false), + Data = table.Column(type: "jsonb", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_PluginContents", x => x.Id); + table.ForeignKey( + name: "FK_PluginContents_Plugin_PluginId", + column: x => x.PluginId, + principalTable: "Plugin", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_PluginContents_Sites_SiteId", + column: x => x.SiteId, + principalTable: "Sites", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "UserRole", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + UserId = table.Column(type: "uuid", nullable: false), + RoleId = table.Column(type: "uuid", nullable: false), + CreatedBy = table.Column(type: "text", nullable: false), + CreatedAt = table.Column(type: "timestamp with time zone", nullable: false), + ModifiedBy = table.Column(type: "text", nullable: true), + ModifiedAt = table.Column(type: "timestamp with time zone", nullable: true), + SiteId = table.Column(type: "uuid", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_UserRole", x => x.Id); + table.ForeignKey( + name: "FK_UserRole_IdentityUser_UserId", + column: x => x.UserId, + principalTable: "IdentityUser", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_UserRole_Role_RoleId", + column: x => x.RoleId, + principalTable: "Role", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_UserRole_Sites_SiteId", + column: x => x.SiteId, + principalTable: "Sites", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_Blocks_SiteId", + table: "Blocks", + column: "SiteId"); + + migrationBuilder.CreateIndex( + name: "IX_ContentTypeFields_ContentTypeId", + table: "ContentTypeFields", + column: "ContentTypeId"); + + migrationBuilder.CreateIndex( + name: "IX_ContentTypeFields_TypeId", + table: "ContentTypeFields", + column: "TypeId"); + + migrationBuilder.CreateIndex( + name: "IX_Files_FolderId", + table: "Files", + column: "FolderId"); + + migrationBuilder.CreateIndex( + name: "IX_Folders_FolderId", + table: "Folders", + column: "FolderId"); + + migrationBuilder.CreateIndex( + name: "IX_Layouts_SiteId", + table: "Layouts", + column: "SiteId"); + + migrationBuilder.CreateIndex( + name: "IX_Pages_SiteId", + table: "Pages", + column: "SiteId"); + + migrationBuilder.CreateIndex( + name: "IX_Permissions_SiteId", + table: "Permissions", + column: "SiteId"); + + migrationBuilder.CreateIndex( + name: "IX_Plugin_SiteId", + table: "Plugin", + column: "SiteId"); + + migrationBuilder.CreateIndex( + name: "IX_PluginContents_PluginId", + table: "PluginContents", + column: "PluginId"); + + migrationBuilder.CreateIndex( + name: "IX_PluginContents_SiteId", + table: "PluginContents", + column: "SiteId"); + + migrationBuilder.CreateIndex( + name: "IX_PluginDefinitionType_DefinitionId", + table: "PluginDefinitionType", + column: "DefinitionId"); + + migrationBuilder.CreateIndex( + name: "IX_PluginDefinitionType_PluginDefinitionId", + table: "PluginDefinitionType", + column: "PluginDefinitionId"); + + migrationBuilder.CreateIndex( + name: "IX_Policy_ApiTokenId", + table: "Policy", + column: "ApiTokenId"); + + migrationBuilder.CreateIndex( + name: "IX_Role_SiteId", + table: "Role", + column: "SiteId"); + + migrationBuilder.CreateIndex( + name: "IX_Sites_DetailLayoutId", + table: "Sites", + column: "DetailLayoutId"); + + migrationBuilder.CreateIndex( + name: "IX_Sites_EditLayoutId", + table: "Sites", + column: "EditLayoutId"); + + migrationBuilder.CreateIndex( + name: "IX_Sites_LayoutId", + table: "Sites", + column: "LayoutId"); + + migrationBuilder.CreateIndex( + name: "IX_UserClaims_UserId", + table: "UserClaims", + column: "UserId"); + + migrationBuilder.CreateIndex( + name: "IX_UserLogins_UserId", + table: "UserLogins", + column: "UserId"); + + migrationBuilder.CreateIndex( + name: "IX_UserRole_RoleId", + table: "UserRole", + column: "RoleId"); + + migrationBuilder.CreateIndex( + name: "IX_UserRole_SiteId", + table: "UserRole", + column: "SiteId"); + + migrationBuilder.CreateIndex( + name: "IX_UserRole_UserId", + table: "UserRole", + column: "UserId"); + + migrationBuilder.CreateIndex( + name: "IX_UserTokens_UserId", + table: "UserTokens", + column: "UserId"); + + migrationBuilder.CreateIndex( + name: "IX_UserTwoFactorRecoveryCode_UserId", + table: "UserTwoFactorRecoveryCode", + column: "UserId"); + + migrationBuilder.AddForeignKey( + name: "FK_Blocks_Sites_SiteId", + table: "Blocks", + column: "SiteId", + principalTable: "Sites", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + + migrationBuilder.AddForeignKey( + name: "FK_Layouts_Sites_SiteId", + table: "Layouts", + column: "SiteId", + principalTable: "Sites", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_Layouts_Sites_SiteId", + table: "Layouts"); + + migrationBuilder.DropTable( + name: "Blocks"); + + migrationBuilder.DropTable( + name: "Contents"); + + migrationBuilder.DropTable( + name: "ContentTypeFields"); + + migrationBuilder.DropTable( + name: "Files"); + + migrationBuilder.DropTable( + name: "GlobalSettings"); + + migrationBuilder.DropTable( + name: "Pages"); + + migrationBuilder.DropTable( + name: "Permissions"); + + migrationBuilder.DropTable( + name: "PluginContents"); + + migrationBuilder.DropTable( + name: "PluginDefinitionType"); + + migrationBuilder.DropTable( + name: "Policy"); + + migrationBuilder.DropTable( + name: "RoleClaims"); + + migrationBuilder.DropTable( + name: "Roles"); + + migrationBuilder.DropTable( + name: "Settings"); + + migrationBuilder.DropTable( + name: "UserClaims"); + + migrationBuilder.DropTable( + name: "UserLogins"); + + migrationBuilder.DropTable( + name: "UserRole"); + + migrationBuilder.DropTable( + name: "UserRoles"); + + migrationBuilder.DropTable( + name: "UserTokens"); + + migrationBuilder.DropTable( + name: "UserTwoFactorRecoveryCode"); + + migrationBuilder.DropTable( + name: "ContentTypes"); + + migrationBuilder.DropTable( + name: "Folders"); + + migrationBuilder.DropTable( + name: "Plugin"); + + migrationBuilder.DropTable( + name: "PluginDefinitions"); + + migrationBuilder.DropTable( + name: "ApiTokens"); + + migrationBuilder.DropTable( + name: "Role"); + + migrationBuilder.DropTable( + name: "IdentityUser"); + + migrationBuilder.DropTable( + name: "Sites"); + + migrationBuilder.DropTable( + name: "Layouts"); + } + } +} diff --git a/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Migrations/PostgresDbContextModelSnapshot.cs b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Migrations/PostgresDbContextModelSnapshot.cs new file mode 100644 index 000000000..2739d7c50 --- /dev/null +++ b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Migrations/PostgresDbContextModelSnapshot.cs @@ -0,0 +1,1412 @@ +// +using System; +using System.Collections.Generic; +using FluentCMS.Repositories.Postgres; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace FluentCMS.Repositories.Postgres.Migrations +{ + [DbContext(typeof(PostgresDbContext))] + partial class PostgresDbContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.10") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("FluentCMS.Entities.ApiToken", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("text"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("Enabled") + .HasColumnType("boolean"); + + b.Property("ExpireAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Key") + .IsRequired() + .HasColumnType("text"); + + b.Property("ModifiedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ModifiedBy") + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Secret") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("ApiTokens"); + }); + + modelBuilder.Entity("FluentCMS.Entities.Block", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Category") + .IsRequired() + .HasColumnType("text"); + + b.Property("Content") + .IsRequired() + .HasColumnType("text"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("text"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("ModifiedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ModifiedBy") + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("SiteId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("SiteId"); + + b.ToTable("Blocks"); + }); + + modelBuilder.Entity("FluentCMS.Entities.Content", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("text"); + + b.Property("ModifiedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ModifiedBy") + .HasColumnType("text"); + + b.Property("TypeId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.ToTable("Contents"); + }); + + modelBuilder.Entity("FluentCMS.Entities.ContentType", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("text"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("ModifiedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ModifiedBy") + .HasColumnType("text"); + + b.Property("Slug") + .IsRequired() + .HasColumnType("text"); + + b.Property("Title") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("ContentTypes"); + }); + + modelBuilder.Entity("FluentCMS.Entities.ContentTypeField", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ContentTypeId") + .HasColumnType("uuid"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("Label") + .IsRequired() + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Required") + .HasColumnType("boolean"); + + b.Property>("Settings") + .HasColumnType("jsonb"); + + b.Property("Type") + .IsRequired() + .HasColumnType("text"); + + b.Property("TypeId") + .HasColumnType("uuid"); + + b.Property("Unique") + .HasColumnType("boolean"); + + b.HasKey("Id"); + + b.HasIndex("ContentTypeId"); + + b.HasIndex("TypeId"); + + b.ToTable("ContentTypeFields"); + }); + + modelBuilder.Entity("FluentCMS.Entities.File", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ContentType") + .IsRequired() + .HasColumnType("text"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("text"); + + b.Property("Extension") + .IsRequired() + .HasColumnType("text"); + + b.Property("FolderId") + .HasColumnType("uuid"); + + b.Property("ModifiedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ModifiedBy") + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Size") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("FolderId"); + + b.ToTable("Files"); + }); + + modelBuilder.Entity("FluentCMS.Entities.Folder", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("text"); + + b.Property("FolderId") + .HasColumnType("uuid"); + + b.Property("ModifiedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ModifiedBy") + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("FolderId"); + + b.ToTable("Folders"); + }); + + modelBuilder.Entity("FluentCMS.Entities.GlobalSettings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("text"); + + b.Property("Initialized") + .HasColumnType("boolean"); + + b.Property("ModifiedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ModifiedBy") + .HasColumnType("text"); + + b.Property>("SuperAdmins") + .IsRequired() + .HasColumnType("text[]"); + + b.HasKey("Id"); + + b.ToTable("GlobalSettings"); + }); + + modelBuilder.Entity("FluentCMS.Entities.Layout", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Body") + .IsRequired() + .HasColumnType("text"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("text"); + + b.Property("Head") + .IsRequired() + .HasColumnType("text"); + + b.Property("ModifiedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ModifiedBy") + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("SiteId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("SiteId"); + + b.ToTable("Layouts"); + }); + + modelBuilder.Entity("FluentCMS.Entities.Page", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("text"); + + b.Property("DetailLayoutId") + .HasColumnType("uuid"); + + b.Property("EditLayoutId") + .HasColumnType("uuid"); + + b.Property("LayoutId") + .HasColumnType("uuid"); + + b.Property("Locked") + .HasColumnType("boolean"); + + b.Property("ModifiedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ModifiedBy") + .HasColumnType("text"); + + b.Property("Order") + .HasColumnType("integer"); + + b.Property("ParentId") + .HasColumnType("uuid"); + + b.Property("Path") + .IsRequired() + .HasColumnType("text"); + + b.Property("SiteId") + .HasColumnType("uuid"); + + b.Property("Title") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("SiteId"); + + b.ToTable("Pages"); + }); + + modelBuilder.Entity("FluentCMS.Entities.Permission", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Action") + .IsRequired() + .HasColumnType("text"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("text"); + + b.Property("EntityId") + .HasColumnType("uuid"); + + b.Property("EntityType") + .IsRequired() + .HasColumnType("text"); + + b.Property("ModifiedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ModifiedBy") + .HasColumnType("text"); + + b.Property("RoleId") + .HasColumnType("uuid"); + + b.Property("SiteId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("SiteId"); + + b.ToTable("Permissions"); + }); + + modelBuilder.Entity("FluentCMS.Entities.Plugin", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Cols") + .HasColumnType("integer"); + + b.Property("ColsLg") + .HasColumnType("integer"); + + b.Property("ColsMd") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("text"); + + b.Property("DefinitionId") + .HasColumnType("uuid"); + + b.Property("Locked") + .HasColumnType("boolean"); + + b.Property("ModifiedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ModifiedBy") + .HasColumnType("text"); + + b.Property("Order") + .HasColumnType("integer"); + + b.Property("PageId") + .HasColumnType("uuid"); + + b.Property("Section") + .IsRequired() + .HasColumnType("text"); + + b.Property("SiteId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("SiteId"); + + b.ToTable("Plugin"); + }); + + modelBuilder.Entity("FluentCMS.Entities.PluginContent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("text"); + + b.Property("ModifiedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ModifiedBy") + .HasColumnType("text"); + + b.Property("PluginId") + .HasColumnType("uuid"); + + b.Property("SiteId") + .HasColumnType("uuid"); + + b.Property("Type") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("PluginId"); + + b.HasIndex("SiteId"); + + b.ToTable("PluginContents"); + }); + + modelBuilder.Entity("FluentCMS.Entities.PluginDefinition", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Assembly") + .IsRequired() + .HasColumnType("text"); + + b.Property("Category") + .HasColumnType("text"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("text"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("Locked") + .HasColumnType("boolean"); + + b.Property("ModifiedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ModifiedBy") + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("PluginDefinitions"); + }); + + modelBuilder.Entity("FluentCMS.Entities.PluginDefinitionType", b => + { + b.Property("Type") + .HasColumnType("text"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("DefinitionId") + .HasColumnType("uuid"); + + b.Property("IsDefault") + .HasColumnType("boolean"); + + b.Property("PluginDefinitionId") + .HasColumnType("uuid"); + + b.HasKey("Type", "Name"); + + b.HasIndex("DefinitionId"); + + b.HasIndex("PluginDefinitionId"); + + b.ToTable("PluginDefinitionType"); + }); + + modelBuilder.Entity("FluentCMS.Entities.Policy", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ApiTokenId") + .HasColumnType("uuid"); + + b.Property("Area") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("ApiTokenId"); + + b.ToTable("Policy"); + }); + + modelBuilder.Entity("FluentCMS.Entities.Role", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("text"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("ModifiedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ModifiedBy") + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("SiteId") + .HasColumnType("uuid"); + + b.Property("Type") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("SiteId"); + + b.ToTable("Role"); + }); + + modelBuilder.Entity("FluentCMS.Entities.Settings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("text"); + + b.Property("ModifiedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ModifiedBy") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("Settings"); + }); + + modelBuilder.Entity("FluentCMS.Entities.Site", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("text"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("DetailLayoutId") + .HasColumnType("uuid"); + + b.Property("EditLayoutId") + .HasColumnType("uuid"); + + b.Property("LayoutId") + .HasColumnType("uuid"); + + b.Property("ModifiedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ModifiedBy") + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("DetailLayoutId"); + + b.HasIndex("EditLayoutId"); + + b.HasIndex("LayoutId"); + + b.ToTable("Sites"); + }); + + modelBuilder.Entity("FluentCMS.Entities.UserRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("text"); + + b.Property("ModifiedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ModifiedBy") + .HasColumnType("text"); + + b.Property("RoleId") + .HasColumnType("uuid"); + + b.Property("SiteId") + .HasColumnType("uuid"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.HasIndex("SiteId"); + + b.HasIndex("UserId"); + + b.ToTable("UserRole"); + }); + + modelBuilder.Entity("FluentCMS.Entities.UserTwoFactorRecoveryCode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Code") + .IsRequired() + .HasColumnType("text"); + + b.Property("Redeemed") + .HasColumnType("boolean"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserTwoFactorRecoveryCode"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .HasColumnType("text"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("NormalizedName") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("Roles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("text"); + + b.Property("ClaimValue") + .HasColumnType("text"); + + b.Property("RoleId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.ToTable("RoleClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AccessFailedCount") + .HasColumnType("integer"); + + b.Property("ConcurrencyStamp") + .HasColumnType("text"); + + b.Property("Discriminator") + .IsRequired() + .HasMaxLength(21) + .HasColumnType("character varying(21)"); + + b.Property("Email") + .HasColumnType("text"); + + b.Property("EmailConfirmed") + .HasColumnType("boolean"); + + b.Property("LockoutEnabled") + .HasColumnType("boolean"); + + b.Property("LockoutEnd") + .HasColumnType("timestamp with time zone"); + + b.Property("NormalizedEmail") + .HasColumnType("text"); + + b.Property("NormalizedUserName") + .HasColumnType("text"); + + b.Property("PasswordHash") + .HasColumnType("text"); + + b.Property("PhoneNumber") + .HasColumnType("text"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("boolean"); + + b.Property("SecurityStamp") + .HasColumnType("text"); + + b.Property("TwoFactorEnabled") + .HasColumnType("boolean"); + + b.Property("UserName") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("IdentityUser"); + + b.HasDiscriminator().HasValue("IdentityUser"); + + b.UseTphMappingStrategy(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("text"); + + b.Property("ClaimValue") + .HasColumnType("text"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("LoginProvider") + .IsRequired() + .HasColumnType("text"); + + b.Property("ProviderDisplayName") + .HasColumnType("text"); + + b.Property("ProviderKey") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserLogins"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("RoleId") + .HasColumnType("uuid"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.ToTable("UserRoles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("LoginProvider") + .IsRequired() + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.Property("Value") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserTokens"); + }); + + modelBuilder.Entity("FluentCMS.Entities.User", b => + { + b.HasBaseType("Microsoft.AspNetCore.Identity.IdentityUser"); + + b.Property("AuthenticatorKey") + .HasColumnType("text"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("text"); + + b.Property("Enabled") + .HasColumnType("boolean"); + + b.Property("FirstName") + .HasColumnType("text"); + + b.Property("LastName") + .HasColumnType("text"); + + b.Property("LoginAt") + .HasColumnType("timestamp with time zone"); + + b.Property("LoginCount") + .HasColumnType("integer"); + + b.Property("ModifiedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ModifiedBy") + .HasColumnType("text"); + + b.Property("PasswordChangedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("PasswordChangedBy") + .HasColumnType("text"); + + b.HasDiscriminator().HasValue("User"); + }); + + modelBuilder.Entity("FluentCMS.Entities.Block", b => + { + b.HasOne("FluentCMS.Entities.Site", null) + .WithMany() + .HasForeignKey("SiteId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("FluentCMS.Entities.Content", b => + { + b.OwnsOne("System.Collections.Generic.Dictionary", "Data", b1 => + { + b1.Property("ContentId") + .HasColumnType("uuid"); + + b1.HasKey("ContentId"); + + b1.ToTable("Contents"); + + b1.ToJson("Data"); + + b1.WithOwner() + .HasForeignKey("ContentId"); + }); + + b.Navigation("Data") + .IsRequired(); + }); + + modelBuilder.Entity("FluentCMS.Entities.ContentTypeField", b => + { + b.HasOne("FluentCMS.Entities.ContentType", null) + .WithMany("Fields") + .HasForeignKey("ContentTypeId"); + + b.HasOne("FluentCMS.Entities.ContentType", null) + .WithMany() + .HasForeignKey("TypeId"); + }); + + modelBuilder.Entity("FluentCMS.Entities.File", b => + { + b.HasOne("FluentCMS.Entities.Folder", null) + .WithMany() + .HasForeignKey("FolderId"); + }); + + modelBuilder.Entity("FluentCMS.Entities.Folder", b => + { + b.HasOne("FluentCMS.Entities.Folder", null) + .WithMany() + .HasForeignKey("FolderId"); + }); + + modelBuilder.Entity("FluentCMS.Entities.GlobalSettings", b => + { + b.OwnsOne("FluentCMS.Entities.FileUploadConfig", "FileUpload", b1 => + { + b1.Property("GlobalSettingsId") + .HasColumnType("uuid"); + + b1.Property("AllowedExtensions") + .IsRequired() + .HasColumnType("text"); + + b1.Property("MaxCount") + .HasColumnType("integer"); + + b1.Property("MaxSize") + .HasColumnType("bigint"); + + b1.HasKey("GlobalSettingsId"); + + b1.ToTable("GlobalSettings"); + + b1.ToJson("FileUpload"); + + b1.WithOwner() + .HasForeignKey("GlobalSettingsId"); + }); + + b.Navigation("FileUpload"); + }); + + modelBuilder.Entity("FluentCMS.Entities.Layout", b => + { + b.HasOne("FluentCMS.Entities.Site", null) + .WithMany() + .HasForeignKey("SiteId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("FluentCMS.Entities.Page", b => + { + b.HasOne("FluentCMS.Entities.Site", null) + .WithMany() + .HasForeignKey("SiteId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("FluentCMS.Entities.Permission", b => + { + b.HasOne("FluentCMS.Entities.Site", null) + .WithMany() + .HasForeignKey("SiteId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("FluentCMS.Entities.Plugin", b => + { + b.HasOne("FluentCMS.Entities.Site", null) + .WithMany() + .HasForeignKey("SiteId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("FluentCMS.Entities.PluginContent", b => + { + b.HasOne("FluentCMS.Entities.Plugin", null) + .WithMany() + .HasForeignKey("PluginId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("FluentCMS.Entities.Site", null) + .WithMany() + .HasForeignKey("SiteId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.OwnsOne("System.Collections.Generic.Dictionary", "Data", b1 => + { + b1.Property("PluginContentId") + .HasColumnType("uuid"); + + b1.HasKey("PluginContentId"); + + b1.ToTable("PluginContents"); + + b1.ToJson("Data"); + + b1.WithOwner() + .HasForeignKey("PluginContentId"); + }); + + b.Navigation("Data") + .IsRequired(); + }); + + modelBuilder.Entity("FluentCMS.Entities.PluginDefinitionType", b => + { + b.HasOne("FluentCMS.Entities.PluginDefinition", null) + .WithMany() + .HasForeignKey("DefinitionId"); + + b.HasOne("FluentCMS.Entities.PluginDefinition", null) + .WithMany("Types") + .HasForeignKey("PluginDefinitionId"); + }); + + modelBuilder.Entity("FluentCMS.Entities.Policy", b => + { + b.HasOne("FluentCMS.Entities.ApiToken", null) + .WithMany("Policies") + .HasForeignKey("ApiTokenId"); + + b.OwnsOne("FluentCMS.Entities.Policy.Actions#List", "Actions", b1 => + { + b1.Property("PolicyId") + .HasColumnType("uuid"); + + b1.Property("Capacity") + .HasColumnType("integer"); + + b1.HasKey("PolicyId"); + + b1.ToTable("Policy"); + + b1.ToJson("Actions"); + + b1.WithOwner() + .HasForeignKey("PolicyId"); + }); + + b.Navigation("Actions") + .IsRequired(); + }); + + modelBuilder.Entity("FluentCMS.Entities.Role", b => + { + b.HasOne("FluentCMS.Entities.Site", null) + .WithMany() + .HasForeignKey("SiteId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("FluentCMS.Entities.Settings", b => + { + b.OwnsOne("System.Collections.Generic.Dictionary", "Values", b1 => + { + b1.Property("SettingsId") + .HasColumnType("uuid"); + + b1.HasKey("SettingsId"); + + b1.ToTable("Settings"); + + b1.ToJson("Values"); + + b1.WithOwner() + .HasForeignKey("SettingsId"); + }); + + b.Navigation("Values") + .IsRequired(); + }); + + modelBuilder.Entity("FluentCMS.Entities.Site", b => + { + b.HasOne("FluentCMS.Entities.Layout", null) + .WithMany() + .HasForeignKey("DetailLayoutId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("FluentCMS.Entities.Layout", null) + .WithMany() + .HasForeignKey("EditLayoutId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("FluentCMS.Entities.Layout", null) + .WithMany() + .HasForeignKey("LayoutId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.OwnsOne("System.Collections.Generic.List", "Urls", b1 => + { + b1.Property("SiteId") + .HasColumnType("uuid"); + + b1.Property("Capacity") + .HasColumnType("integer"); + + b1.HasKey("SiteId"); + + b1.ToTable("Sites"); + + b1.ToJson("Urls"); + + b1.WithOwner() + .HasForeignKey("SiteId"); + }); + + b.Navigation("Urls") + .IsRequired(); + }); + + modelBuilder.Entity("FluentCMS.Entities.UserRole", b => + { + b.HasOne("FluentCMS.Entities.Role", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("FluentCMS.Entities.Site", null) + .WithMany() + .HasForeignKey("SiteId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("FluentCMS.Entities.User", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("FluentCMS.Entities.UserTwoFactorRecoveryCode", b => + { + b.HasOne("FluentCMS.Entities.User", null) + .WithMany("RecoveryCodes") + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("FluentCMS.Entities.User", null) + .WithMany("Claims") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("FluentCMS.Entities.User", null) + .WithMany("Logins") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("FluentCMS.Entities.User", null) + .WithMany("Tokens") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("FluentCMS.Entities.ApiToken", b => + { + b.Navigation("Policies"); + }); + + modelBuilder.Entity("FluentCMS.Entities.ContentType", b => + { + b.Navigation("Fields"); + }); + + modelBuilder.Entity("FluentCMS.Entities.PluginDefinition", b => + { + b.Navigation("Types"); + }); + + modelBuilder.Entity("FluentCMS.Entities.User", b => + { + b.Navigation("Claims"); + + b.Navigation("Logins"); + + b.Navigation("RecoveryCodes"); + + b.Navigation("Tokens"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Backend/Repositories/FluentCMS.Repositories.Postgres/PostgresDbContext.cs b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/PostgresDbContext.cs new file mode 100644 index 000000000..648811b00 --- /dev/null +++ b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/PostgresDbContext.cs @@ -0,0 +1,76 @@ +using EntityFramework.Exceptions.PostgreSQL; +using Microsoft.AspNetCore.Identity; +using Microsoft.AspNetCore.Identity.EntityFrameworkCore; + +namespace FluentCMS.Repositories.Postgres; + +public class PostgresDbContext : IdentityDbContext, Guid> +{ + readonly IApiExecutionContext _apiExecutionContext; + public DbSet ApiTokens { get; set; } = default!; + public DbSet Contents { get; set; } = default!; + public DbSet ContentTypes { get; set; } = default!; + public DbSet ContentTypeFields { get; set; } = default!; + public DbSet Files { get; set; } = default!; + public DbSet Folders { get; set; } = default!; + public DbSet GlobalSettings { get; set; } = default!; + public DbSet Permissions { get; set; } = default!; + public DbSet PluginContents { get; set; } = default!; + public DbSet PluginDefinitions { get; set; } = default!; + + public DbSet Sites { get; set; } = default!; + public DbSet Layouts { get; set; } = default!; + public DbSet Pages { get; set; } = default!; + public DbSet Blocks { get; set; } = default!; + + public PostgresDbContext(DbContextOptions options, IApiExecutionContext apiExecutionContext): base(options) + { + _apiExecutionContext = apiExecutionContext; + } + + protected override void OnModelCreating(ModelBuilder builder) + { + builder.ApplyConfigurationsFromAssembly(typeof(PostgresDbContext).Assembly); + } + + protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) + { + optionsBuilder.UseExceptionProcessor(); + } + + public override Task SaveChangesAsync(CancellationToken cancellationToken = new CancellationToken()) + { + ChangeTracker.DetectChanges(); + ChangeTracker.AutoDetectChangesEnabled = false; + foreach (var entry in ChangeTracker.Entries()) + { + var now = DateTime.UtcNow; + + var userName = _apiExecutionContext.Username; + var entity = entry.Entity; + + switch (entry.State) + { + case EntityState.Added or EntityState.Modified: + { + entity.ModifiedBy = userName; + + entity.ModifiedAt = now; + + if (entity.CreatedAt != default) + { + continue; + } + + entity.CreatedAt = now; + entity.CreatedBy = userName; + break; + } + } + } + + ChangeTracker.AutoDetectChangesEnabled = true; + + return base.SaveChangesAsync(cancellationToken); + } +} diff --git a/src/Backend/Repositories/FluentCMS.Repositories.Postgres/README.md b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/README.md new file mode 100644 index 000000000..458fc2849 --- /dev/null +++ b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/README.md @@ -0,0 +1,3 @@ +# Migrations + +use the supplied ```add-migrations.ps1``` script to generate migrations. diff --git a/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Repositories/ApiTokenRepository.cs b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Repositories/ApiTokenRepository.cs new file mode 100644 index 000000000..14249131d --- /dev/null +++ b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Repositories/ApiTokenRepository.cs @@ -0,0 +1,16 @@ +namespace FluentCMS.Repositories.Postgres.Repositories; + +public class ApiTokenRepository(PostgresDbContext context) : AuditableEntityRepository(context), IApiTokenRepository, IService +{ + public async Task GetByKey(string apiKey, CancellationToken cancellationToken = default) + { + cancellationToken.ThrowIfCancellationRequested(); + return await GetByExpression(x => x.Key == apiKey, cancellationToken); + } + + public async Task GetByName(string name, CancellationToken cancellationToken = default) + { + cancellationToken.ThrowIfCancellationRequested(); + return await Table.FirstOrDefaultAsync(x => x.Name == name,cancellationToken); + } +} diff --git a/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Repositories/Base/AuditableEntityRepository.cs b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Repositories/Base/AuditableEntityRepository.cs new file mode 100644 index 000000000..024a05dec --- /dev/null +++ b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Repositories/Base/AuditableEntityRepository.cs @@ -0,0 +1,7 @@ +namespace FluentCMS.Repositories.Postgres.Repositories.Base; + +public abstract class AuditableEntityRepository(PostgresDbContext context) : EntityRepository(context), IAuditableEntityRepository where TEntity : AuditableEntity +{ + + +} diff --git a/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Repositories/Base/EntityRepository.cs b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Repositories/Base/EntityRepository.cs new file mode 100644 index 000000000..df108c307 --- /dev/null +++ b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Repositories/Base/EntityRepository.cs @@ -0,0 +1,101 @@ +using System.Linq.Expressions; + +namespace FluentCMS.Repositories.Postgres.Repositories.Base; + +public abstract class EntityRepository : IEntityRepository where TEntity : Entity +{ + protected readonly DbSet Table; + protected readonly PostgresDbContext Context; + readonly IQueryable _queryable; + + public EntityRepository(PostgresDbContext context) + { + Table = context.Set(); + _queryable = Table.AsNoTrackingWithIdentityResolution().AsQueryable(); + Context = context; + + } + + protected async Task GetByExpression(Expression> predicate, CancellationToken cancellationToken = default) + { + cancellationToken.ThrowIfCancellationRequested(); + return (await GetAllByExpression(predicate, cancellationToken)).SingleOrDefault(); + } + + protected async Task> GetAllByExpression(Expression> predicate, CancellationToken cancellationToken = default) + { + cancellationToken.ThrowIfCancellationRequested(); + return await _queryable.Where(predicate).ToListAsync(cancellationToken); + } + + + public virtual async Task> GetAll(CancellationToken cancellationToken = default) + { + cancellationToken.ThrowIfCancellationRequested(); + return await _queryable.ToListAsync(cancellationToken); + } + + public virtual async Task GetById(Guid id, CancellationToken cancellationToken = default) + { + cancellationToken.ThrowIfCancellationRequested(); + return await _queryable.SingleOrDefaultAsync(x => x.Id == id, cancellationToken); + } + + public virtual async Task> GetByIds(IEnumerable ids, CancellationToken cancellationToken = default) + { + cancellationToken.ThrowIfCancellationRequested(); + var idsFilter = ids.ToList(); + return await Table.Where(x => idsFilter.Contains(x.Id)).ToListAsync(cancellationToken); + } + + public virtual async Task Create(TEntity entity, CancellationToken cancellationToken = default) + { + cancellationToken.ThrowIfCancellationRequested(); + var result = await Table.AddAsync(entity, cancellationToken); + await Context.SaveChangesAsync(cancellationToken); + return result.Entity; + } + + public virtual async Task> CreateMany(IEnumerable entities, CancellationToken cancellationToken = default) + { + cancellationToken.ThrowIfCancellationRequested(); + var enumerable = entities.ToList(); + await Table.AddRangeAsync(enumerable, cancellationToken); + await Context.SaveChangesAsync(cancellationToken); + return enumerable; + } + + public virtual async Task Update(TEntity entity, CancellationToken cancellationToken = default) + { + cancellationToken.ThrowIfCancellationRequested(); + var result = Table.Update(entity); + await Context.SaveChangesAsync(cancellationToken); + return result.Entity; + + } + + public virtual async Task Delete(Guid id, CancellationToken cancellationToken = default) + { + cancellationToken.ThrowIfCancellationRequested(); + var entity = await GetById( id, cancellationToken); + if (entity == null) + { + return null; + } + + Table.Remove(entity); + await Context.SaveChangesAsync(cancellationToken); + + + return null; + } + + public virtual async Task> DeleteMany(IEnumerable ids, CancellationToken cancellationToken = default) + { + cancellationToken.ThrowIfCancellationRequested(); + var entities = await GetByIds(ids, cancellationToken); + var entityIds = entities.Select(x => x.Id).ToList(); + await Table.Where(x => entityIds.Contains(x.Id)).ExecuteDeleteAsync(cancellationToken); + return entities; + } +} diff --git a/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Repositories/Base/IService.cs b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Repositories/Base/IService.cs new file mode 100644 index 000000000..5a1d3c31f --- /dev/null +++ b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Repositories/Base/IService.cs @@ -0,0 +1,6 @@ +namespace FluentCMS.Repositories.Postgres.Repositories.Base; + +public interface IService +{ + +} diff --git a/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Repositories/BlockRepository.cs b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Repositories/BlockRepository.cs new file mode 100644 index 000000000..5b0069722 --- /dev/null +++ b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Repositories/BlockRepository.cs @@ -0,0 +1,5 @@ +namespace FluentCMS.Repositories.Postgres.Repositories; + +public class BlockRepository(PostgresDbContext context) : SiteAssociatedRepository(context), IBlockRepository, IService +{ +} diff --git a/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Repositories/ContentRepository.cs b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Repositories/ContentRepository.cs new file mode 100644 index 000000000..92895fc49 --- /dev/null +++ b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Repositories/ContentRepository.cs @@ -0,0 +1,11 @@ +namespace FluentCMS.Repositories.Postgres.Repositories; + +public class ContentRepository(PostgresDbContext context) : AuditableEntityRepository(context), IContentRepository, IService +{ + public async Task> GetAll(Guid contentTypeId, CancellationToken cancellationToken = default) + { + cancellationToken.ThrowIfCancellationRequested(); + return await Table.Where(x => x.TypeId == contentTypeId) + .ToListAsync(cancellationToken); + } +} diff --git a/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Repositories/ContentTypeRepository.cs b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Repositories/ContentTypeRepository.cs new file mode 100644 index 000000000..f3afdc661 --- /dev/null +++ b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Repositories/ContentTypeRepository.cs @@ -0,0 +1,10 @@ +namespace FluentCMS.Repositories.Postgres.Repositories; + +public class ContentTypeRepository(PostgresDbContext context) : AuditableEntityRepository(context), IContentTypeRepository, IService +{ + public async Task GetBySlug(string contentTypeSlug, CancellationToken cancellationToken = default) + { + cancellationToken.ThrowIfCancellationRequested(); + return await GetByExpression(x => x.Slug == contentTypeSlug, cancellationToken); + } +} diff --git a/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Repositories/FileRepository.cs b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Repositories/FileRepository.cs new file mode 100644 index 000000000..09096e3eb --- /dev/null +++ b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Repositories/FileRepository.cs @@ -0,0 +1,4 @@ +namespace FluentCMS.Repositories.Postgres.Repositories; + +public class FileRepository(PostgresDbContext context) : AuditableEntityRepository(context), IFileRepository, IService; + diff --git a/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Repositories/FolderRepository.cs b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Repositories/FolderRepository.cs new file mode 100644 index 000000000..4facca69b --- /dev/null +++ b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Repositories/FolderRepository.cs @@ -0,0 +1,3 @@ +namespace FluentCMS.Repositories.Postgres.Repositories; + +public class FolderRepository(PostgresDbContext context) : AuditableEntityRepository(context), IFolderRepository, IService; diff --git a/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Repositories/GlobalSettingsRepository.cs b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Repositories/GlobalSettingsRepository.cs new file mode 100644 index 000000000..d008f7c47 --- /dev/null +++ b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Repositories/GlobalSettingsRepository.cs @@ -0,0 +1,25 @@ +namespace FluentCMS.Repositories.Postgres.Repositories; + +public class GlobalSettingsRepository(PostgresDbContext context) : AuditableEntityRepository(context), IGlobalSettingsRepository, IService +{ + + public async Task Get(CancellationToken cancellationToken = default) + { + cancellationToken.ThrowIfCancellationRequested(); + return (await GetAll(cancellationToken)).SingleOrDefault(); + } + + + public async Task Initialized(CancellationToken cancellationToken = default) + { + cancellationToken.ThrowIfCancellationRequested(); + + var existing = await Get(cancellationToken); + + return existing?.Initialized ?? false; + } + + + + +} diff --git a/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Repositories/LayoutRepository.cs b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Repositories/LayoutRepository.cs new file mode 100644 index 000000000..3857519da --- /dev/null +++ b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Repositories/LayoutRepository.cs @@ -0,0 +1,3 @@ +namespace FluentCMS.Repositories.Postgres.Repositories; + +public class LayoutRepository(PostgresDbContext context ) : SiteAssociatedRepository(context), ILayoutRepository, IService; diff --git a/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Repositories/PageRepository.cs b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Repositories/PageRepository.cs new file mode 100644 index 000000000..0bcb764b4 --- /dev/null +++ b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Repositories/PageRepository.cs @@ -0,0 +1,3 @@ +namespace FluentCMS.Repositories.Postgres.Repositories; + +public class PageRepository(PostgresDbContext context) : SiteAssociatedRepository(context), IPageRepository, IService; diff --git a/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Repositories/PermissionRepository.cs b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Repositories/PermissionRepository.cs new file mode 100644 index 000000000..2c3291792 --- /dev/null +++ b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Repositories/PermissionRepository.cs @@ -0,0 +1,27 @@ +namespace FluentCMS.Repositories.Postgres.Repositories; + +public class PermissionRepository(PostgresDbContext context) : SiteAssociatedRepository(context), IPermissionRepository, IService +{ + public async Task> Set(Guid siteId, Guid entityId, string entityTypeName, string action, IEnumerable roleIds, CancellationToken cancellationToken = default) + { + cancellationToken.ThrowIfCancellationRequested(); + + var existPermissions = await Table.Where(x => x.EntityId == entityId && x.EntityType == entityTypeName && x.Action == action).ToListAsync(cancellationToken: cancellationToken); + + await DeleteMany(existPermissions.Select(x => x.Id), cancellationToken); + + var permissions = roleIds.Select(x => new Permission + { + EntityType = entityTypeName, + Action = action, + EntityId = entityId, + RoleId = x, + SiteId = siteId + }).ToList(); + + if (permissions.Count == 0) + return []; + + return await CreateMany(permissions, cancellationToken); + } +} diff --git a/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Repositories/PluginContentRepository.cs b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Repositories/PluginContentRepository.cs new file mode 100644 index 000000000..ff7e306b7 --- /dev/null +++ b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Repositories/PluginContentRepository.cs @@ -0,0 +1,11 @@ +namespace FluentCMS.Repositories.Postgres.Repositories; + +public class PluginContentRepository(PostgresDbContext context) : SiteAssociatedRepository(context), IPluginContentRepository, IService +{ + + public async Task> GetByPluginId(Guid pluginId, CancellationToken cancellationToken = default) + { + cancellationToken.ThrowIfCancellationRequested(); + return await Table.Where(x => x.PluginId == pluginId).ToListAsync(cancellationToken: cancellationToken); + } +} diff --git a/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Repositories/PluginDefinitionRepository.cs b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Repositories/PluginDefinitionRepository.cs new file mode 100644 index 000000000..efe0fcf68 --- /dev/null +++ b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Repositories/PluginDefinitionRepository.cs @@ -0,0 +1,4 @@ +namespace FluentCMS.Repositories.Postgres.Repositories; + +public class PluginDefinitionRepository(PostgresDbContext context) : AuditableEntityRepository(context), IPluginDefinitionRepository, IService; + diff --git a/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Repositories/PluginRepository.cs b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Repositories/PluginRepository.cs new file mode 100644 index 000000000..d688939cc --- /dev/null +++ b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Repositories/PluginRepository.cs @@ -0,0 +1,43 @@ +namespace FluentCMS.Repositories.Postgres.Repositories; + +public class PluginRepository(PostgresDbContext context) : SiteAssociatedRepository(context), IPluginRepository, IService +{ + public async Task> GetByPageId(Guid pageId, CancellationToken cancellationToken = default) + { + cancellationToken.ThrowIfCancellationRequested(); + + return await Table.Where(x => x.PageId == pageId).ToListAsync(cancellationToken); + } + + public async Task UpdateOrder(Guid pluginId, string section, int order, CancellationToken cancellationToken = default) + { + cancellationToken.ThrowIfCancellationRequested(); + + var plugin = await GetById(pluginId, cancellationToken); + + if (plugin != null) + { + plugin.Order = order; + plugin.Section = section; + + return await Update(plugin, cancellationToken); + } + return default; + } + + public async Task UpdateCols(Guid pluginId, int cols, int colsMd, int colsLg, CancellationToken cancellationToken = default) + { + cancellationToken.ThrowIfCancellationRequested(); + + var plugin = await GetById(pluginId, cancellationToken); + + if (plugin != null) + { + plugin.Cols = cols; + plugin.ColsMd = colsMd; + plugin.ColsLg = colsLg; + return await Update(plugin, cancellationToken); + } + return default; + } +} diff --git a/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Repositories/RoleRepository.cs b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Repositories/RoleRepository.cs new file mode 100644 index 000000000..35e16f977 --- /dev/null +++ b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Repositories/RoleRepository.cs @@ -0,0 +1,5 @@ +namespace FluentCMS.Repositories.Postgres.Repositories; + +public class RoleRepository(PostgresDbContext context) : SiteAssociatedRepository(context), IRoleRepository, IService +{ +} diff --git a/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Repositories/SettingsRepository.cs b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Repositories/SettingsRepository.cs new file mode 100644 index 000000000..18940dcbf --- /dev/null +++ b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Repositories/SettingsRepository.cs @@ -0,0 +1,33 @@ +namespace FluentCMS.Repositories.Postgres.Repositories; + +public class SettingsRepository(PostgresDbContext postgresDbContext) : AuditableEntityRepository(postgresDbContext), ISettingsRepository, IService +{ + + public async Task Update(Guid entityId, Dictionary settings, CancellationToken cancellationToken = default) + { + cancellationToken.ThrowIfCancellationRequested(); + + var existing = await GetById(entityId, cancellationToken); + + if (existing != null) + { + + // add new settings to existing settings or update existing settings + foreach (var setting in settings) + existing.Values[setting.Key] = setting.Value; + + await Update(existing, cancellationToken); + return existing; + } + + var newSettings = new Settings + { + Id = entityId, + Values = settings + }; + await Create(newSettings, cancellationToken); + return newSettings; + } + + +} diff --git a/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Repositories/SiteAssociatedRepository.cs b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Repositories/SiteAssociatedRepository.cs new file mode 100644 index 000000000..31a1d1ca3 --- /dev/null +++ b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Repositories/SiteAssociatedRepository.cs @@ -0,0 +1,23 @@ +namespace FluentCMS.Repositories.Postgres.Repositories; + +public abstract class SiteAssociatedRepository(PostgresDbContext context) : AuditableEntityRepository(context), IService, ISiteAssociatedRepository where TEntity : SiteAssociatedEntity +{ + public override async Task Update(TEntity entity, CancellationToken cancellationToken = default) + { + cancellationToken.ThrowIfCancellationRequested(); + + var existing = await GetById(entity.Id, cancellationToken); + if (existing is null) + return default; + + entity.SiteId = existing.SiteId; + + return await base.Update(entity, cancellationToken); + } + + public async Task> GetAllForSite(Guid siteId, CancellationToken cancellationToken = default) + { + cancellationToken.ThrowIfCancellationRequested(); + return await Table.Where(x => x.SiteId == siteId).ToListAsync(cancellationToken); + } +} diff --git a/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Repositories/SiteRepository.cs b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Repositories/SiteRepository.cs new file mode 100644 index 000000000..4c57e32aa --- /dev/null +++ b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Repositories/SiteRepository.cs @@ -0,0 +1,11 @@ +namespace FluentCMS.Repositories.Postgres.Repositories; + +public class SiteRepository(PostgresDbContext context) : AuditableEntityRepository(context), ISiteRepository, IService +{ + public async Task GetByUrl(string url, CancellationToken cancellationToken = default) + { + cancellationToken.ThrowIfCancellationRequested(); + + return await GetByExpression(x => x.Urls.Contains(url),cancellationToken); + } +} diff --git a/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Repositories/UserRepository.cs b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Repositories/UserRepository.cs new file mode 100644 index 000000000..795b633ae --- /dev/null +++ b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Repositories/UserRepository.cs @@ -0,0 +1,113 @@ +using System.Security.Claims; + +namespace FluentCMS.Repositories.Postgres.Repositories; + +public class UserRepository : IUserRepository, IService +{ + readonly PostgresDbContext _context; + readonly DbSet _table; + + public UserRepository(PostgresDbContext context) + { + _context = context; + _table = context.Users; + } + public IQueryable AsQueryable() + { + return _table.AsQueryable(); + } + + public Task> GetUsersForClaim(Claim claim, CancellationToken cancellationToken = default) + { + cancellationToken.ThrowIfCancellationRequested(); + var users = AsQueryable().Where(u => u.Claims.Any(c => c.ClaimType == claim.Type && c.ClaimValue == claim.Value)).ToList(); + return Task.FromResult((IList)users); + } + + public Task FindByEmail(string normalizedEmail, CancellationToken cancellationToken = default) + { + cancellationToken.ThrowIfCancellationRequested(); + var user = AsQueryable().SingleOrDefault(x => x.NormalizedEmail == normalizedEmail); + return Task.FromResult(user); + } + + public Task FindByLogin(string loginProvider, string providerKey, CancellationToken cancellationToken = default) + { + cancellationToken.ThrowIfCancellationRequested(); + var user = AsQueryable().FirstOrDefault(user => user.Logins.Any(x => x.LoginProvider == loginProvider && x.ProviderKey == providerKey)); + return Task.FromResult(user); + } + + public Task FindByName(string normalizedUserName, CancellationToken cancellationToken = default) + { + cancellationToken.ThrowIfCancellationRequested(); + var user = AsQueryable().FirstOrDefault(x => x.NormalizedUserName == normalizedUserName); + return Task.FromResult(user); + } + + public async Task Create(User entity, CancellationToken cancellationToken = default) + { + cancellationToken.ThrowIfCancellationRequested(); + var result = await _table.AddAsync(entity, cancellationToken); + await _context.SaveChangesAsync(cancellationToken); + return result.Entity; + } + + public async Task> CreateMany(IEnumerable entities, CancellationToken cancellationToken = default) + { + var enumerable = entities.ToList(); + await _table.AddRangeAsync(enumerable, cancellationToken); + await _context.SaveChangesAsync(cancellationToken); + return enumerable; + } + + public async Task Update(User entity, CancellationToken cancellationToken = default) + { + cancellationToken.ThrowIfCancellationRequested(); + var result = _table.Update(entity); + await _context.SaveChangesAsync(cancellationToken); + return result.Entity; + } + + public async Task Delete(Guid id, CancellationToken cancellationToken = default) + { + cancellationToken.ThrowIfCancellationRequested(); + var entity = await GetById( id, cancellationToken); + if (entity == null) + { + return null; + } + + _table.Remove(entity); + await _context.SaveChangesAsync(cancellationToken); + + + return null; + } + + public async Task> DeleteMany(IEnumerable ids, CancellationToken cancellationToken = default) + { + cancellationToken.ThrowIfCancellationRequested(); + var entities = await GetByIds(ids, cancellationToken); + var entityIds = entities.Select(x => x.Id).ToList(); + await _table.Where(x => entityIds.Contains(x.Id)).ExecuteDeleteAsync(cancellationToken); + return entities; + } + + public async Task> GetAll(CancellationToken cancellationToken = default) + { + return await AsQueryable().ToListAsync(cancellationToken); + } + + public async Task GetById(Guid id, CancellationToken cancellationToken = default) + { + return await AsQueryable().SingleOrDefaultAsync(x => x.Id == id, cancellationToken); + } + + public async Task> GetByIds(IEnumerable ids, CancellationToken cancellationToken = default) + { + cancellationToken.ThrowIfCancellationRequested(); + var idsFilter = ids.ToList(); + return await _table.Where(x => idsFilter.Contains(x.Id)).ToListAsync(cancellationToken); + } +} diff --git a/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Repositories/UserRoleRepository.cs b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Repositories/UserRoleRepository.cs new file mode 100644 index 000000000..343ff7ed8 --- /dev/null +++ b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Repositories/UserRoleRepository.cs @@ -0,0 +1,22 @@ +namespace FluentCMS.Repositories.Postgres.Repositories; + +public class UserRoleRepository(PostgresDbContext context) : SiteAssociatedRepository(context), IUserRoleRepository, IService +{ + public async Task> GetUserRoles(Guid userId, Guid siteId, CancellationToken cancellationToken = default) + { + cancellationToken.ThrowIfCancellationRequested(); + return await GetAllByExpression(x => x.SiteId == siteId && x.UserId == userId, cancellationToken); + } + + public async Task> GetByRoleId(Guid roleId, CancellationToken cancellationToken = default) + { + cancellationToken.ThrowIfCancellationRequested(); + return await GetAllByExpression(x => x.RoleId == roleId, cancellationToken); + } + + public async Task> GetByUserId(Guid userId, CancellationToken cancellationToken = default) + { + cancellationToken.ThrowIfCancellationRequested(); + return await GetAllByExpression(x => x.UserId == userId, cancellationToken); + } +} diff --git a/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Workers/DatabaseMigrator.cs b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Workers/DatabaseMigrator.cs new file mode 100644 index 000000000..b35fdf888 --- /dev/null +++ b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/Workers/DatabaseMigrator.cs @@ -0,0 +1,29 @@ +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; + +namespace FluentCMS.Repositories.Postgres.Workers; + +public class DatabaseMigrator : BackgroundService +{ + readonly IServiceScope _scope; + readonly PostgresDbContext _context; + readonly ILogger _logger; + + public DatabaseMigrator(IServiceProvider serviceProvider, ILogger logger) + { + _scope = serviceProvider.CreateScope(); + _context = _scope.ServiceProvider.GetRequiredService(); + _logger = logger; + } + protected override async Task ExecuteAsync(CancellationToken stoppingToken) + { + await _context.Database.MigrateAsync(stoppingToken); + } + + public override void Dispose() + { + base.Dispose(); + _scope.Dispose(); + } +} diff --git a/src/Backend/Repositories/FluentCMS.Repositories.Postgres/add-migrations.ps1 b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/add-migrations.ps1 new file mode 100644 index 000000000..4dbd4a3b7 --- /dev/null +++ b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/add-migrations.ps1 @@ -0,0 +1,37 @@ +param( + [Parameter(Mandatory=$true)] + [string] + $MigrationName +) + +$startupProject = "./FluentCMS.Repositories.Postgres.csproj" +$project = "./FluentCMS.Repositories.Postgres.csproj" +$context = "PostgresDbContext" + + + +try { + + # Save the current directory + $originalDir = Get-Location + + # Set the scripts directory as the current directory + Set-Location -Path $PSScriptRoot + + dotnet tool update dotnet-ef -g + + # Generate migrations + $output = dotnet ef migrations add $MigrationName -o ./Migrations --context $context --startup-project $startupProject --project $project + Write-Output "Migrations generated. Output was: `n$output" + + # Generate SQL script from migrations + #$output = dotnet ef migrations script --project $project --context $context --output ./Data/sql/migrations.sql --idempotent + #Write-Output "Migration SQL script generated. Output was: `n$output" + + + # Restore the original directory + Set-Location -Path $originalDir +} catch { + Write-Output "Command failed. Error was: `n$_" +} + diff --git a/src/Backend/Repositories/FluentCMS.Repositories.Postgres/appsettings.json b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/appsettings.json new file mode 100644 index 000000000..ef9d31ec3 --- /dev/null +++ b/src/Backend/Repositories/FluentCMS.Repositories.Postgres/appsettings.json @@ -0,0 +1,6 @@ +{ + "COMMENT": "only needed to create migrations", + "ConnectionStrings": { + "PostgresDbContext": "Host=localhost;Database=fluentcms;Username=postgres;Password=postgres" + } +} diff --git a/src/FluentCMS/Dockerfile b/src/FluentCMS/Dockerfile new file mode 100644 index 000000000..fbc5457fa --- /dev/null +++ b/src/FluentCMS/Dockerfile @@ -0,0 +1,54 @@ +FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base +USER $APP_UID +WORKDIR /app +EXPOSE 8080 +EXPOSE 8081 + +FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build +ARG BUILD_CONFIGURATION=Release +WORKDIR /src +COPY ["FluentCMS/FluentCMS.csproj", "FluentCMS/"] +COPY ["Backend/FluentCMS.Web.Api/FluentCMS.Web.Api.csproj", "Backend/FluentCMS.Web.Api/"] +COPY ["Backend/FluentCMS.Services/FluentCMS.Services.csproj", "Backend/FluentCMS.Services/"] +COPY ["Providers/ApiTokenProviders/FluentCMS.Providers.ApiTokenProviders.Abstractions/FluentCMS.Providers.ApiTokenProviders.Abstractions.csproj", "Providers/ApiTokenProviders/FluentCMS.Providers.ApiTokenProviders.Abstractions/"] +COPY ["Providers/EmailProviders/FluentCMS.Providers.EmailProviders.Abstractions/FluentCMS.Providers.EmailProviders.Abstractions.csproj", "Providers/EmailProviders/FluentCMS.Providers.EmailProviders.Abstractions/"] +COPY ["Providers/FileStorageProviders/FluentCMS.Providers.FileStorageProviders.Abstractions/FluentCMS.Providers.FileStorageProviders.Abstractions.csproj", "Providers/FileStorageProviders/FluentCMS.Providers.FileStorageProviders.Abstractions/"] +COPY ["Providers/MessageBusProviders/FluentCMS.Providers.MessageBusProviders.Abstractions/FluentCMS.Providers.MessageBusProviders.Abstractions.csproj", "Providers/MessageBusProviders/FluentCMS.Providers.MessageBusProviders.Abstractions/"] +COPY ["Backend/FluentCMS.Identity/FluentCMS.Identity.csproj", "Backend/FluentCMS.Identity/"] +COPY ["Backend/Repositories/FluentCMS.Repositories.Abstractions/FluentCMS.Repositories.Abstractions.csproj", "Backend/Repositories/FluentCMS.Repositories.Abstractions/"] +COPY ["Backend/FluentCMS.Entities/FluentCMS.Entities.csproj", "Backend/FluentCMS.Entities/"] +COPY ["Shared/Shared.csproj", "Shared/"] +COPY ["Backend/Repositories/FluentCMS.Repositories.Caching/FluentCMS.Repositories.Caching.csproj", "Backend/Repositories/FluentCMS.Repositories.Caching/"] +COPY ["Providers/CacheProviders/FluentCMS.Providers.CacheProviders.Abstractions/FluentCMS.Providers.CacheProviders.Abstractions.csproj", "Providers/CacheProviders/FluentCMS.Providers.CacheProviders.Abstractions/"] +COPY ["Backend/Repositories/FluentCMS.Repositories.MongoDB/FluentCMS.Repositories.MongoDB.csproj", "Backend/Repositories/FluentCMS.Repositories.MongoDB/"] +COPY ["Backend/Repositories/FluentCMS.Repositories.LiteDb/FluentCMS.Repositories.LiteDb.csproj", "Backend/Repositories/FluentCMS.Repositories.LiteDb/"] +COPY ["Frontend/FluentCMS.Web.UI/FluentCMS.Web.UI.csproj", "Frontend/FluentCMS.Web.UI/"] +COPY ["Providers/TemplateRenderingProviders/FluentCMS.Providers.TemplateRenderingProviders.Abstractions/FluentCMS.Providers.TemplateRenderingProviders.Abstractions.csproj", "Providers/TemplateRenderingProviders/FluentCMS.Providers.TemplateRenderingProviders.Abstractions/"] +COPY ["Frontend/FluentCMS.Web.ApiClients/FluentCMS.Web.ApiClients.csproj", "Frontend/FluentCMS.Web.ApiClients/"] +COPY ["Frontend/FluentCMS.Web.UI.Components/FluentCMS.Web.UI.Components.csproj", "Frontend/FluentCMS.Web.UI.Components/"] +COPY ["Frontend/Plugins/FluentCMS.Web.Plugins.Contents.TextHTML/FluentCMS.Web.Plugins.Contents.TextHTML.csproj", "Frontend/Plugins/FluentCMS.Web.Plugins.Contents.TextHTML/"] +COPY ["Frontend/Plugins/FluentCMS.Web.Plugins.Base/FluentCMS.Web.Plugins.Base.csproj", "Frontend/Plugins/FluentCMS.Web.Plugins.Base/"] +COPY ["Frontend/Plugins/FluentCMS.Web.Plugins.Contents.Block/FluentCMS.Web.Plugins.Contents.Block.csproj", "Frontend/Plugins/FluentCMS.Web.Plugins.Contents.Block/"] +COPY ["Frontend/Plugins/FluentCMS.Web.Plugins.Contents.RichText/FluentCMS.Web.Plugins.Contents.RichText.csproj", "Frontend/Plugins/FluentCMS.Web.Plugins.Contents.RichText/"] +COPY ["Frontend/Plugins/FluentCMS.Web.Plugins.Contents.ContentViewer/FluentCMS.Web.Plugins.Contents.ContentViewer.csproj", "Frontend/Plugins/FluentCMS.Web.Plugins.Contents.ContentViewer/"] +COPY ["Frontend/Plugins/FluentCMS.Web.Plugins.Admin/FluentCMS.Web.Plugins.Admin.csproj", "Frontend/Plugins/FluentCMS.Web.Plugins.Admin/"] +COPY ["Providers/ApiTokenProviders/FluentCMS.Providers.ApiTokenProviders/FluentCMS.Providers.ApiTokenProviders.csproj", "Providers/ApiTokenProviders/FluentCMS.Providers.ApiTokenProviders/"] +COPY ["Providers/CacheProviders/FluentCMS.Providers.CacheProviders/FluentCMS.Providers.CacheProviders.csproj", "Providers/CacheProviders/FluentCMS.Providers.CacheProviders/"] +COPY ["Providers/EmailProviders/FluentCMS.Providers.EmailProviders/FluentCMS.Providers.EmailProviders.csproj", "Providers/EmailProviders/FluentCMS.Providers.EmailProviders/"] +COPY ["Providers/FileStorageProviders/FluentCMS.Providers.FileStorageProviders/FluentCMS.Providers.FileStorageProviders.csproj", "Providers/FileStorageProviders/FluentCMS.Providers.FileStorageProviders/"] +COPY ["Providers/MessageBusProviders/FluentCMS.Providers.MessageBusProviders/FluentCMS.Providers.MessageBusProviders.csproj", "Providers/MessageBusProviders/FluentCMS.Providers.MessageBusProviders/"] +COPY ["Providers/TemplateRenderingProviders/FluentCMS.Providers.TemplateRenderingProviders/FluentCMS.Providers.TemplateRenderingProviders.csproj", "Providers/TemplateRenderingProviders/FluentCMS.Providers.TemplateRenderingProviders/"] +COPY ["Backend/Repositories/FluentCMS.Repositories.Postgres/FluentCMS.Repositories.Postgres.csproj", "Backend/Repositories/FluentCMS.Repositories.Postgres/"] +RUN dotnet restore "FluentCMS/FluentCMS.csproj" +COPY . . +WORKDIR "/src/FluentCMS" +RUN dotnet build "FluentCMS.csproj" -c $BUILD_CONFIGURATION -o /app/build + +FROM build AS publish +ARG BUILD_CONFIGURATION=Release +RUN dotnet publish "FluentCMS.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false + +FROM base AS final +WORKDIR /app +COPY --from=publish /app/publish . +ENTRYPOINT ["dotnet", "FluentCMS.dll"] diff --git a/src/FluentCMS/FluentCMS.csproj b/src/FluentCMS/FluentCMS.csproj index ab548e33f..363e11e69 100644 --- a/src/FluentCMS/FluentCMS.csproj +++ b/src/FluentCMS/FluentCMS.csproj @@ -6,6 +6,7 @@ enable true 0.0.0.0 + Linux @@ -13,6 +14,7 @@ + diff --git a/src/FluentCMS/Program.cs b/src/FluentCMS/Program.cs index d4c117c8d..e7aaf059d 100644 --- a/src/FluentCMS/Program.cs +++ b/src/FluentCMS/Program.cs @@ -1,3 +1,5 @@ +using FluentCMS.Repositories.Postgres.Extensions; + var builder = WebApplication.CreateBuilder(args); #region Services @@ -10,11 +12,14 @@ services.AddCmsServices(configuration); // Use LiteDB as database -services.AddLiteDbRepositories("LiteDb"); +// services.AddLiteDbRepositories("LiteDb"); // Use MongoDB as database //services.AddMongoDbRepositories("MongoDb"); +// Use Postgres as database +services.AddPostgresDbRepositories("Postgres"); + // Enable caching for repository layer services.AddCachedRepositories(); diff --git a/src/FluentCMS/appsettings.json b/src/FluentCMS/appsettings.json index 8a1a2b80a..719045e08 100644 --- a/src/FluentCMS/appsettings.json +++ b/src/FluentCMS/appsettings.json @@ -1,39 +1,40 @@ { - "ClientSettings": { - "Url": "http://localhost:5000", - "Key": "" + "ClientSettings": { + "Url": "http://localhost:5000", + "Key": "xoZ4vCZLSNGHbQPQZZ2gnfE1aHfrEZtyBqPxfDEhxQc=:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYmYiOjE3Mjg5NDM0MjIsImV4cCI6MjA0NDQ3NjIyMiwiaWF0IjoxNzI4OTQzNDIyfQ.ZwCgciUcqbZPsJLuQevqI3D8c_8YnldpGMMSLxtc5Cc" + }, + "JwtOptions": { + "Issuer": "FluentCMS", + "Audience": "FluentCMS", + "Secret": "YOUR_SECRET_CHANGE_THIS_KEY", + "TokenExpiry": -1, + "RefreshTokenExpiry": -1 + }, + "ConnectionStrings": { + "LiteDb": "./LiteDb.db", + "MongoDb": "mongodb://localhost:27017/FluentCMS", + "Postgres": "Host=localhost;Port=5432;Database=fluentcms_db;Username=fluentcms_user;Password=fluentcms_password;Include Error Detail=True;" + }, + "Providers": { + "Email": { + "SmtpServerConfig": { + "Server": "sandbox.smtp.mailtrap.io", + "Port": 2525, + "Username": "33b3d4be6eff7c", + "Password": "3bc847fa1f6d59", + "EnableSsl": true, + "From": "admin@fluentcms.com" + } }, - "JwtOptions": { - "Issuer": "FluentCMS", - "Audience": "FluentCMS", - "Secret": "YOUR_SECRET_CHANGE_THIS_KEY", - "TokenExpiry": -1, - "RefreshTokenExpiry": -1 + "FileStorage": { + "FileStorageConfig": { + "Path": "files" + } }, - "ConnectionStrings": { - "LiteDb": "./LiteDb.db", - "MongoDb": "mongodb://localhost:27017/FluentCMS" - }, - "Providers": { - "Email": { - "SmtpServerConfig": { - "Server": "sandbox.smtp.mailtrap.io", - "Port": 2525, - "Username": "33b3d4be6eff7c", - "Password": "3bc847fa1f6d59", - "EnableSsl": true, - "From": "admin@fluentcms.com" - } - }, - "FileStorage": { - "FileStorageConfig": { - "Path": "files" - } - }, - "ApiToken": { - "JwtApiTokenConfig": { - "Secret": "YOUR_SECRET_KEY_SHOULD_BE_HERE!" - } - } + "ApiToken": { + "JwtApiTokenConfig": { + "Secret": "YOUR_SECRET_KEY_SHOULD_BE_HERE!" + } } -} + } +} \ No newline at end of file