diff --git a/modules/cms-kit/.gitattributes b/modules/cms-kit/.gitattributes
new file mode 100644
index 0000000000..c941e52669
--- /dev/null
+++ b/modules/cms-kit/.gitattributes
@@ -0,0 +1 @@
+**/wwwroot/libs/** linguist-vendored
diff --git a/modules/cms-kit/.gitignore b/modules/cms-kit/.gitignore
new file mode 100644
index 0000000000..e9589dd2d6
--- /dev/null
+++ b/modules/cms-kit/.gitignore
@@ -0,0 +1,258 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+
+# User-specific files
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+
+# Visual Studio 2015 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUNIT
+*.VisualState.xml
+TestResult.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# DNX
+project.lock.json
+artifacts/
+
+*_i.c
+*_p.c
+*_i.h
+*.ilk
+*.meta
+*.obj
+*.pch
+*.pdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# JustCode is a .NET coding add-in
+.JustCode
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# TODO: Comment the next line if you want to checkin your web deploy settings
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# The packages folder can be ignored because of Package Restore
+**/packages/*
+# except build/, which is used as an MSBuild target.
+!**/packages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/packages/repositories.config
+# NuGet v3's project.json files produces more ignoreable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.pfx
+*.publishsettings
+node_modules/
+orleans.codegen.cs
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+
+# SQL Server files
+*.mdf
+*.ldf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# JetBrains Rider
+.idea/
+*.sln.iml
+
+# CmsKit
+host/Volo.CmsKit.IdentityServer/Logs/logs.txt
+host/Volo.CmsKit.HttpApi.Host/Logs/logs.txt
+host/Volo.CmsKit.Web.Host/Logs/logs.txt
+host/Volo.CmsKit.Web.Unified/Logs/logs.txt
diff --git a/modules/cms-kit/Volo.CmsKit.sln b/modules/cms-kit/Volo.CmsKit.sln
new file mode 100644
index 0000000000..478e5c57e8
--- /dev/null
+++ b/modules/cms-kit/Volo.CmsKit.sln
@@ -0,0 +1,167 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.29001.49
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.CmsKit.Domain.Shared", "src\Volo.CmsKit.Domain.Shared\Volo.CmsKit.Domain.Shared.csproj", "{D64C1577-4929-4B60-939E-96DE1534891A}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.CmsKit.Domain", "src\Volo.CmsKit.Domain\Volo.CmsKit.Domain.csproj", "{F2840BC7-0188-4606-9126-DADD0F5ABF7A}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.CmsKit.Application.Contracts", "src\Volo.CmsKit.Application.Contracts\Volo.CmsKit.Application.Contracts.csproj", "{BD65D04F-08D5-40C1-8C24-77CA0BACB877}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.CmsKit.Application", "src\Volo.CmsKit.Application\Volo.CmsKit.Application.csproj", "{78040F9E-3501-4A40-82DF-00A597710F35}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{649A3FFA-182F-4E56-9717-E6A9A2BEC545}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{CCD2960C-23CC-4AB4-B84D-60C7AAA52F4D}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "host", "host", "{E400416D-2895-4512-9D17-90681EEC7E0A}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.CmsKit.EntityFrameworkCore", "src\Volo.CmsKit.EntityFrameworkCore\Volo.CmsKit.EntityFrameworkCore.csproj", "{0CE86223-D31D-4315-A1F5-87BA3EE1B844}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.CmsKit.MongoDB", "src\Volo.CmsKit.MongoDB\Volo.CmsKit.MongoDB.csproj", "{F1C58097-4C08-4D88-8976-6B3389391481}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.CmsKit.HttpApi", "src\Volo.CmsKit.HttpApi\Volo.CmsKit.HttpApi.csproj", "{077AA5F8-8B61-420C-A6B5-0150A66FDB34}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.CmsKit.HttpApi.Client", "src\Volo.CmsKit.HttpApi.Client\Volo.CmsKit.HttpApi.Client.csproj", "{36E2735F-CEAB-44C8-A6D1-2CDAFF399751}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.CmsKit.TestBase", "test\Volo.CmsKit.TestBase\Volo.CmsKit.TestBase.csproj", "{C5BB573D-3030-4BCB-88B7-F6A85C32766C}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.CmsKit.EntityFrameworkCore.Tests", "test\Volo.CmsKit.EntityFrameworkCore.Tests\Volo.CmsKit.EntityFrameworkCore.Tests.csproj", "{527F645C-C1FC-406E-8479-81386C8ECF13}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.CmsKit.MongoDB.Tests", "test\Volo.CmsKit.MongoDB.Tests\Volo.CmsKit.MongoDB.Tests.csproj", "{D0AD9179-125C-40B2-A8EE-CD4C1EE24BB6}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.CmsKit.Domain.Tests", "test\Volo.CmsKit.Domain.Tests\Volo.CmsKit.Domain.Tests.csproj", "{E60895E5-79C4-447D-88B7-85CB5BA336A4}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.CmsKit.Application.Tests", "test\Volo.CmsKit.Application.Tests\Volo.CmsKit.Application.Tests.csproj", "{90CB5DC4-C040-45C7-8900-9688B26405BC}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.CmsKit.HttpApi.Host", "host\Volo.CmsKit.HttpApi.Host\Volo.CmsKit.HttpApi.Host.csproj", "{37B135B0-DAFE-4616-B25C-1BDF32FC44A2}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.CmsKit.Web", "src\Volo.CmsKit.Web\Volo.CmsKit.Web.csproj", "{3B7B6317-1B85-4164-8E11-75574F80AE17}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.CmsKit.HttpApi.Client.ConsoleTestApp", "test\Volo.CmsKit.HttpApi.Client.ConsoleTestApp\Volo.CmsKit.HttpApi.Client.ConsoleTestApp.csproj", "{1EDCD6D4-DF3A-4E3B-ABB6-C0D0B373EAB8}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.CmsKit.Web.Host", "host\Volo.CmsKit.Web.Host\Volo.CmsKit.Web.Host.csproj", "{73513786-B6C6-4A21-89C5-0FBDD0A46107}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.CmsKit.IdentityServer", "host\Volo.CmsKit.IdentityServer\Volo.CmsKit.IdentityServer.csproj", "{690203F4-3CD5-4569-88D9-EE831EEA5F5F}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.CmsKit.Host.Shared", "host\Volo.CmsKit.Host.Shared\Volo.CmsKit.Host.Shared.csproj", "{F6AC8D4A-EDD7-4514-8E8A-5BCB019864DB}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.CmsKit.Web.Unified", "host\Volo.CmsKit.Web.Unified\Volo.CmsKit.Web.Unified.csproj", "{3D872C41-E226-45C8-89C1-9D3DBD7C73F2}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {D64C1577-4929-4B60-939E-96DE1534891A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {D64C1577-4929-4B60-939E-96DE1534891A}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {D64C1577-4929-4B60-939E-96DE1534891A}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {D64C1577-4929-4B60-939E-96DE1534891A}.Release|Any CPU.Build.0 = Release|Any CPU
+ {F2840BC7-0188-4606-9126-DADD0F5ABF7A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {F2840BC7-0188-4606-9126-DADD0F5ABF7A}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {F2840BC7-0188-4606-9126-DADD0F5ABF7A}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {F2840BC7-0188-4606-9126-DADD0F5ABF7A}.Release|Any CPU.Build.0 = Release|Any CPU
+ {BD65D04F-08D5-40C1-8C24-77CA0BACB877}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {BD65D04F-08D5-40C1-8C24-77CA0BACB877}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {BD65D04F-08D5-40C1-8C24-77CA0BACB877}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {BD65D04F-08D5-40C1-8C24-77CA0BACB877}.Release|Any CPU.Build.0 = Release|Any CPU
+ {78040F9E-3501-4A40-82DF-00A597710F35}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {78040F9E-3501-4A40-82DF-00A597710F35}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {78040F9E-3501-4A40-82DF-00A597710F35}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {78040F9E-3501-4A40-82DF-00A597710F35}.Release|Any CPU.Build.0 = Release|Any CPU
+ {0CE86223-D31D-4315-A1F5-87BA3EE1B844}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {0CE86223-D31D-4315-A1F5-87BA3EE1B844}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {0CE86223-D31D-4315-A1F5-87BA3EE1B844}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {0CE86223-D31D-4315-A1F5-87BA3EE1B844}.Release|Any CPU.Build.0 = Release|Any CPU
+ {F1C58097-4C08-4D88-8976-6B3389391481}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {F1C58097-4C08-4D88-8976-6B3389391481}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {F1C58097-4C08-4D88-8976-6B3389391481}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {F1C58097-4C08-4D88-8976-6B3389391481}.Release|Any CPU.Build.0 = Release|Any CPU
+ {077AA5F8-8B61-420C-A6B5-0150A66FDB34}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {077AA5F8-8B61-420C-A6B5-0150A66FDB34}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {077AA5F8-8B61-420C-A6B5-0150A66FDB34}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {077AA5F8-8B61-420C-A6B5-0150A66FDB34}.Release|Any CPU.Build.0 = Release|Any CPU
+ {36E2735F-CEAB-44C8-A6D1-2CDAFF399751}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {36E2735F-CEAB-44C8-A6D1-2CDAFF399751}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {36E2735F-CEAB-44C8-A6D1-2CDAFF399751}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {36E2735F-CEAB-44C8-A6D1-2CDAFF399751}.Release|Any CPU.Build.0 = Release|Any CPU
+ {C5BB573D-3030-4BCB-88B7-F6A85C32766C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {C5BB573D-3030-4BCB-88B7-F6A85C32766C}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {C5BB573D-3030-4BCB-88B7-F6A85C32766C}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {C5BB573D-3030-4BCB-88B7-F6A85C32766C}.Release|Any CPU.Build.0 = Release|Any CPU
+ {527F645C-C1FC-406E-8479-81386C8ECF13}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {527F645C-C1FC-406E-8479-81386C8ECF13}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {527F645C-C1FC-406E-8479-81386C8ECF13}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {527F645C-C1FC-406E-8479-81386C8ECF13}.Release|Any CPU.Build.0 = Release|Any CPU
+ {D0AD9179-125C-40B2-A8EE-CD4C1EE24BB6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {D0AD9179-125C-40B2-A8EE-CD4C1EE24BB6}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {D0AD9179-125C-40B2-A8EE-CD4C1EE24BB6}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {D0AD9179-125C-40B2-A8EE-CD4C1EE24BB6}.Release|Any CPU.Build.0 = Release|Any CPU
+ {E60895E5-79C4-447D-88B7-85CB5BA336A4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {E60895E5-79C4-447D-88B7-85CB5BA336A4}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {E60895E5-79C4-447D-88B7-85CB5BA336A4}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {E60895E5-79C4-447D-88B7-85CB5BA336A4}.Release|Any CPU.Build.0 = Release|Any CPU
+ {90CB5DC4-C040-45C7-8900-9688B26405BC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {90CB5DC4-C040-45C7-8900-9688B26405BC}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {90CB5DC4-C040-45C7-8900-9688B26405BC}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {90CB5DC4-C040-45C7-8900-9688B26405BC}.Release|Any CPU.Build.0 = Release|Any CPU
+ {37B135B0-DAFE-4616-B25C-1BDF32FC44A2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {37B135B0-DAFE-4616-B25C-1BDF32FC44A2}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {37B135B0-DAFE-4616-B25C-1BDF32FC44A2}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {37B135B0-DAFE-4616-B25C-1BDF32FC44A2}.Release|Any CPU.Build.0 = Release|Any CPU
+ {3B7B6317-1B85-4164-8E11-75574F80AE17}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {3B7B6317-1B85-4164-8E11-75574F80AE17}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {3B7B6317-1B85-4164-8E11-75574F80AE17}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {3B7B6317-1B85-4164-8E11-75574F80AE17}.Release|Any CPU.Build.0 = Release|Any CPU
+ {1EDCD6D4-DF3A-4E3B-ABB6-C0D0B373EAB8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {1EDCD6D4-DF3A-4E3B-ABB6-C0D0B373EAB8}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {1EDCD6D4-DF3A-4E3B-ABB6-C0D0B373EAB8}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {1EDCD6D4-DF3A-4E3B-ABB6-C0D0B373EAB8}.Release|Any CPU.Build.0 = Release|Any CPU
+ {73513786-B6C6-4A21-89C5-0FBDD0A46107}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {73513786-B6C6-4A21-89C5-0FBDD0A46107}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {73513786-B6C6-4A21-89C5-0FBDD0A46107}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {73513786-B6C6-4A21-89C5-0FBDD0A46107}.Release|Any CPU.Build.0 = Release|Any CPU
+ {690203F4-3CD5-4569-88D9-EE831EEA5F5F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {690203F4-3CD5-4569-88D9-EE831EEA5F5F}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {690203F4-3CD5-4569-88D9-EE831EEA5F5F}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {690203F4-3CD5-4569-88D9-EE831EEA5F5F}.Release|Any CPU.Build.0 = Release|Any CPU
+ {F6AC8D4A-EDD7-4514-8E8A-5BCB019864DB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {F6AC8D4A-EDD7-4514-8E8A-5BCB019864DB}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {F6AC8D4A-EDD7-4514-8E8A-5BCB019864DB}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {F6AC8D4A-EDD7-4514-8E8A-5BCB019864DB}.Release|Any CPU.Build.0 = Release|Any CPU
+ {3D872C41-E226-45C8-89C1-9D3DBD7C73F2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {3D872C41-E226-45C8-89C1-9D3DBD7C73F2}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {3D872C41-E226-45C8-89C1-9D3DBD7C73F2}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {3D872C41-E226-45C8-89C1-9D3DBD7C73F2}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(NestedProjects) = preSolution
+ {D64C1577-4929-4B60-939E-96DE1534891A} = {649A3FFA-182F-4E56-9717-E6A9A2BEC545}
+ {F2840BC7-0188-4606-9126-DADD0F5ABF7A} = {649A3FFA-182F-4E56-9717-E6A9A2BEC545}
+ {BD65D04F-08D5-40C1-8C24-77CA0BACB877} = {649A3FFA-182F-4E56-9717-E6A9A2BEC545}
+ {78040F9E-3501-4A40-82DF-00A597710F35} = {649A3FFA-182F-4E56-9717-E6A9A2BEC545}
+ {0CE86223-D31D-4315-A1F5-87BA3EE1B844} = {649A3FFA-182F-4E56-9717-E6A9A2BEC545}
+ {F1C58097-4C08-4D88-8976-6B3389391481} = {649A3FFA-182F-4E56-9717-E6A9A2BEC545}
+ {077AA5F8-8B61-420C-A6B5-0150A66FDB34} = {649A3FFA-182F-4E56-9717-E6A9A2BEC545}
+ {36E2735F-CEAB-44C8-A6D1-2CDAFF399751} = {649A3FFA-182F-4E56-9717-E6A9A2BEC545}
+ {C5BB573D-3030-4BCB-88B7-F6A85C32766C} = {CCD2960C-23CC-4AB4-B84D-60C7AAA52F4D}
+ {527F645C-C1FC-406E-8479-81386C8ECF13} = {CCD2960C-23CC-4AB4-B84D-60C7AAA52F4D}
+ {D0AD9179-125C-40B2-A8EE-CD4C1EE24BB6} = {CCD2960C-23CC-4AB4-B84D-60C7AAA52F4D}
+ {E60895E5-79C4-447D-88B7-85CB5BA336A4} = {CCD2960C-23CC-4AB4-B84D-60C7AAA52F4D}
+ {90CB5DC4-C040-45C7-8900-9688B26405BC} = {CCD2960C-23CC-4AB4-B84D-60C7AAA52F4D}
+ {37B135B0-DAFE-4616-B25C-1BDF32FC44A2} = {E400416D-2895-4512-9D17-90681EEC7E0A}
+ {3B7B6317-1B85-4164-8E11-75574F80AE17} = {649A3FFA-182F-4E56-9717-E6A9A2BEC545}
+ {1EDCD6D4-DF3A-4E3B-ABB6-C0D0B373EAB8} = {CCD2960C-23CC-4AB4-B84D-60C7AAA52F4D}
+ {73513786-B6C6-4A21-89C5-0FBDD0A46107} = {E400416D-2895-4512-9D17-90681EEC7E0A}
+ {690203F4-3CD5-4569-88D9-EE831EEA5F5F} = {E400416D-2895-4512-9D17-90681EEC7E0A}
+ {F6AC8D4A-EDD7-4514-8E8A-5BCB019864DB} = {E400416D-2895-4512-9D17-90681EEC7E0A}
+ {3D872C41-E226-45C8-89C1-9D3DBD7C73F2} = {E400416D-2895-4512-9D17-90681EEC7E0A}
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {4324B3B4-B60B-4E3C-91D8-59576B4E26DD}
+ EndGlobalSection
+EndGlobal
diff --git a/modules/cms-kit/Volo.CmsKit.sln.DotSettings b/modules/cms-kit/Volo.CmsKit.sln.DotSettings
new file mode 100644
index 0000000000..cb0b2c919f
--- /dev/null
+++ b/modules/cms-kit/Volo.CmsKit.sln.DotSettings
@@ -0,0 +1,23 @@
+
+ True
+ WARNING
+ WARNING
+ WARNING
+ WARNING
+ WARNING
+ WARNING
+ WARNING
+ WARNING
+ Required
+ Required
+ Required
+ Required
+ False
+ True
+ False
+ False
+ True
+ False
+ False
+ SQL
+
\ No newline at end of file
diff --git a/modules/cms-kit/angular/.editorconfig b/modules/cms-kit/angular/.editorconfig
new file mode 100644
index 0000000000..59d9a3a3e7
--- /dev/null
+++ b/modules/cms-kit/angular/.editorconfig
@@ -0,0 +1,16 @@
+# Editor configuration, see https://editorconfig.org
+root = true
+
+[*]
+charset = utf-8
+indent_style = space
+indent_size = 2
+insert_final_newline = true
+trim_trailing_whitespace = true
+
+[*.ts]
+quote_type = single
+
+[*.md]
+max_line_length = off
+trim_trailing_whitespace = false
diff --git a/modules/cms-kit/angular/.gitignore b/modules/cms-kit/angular/.gitignore
new file mode 100644
index 0000000000..a8e3c659a1
--- /dev/null
+++ b/modules/cms-kit/angular/.gitignore
@@ -0,0 +1,48 @@
+# See http://help.github.com/ignore-files/ for more about ignoring files.
+
+# compiled output
+/dist
+/tmp
+/out-tsc
+# Only exists if Bazel was run
+/bazel-out
+
+# dependencies
+/node_modules
+
+# profiling files
+chrome-profiler-events*.json
+speed-measure-plugin*.json
+
+# IDEs and editors
+/.idea
+.project
+.classpath
+.c9/
+*.launch
+.settings/
+*.sublime-workspace
+
+# IDE - VSCode
+.vscode/*
+!.vscode/settings.json
+!.vscode/tasks.json
+!.vscode/launch.json
+!.vscode/extensions.json
+.history/*
+
+# misc
+/.sass-cache
+/connect.lock
+/coverage
+/libpeerconnection.log
+npm-debug.log
+yarn-error.log
+testem.log
+/typings
+
+# System Files
+.DS_Store
+Thumbs.db
+
+yarn.lock
\ No newline at end of file
diff --git a/modules/cms-kit/angular/README.md b/modules/cms-kit/angular/README.md
new file mode 100644
index 0000000000..38d90cb368
--- /dev/null
+++ b/modules/cms-kit/angular/README.md
@@ -0,0 +1,27 @@
+# CmsKit
+
+This is a startup project based on the ABP framework. For more information, visit abp.io
+
+## Development server
+
+Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files.
+
+## Code scaffolding
+
+Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`.
+
+## Build
+
+Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. Use the `--prod` flag for a production build.
+
+## Running unit tests
+
+Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io).
+
+## Running end-to-end tests
+
+Run `ng e2e` to execute the end-to-end tests via [Protractor](http://www.protractortest.org/).
+
+## Further help
+
+To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md).
diff --git a/modules/cms-kit/angular/angular.json b/modules/cms-kit/angular/angular.json
new file mode 100644
index 0000000000..b5692b9aec
--- /dev/null
+++ b/modules/cms-kit/angular/angular.json
@@ -0,0 +1,202 @@
+{
+ "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
+ "version": 1,
+ "newProjectRoot": "projects",
+ "projects": {
+ "cms-kit": {
+ "projectType": "library",
+ "root": "projects/cms-kit",
+ "sourceRoot": "projects/cms-kit/src",
+ "prefix": "lib",
+ "architect": {
+ "build": {
+ "builder": "@angular-devkit/build-ng-packagr:build",
+ "options": {
+ "tsConfig": "projects/cms-kit/tsconfig.lib.json",
+ "project": "projects/cms-kit/ng-package.json"
+ },
+ "configurations": {
+ "production": {
+ "tsConfig": "projects/cms-kit/tsconfig.lib.prod.json"
+ }
+ }
+ },
+ "test": {
+ "builder": "@angular-devkit/build-angular:karma",
+ "options": {
+ "main": "projects/cms-kit/src/test.ts",
+ "tsConfig": "projects/cms-kit/tsconfig.spec.json",
+ "karmaConfig": "projects/cms-kit/karma.conf.js"
+ }
+ },
+ "lint": {
+ "builder": "@angular-devkit/build-angular:tslint",
+ "options": {
+ "tsConfig": [
+ "projects/cms-kit/tsconfig.lib.json",
+ "projects/cms-kit/tsconfig.spec.json"
+ ],
+ "exclude": ["**/node_modules/**"]
+ }
+ }
+ }
+ },
+ "dev-app": {
+ "projectType": "application",
+ "schematics": {
+ "@schematics/angular:component": {
+ "style": "scss"
+ }
+ },
+ "root": "projects/dev-app",
+ "sourceRoot": "projects/dev-app/src",
+ "prefix": "app",
+ "architect": {
+ "build": {
+ "builder": "@angular-devkit/build-angular:browser",
+ "options": {
+ "outputPath": "dist/dev-app",
+ "index": "projects/dev-app/src/index.html",
+ "main": "projects/dev-app/src/main.ts",
+ "polyfills": "projects/dev-app/src/polyfills.ts",
+ "tsConfig": "projects/dev-app/tsconfig.app.json",
+ "aot": true,
+ "assets": [
+ "projects/dev-app/src/favicon.ico",
+ "projects/dev-app/src/assets"
+ ],
+ "styles": [
+ {
+ "input": "node_modules/@fortawesome/fontawesome-free/css/all.min.css",
+ "inject": true,
+ "bundleName": "fontawesome-all.min"
+ },
+ {
+ "input": "node_modules/@fortawesome/fontawesome-free/css/v4-shims.min.css",
+ "inject": true,
+ "bundleName": "fontawesome-v4-shims.min"
+ },
+ {
+ "input": "node_modules/@swimlane/ngx-datatable/index.css",
+ "inject": true,
+ "bundleName": "ngx-datatable-index"
+ },
+ {
+ "input": "node_modules/@swimlane/ngx-datatable/assets/icons.css",
+ "inject": true,
+ "bundleName": "ngx-datatable-icons"
+ },
+ {
+ "input": "node_modules/@swimlane/ngx-datatable/themes/material.css",
+ "inject": true,
+ "bundleName": "ngx-datatable-material"
+ },
+ {
+ "input": "node_modules/@abp/ng.theme.shared/styles/bootstrap-rtl.min.css",
+ "inject": false,
+ "bundleName": "bootstrap-rtl.min"
+ },
+ {
+ "input": "node_modules/bootstrap/dist/css/bootstrap.min.css",
+ "inject": true,
+ "bundleName": "bootstrap-ltr.min"
+ },
+ "projects/dev-app/src/styles.scss"
+ ],
+ "scripts": []
+ },
+ "configurations": {
+ "production": {
+ "tsConfig": "projects/dev-app/tsconfig.prod.json",
+ "fileReplacements": [
+ {
+ "replace": "projects/dev-app/src/environments/environment.ts",
+ "with": "projects/dev-app/src/environments/environment.prod.ts"
+ }
+ ],
+ "optimization": true,
+ "outputHashing": "all",
+ "sourceMap": false,
+ "extractCss": true,
+ "namedChunks": false,
+ "extractLicenses": true,
+ "vendorChunk": false,
+ "buildOptimizer": true,
+ "budgets": [
+ {
+ "type": "initial",
+ "maximumWarning": "2mb",
+ "maximumError": "5mb"
+ },
+ {
+ "type": "anyComponentStyle",
+ "maximumWarning": "6kb",
+ "maximumError": "10kb"
+ }
+ ]
+ }
+ }
+ },
+ "serve": {
+ "builder": "@angular-devkit/build-angular:dev-server",
+ "options": {
+ "browserTarget": "dev-app:build"
+ },
+ "configurations": {
+ "production": {
+ "browserTarget": "dev-app:build:production"
+ }
+ }
+ },
+ "extract-i18n": {
+ "builder": "@angular-devkit/build-angular:extract-i18n",
+ "options": {
+ "browserTarget": "dev-app:build"
+ }
+ },
+ "test": {
+ "builder": "@angular-devkit/build-angular:karma",
+ "options": {
+ "main": "projects/dev-app/src/test.ts",
+ "polyfills": "projects/dev-app/src/polyfills.ts",
+ "tsConfig": "projects/dev-app/tsconfig.spec.json",
+ "karmaConfig": "projects/dev-app/karma.conf.js",
+ "assets": [
+ "projects/dev-app/src/favicon.ico",
+ "projects/dev-app/src/assets"
+ ],
+ "styles": ["projects/dev-app/src/styles.scss"],
+ "scripts": []
+ }
+ },
+ "lint": {
+ "builder": "@angular-devkit/build-angular:tslint",
+ "options": {
+ "tsConfig": [
+ "projects/dev-app/tsconfig.app.json",
+ "projects/dev-app/tsconfig.spec.json",
+ "projects/dev-app/e2e/tsconfig.json"
+ ],
+ "exclude": ["**/node_modules/**"]
+ }
+ },
+ "e2e": {
+ "builder": "@angular-devkit/build-angular:protractor",
+ "options": {
+ "protractorConfig": "projects/dev-app/e2e/protractor.conf.js",
+ "devServerTarget": "dev-app:serve"
+ },
+ "configurations": {
+ "production": {
+ "devServerTarget": "dev-app:serve:production"
+ }
+ }
+ }
+ }
+ }
+ },
+ "cli": {
+ "analytics": false
+ },
+ "defaultProject": "dev-app"
+}
diff --git a/modules/cms-kit/angular/package.json b/modules/cms-kit/angular/package.json
new file mode 100644
index 0000000000..f162ebd366
--- /dev/null
+++ b/modules/cms-kit/angular/package.json
@@ -0,0 +1,58 @@
+{
+ "name": "cms-kit",
+ "version": "0.0.0",
+ "scripts": {
+ "ng": "ng",
+ "start": "ng serve dev-app --open",
+ "build": "ng build cms-kit --prod",
+ "build:app": "npm run symlink:copy -- --no-watch && ng build dev-app --prod",
+ "symlink:copy": "symlink copy --angular --packages @my-company-name/cms-kit --prod",
+ "test": "ng test",
+ "lint": "ng lint",
+ "e2e": "ng e2e",
+ "compile:ivy": "yarn ngcc --properties es2015 browser module main --first-only --create-ivy-entry-points --tsconfig './tsconfig.prod.json' --source node_modules --async false",
+ "postinstall": "npm run compile:ivy"
+ },
+ "private": true,
+ "dependencies": {
+ "@abp/ng.account": "~3.0.3",
+ "@abp/ng.identity": "~3.0.3",
+ "@abp/ng.setting-management": "~3.0.3",
+ "@abp/ng.tenant-management": "~3.0.3",
+ "@abp/ng.theme.basic": "~3.0.3",
+ "@angular/animations": "~10.0.0",
+ "@angular/common": "~10.0.0",
+ "@angular/compiler": "~10.0.0",
+ "@angular/core": "~10.0.0",
+ "@angular/forms": "~10.0.0",
+ "@angular/platform-browser": "~10.0.0",
+ "@angular/platform-browser-dynamic": "~10.0.0",
+ "@angular/router": "~10.0.0",
+ "rxjs": "~6.5.4",
+ "tslib": "^2.0.0",
+ "zone.js": "~0.10.2"
+ },
+ "devDependencies": {
+ "@angular-devkit/build-angular": "~0.1000.0",
+ "@angular-devkit/build-ng-packagr": "~0.1000.0",
+ "@angular/cli": "~10.0.0",
+ "@angular/compiler-cli": "~10.0.0",
+ "@types/jasmine": "~3.5.0",
+ "@types/jasminewd2": "~2.0.3",
+ "@types/node": "^12.11.1",
+ "codelyzer": "^5.1.2",
+ "jasmine-core": "~3.5.0",
+ "jasmine-spec-reporter": "~5.0.0",
+ "karma": "~5.0.0",
+ "karma-chrome-launcher": "~3.1.0",
+ "karma-coverage-istanbul-reporter": "~3.0.2",
+ "karma-jasmine": "~3.3.0",
+ "karma-jasmine-html-reporter": "^1.5.0",
+ "ng-packagr": "^10.0.0",
+ "protractor": "~7.0.0",
+ "symlink-manager": "^1.5.0",
+ "ts-node": "~8.3.0",
+ "tslint": "~6.1.0",
+ "typescript": "~3.9.5"
+ }
+}
\ No newline at end of file
diff --git a/modules/cms-kit/angular/projects/cms-kit/README.md b/modules/cms-kit/angular/projects/cms-kit/README.md
new file mode 100644
index 0000000000..4174520f2c
--- /dev/null
+++ b/modules/cms-kit/angular/projects/cms-kit/README.md
@@ -0,0 +1,24 @@
+# CmsKit
+
+This is a startup project based on the ABP framework. For more information, visit abp.io Note: Don't forget to add `--project cms-kit` or else it will be added to the default project in your `angular.json` file.
+
+## Build
+
+Run `ng build cms-kit` to build the project. The build artifacts will be stored in the `dist/` directory.
+
+## Publishing
+
+After building your library with `ng build cms-kit`, go to the dist folder `cd dist/cms-kit` and run `npm publish`.
+
+## Running unit tests
+
+Run `ng test cms-kit` to execute the unit tests via [Karma](https://karma-runner.github.io).
+
+## Further help
+
+To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md).
diff --git a/modules/cms-kit/angular/projects/cms-kit/config/ng-package.json b/modules/cms-kit/angular/projects/cms-kit/config/ng-package.json
new file mode 100644
index 0000000000..c2e5f0483f
--- /dev/null
+++ b/modules/cms-kit/angular/projects/cms-kit/config/ng-package.json
@@ -0,0 +1,7 @@
+{
+ "$schema": "../../../node_modules/ng-packagr/ng-package.schema.json",
+ "dest": "../../dist/cms-kit/config",
+ "lib": {
+ "entryFile": "src/public-api.ts"
+ }
+}
diff --git a/modules/cms-kit/angular/projects/cms-kit/config/src/cms-kit-config.module.ts b/modules/cms-kit/angular/projects/cms-kit/config/src/cms-kit-config.module.ts
new file mode 100644
index 0000000000..6f20218868
--- /dev/null
+++ b/modules/cms-kit/angular/projects/cms-kit/config/src/cms-kit-config.module.ts
@@ -0,0 +1,12 @@
+import { ModuleWithProviders, NgModule } from '@angular/core';
+import { MY_PROJECT_NAME_ROUTE_PROVIDERS } from './providers/route.provider';
+
+@NgModule()
+export class CmsKitConfigModule {
+ static forRoot(): ModuleWithProviders {
+ return {
+ ngModule: CmsKitConfigModule,
+ providers: [MY_PROJECT_NAME_ROUTE_PROVIDERS],
+ };
+ }
+}
diff --git a/modules/cms-kit/angular/projects/cms-kit/config/src/enums/index.ts b/modules/cms-kit/angular/projects/cms-kit/config/src/enums/index.ts
new file mode 100644
index 0000000000..3bda94b078
--- /dev/null
+++ b/modules/cms-kit/angular/projects/cms-kit/config/src/enums/index.ts
@@ -0,0 +1 @@
+export * from './route-names';
diff --git a/modules/cms-kit/angular/projects/cms-kit/config/src/enums/route-names.ts b/modules/cms-kit/angular/projects/cms-kit/config/src/enums/route-names.ts
new file mode 100644
index 0000000000..c05735b0ec
--- /dev/null
+++ b/modules/cms-kit/angular/projects/cms-kit/config/src/enums/route-names.ts
@@ -0,0 +1,3 @@
+export const enum eCmsKitRouteNames {
+ CmsKit = 'CmsKit',
+}
diff --git a/modules/cms-kit/angular/projects/cms-kit/config/src/providers/index.ts b/modules/cms-kit/angular/projects/cms-kit/config/src/providers/index.ts
new file mode 100644
index 0000000000..fe08efba8c
--- /dev/null
+++ b/modules/cms-kit/angular/projects/cms-kit/config/src/providers/index.ts
@@ -0,0 +1 @@
+export * from './route.provider';
diff --git a/modules/cms-kit/angular/projects/cms-kit/config/src/providers/route.provider.ts b/modules/cms-kit/angular/projects/cms-kit/config/src/providers/route.provider.ts
new file mode 100644
index 0000000000..2fa8ce1bb8
--- /dev/null
+++ b/modules/cms-kit/angular/projects/cms-kit/config/src/providers/route.provider.ts
@@ -0,0 +1,27 @@
+import { eLayoutType, RoutesService } from '@abp/ng.core';
+import { eThemeSharedRouteNames } from '@abp/ng.theme.shared';
+import { APP_INITIALIZER } from '@angular/core';
+import { eCmsKitRouteNames } from '../enums/route-names';
+
+export const MY_PROJECT_NAME_ROUTE_PROVIDERS = [
+ {
+ provide: APP_INITIALIZER,
+ useFactory: configureRoutes,
+ deps: [RoutesService],
+ multi: true,
+ },
+];
+
+export function configureRoutes(routes: RoutesService) {
+ return () => {
+ routes.add([
+ {
+ path: '/cms-kit',
+ name: eCmsKitRouteNames.CmsKit,
+ iconClass: 'fas fa-book',
+ layout: eLayoutType.application,
+ order: 3,
+ },
+ ]);
+ };
+}
diff --git a/modules/cms-kit/angular/projects/cms-kit/config/src/public-api.ts b/modules/cms-kit/angular/projects/cms-kit/config/src/public-api.ts
new file mode 100644
index 0000000000..a77eadc283
--- /dev/null
+++ b/modules/cms-kit/angular/projects/cms-kit/config/src/public-api.ts
@@ -0,0 +1,3 @@
+export * from './enums';
+export * from './cms-kit-config.module';
+export * from './providers';
diff --git a/modules/cms-kit/angular/projects/cms-kit/karma.conf.js b/modules/cms-kit/angular/projects/cms-kit/karma.conf.js
new file mode 100644
index 0000000000..5a1214c588
--- /dev/null
+++ b/modules/cms-kit/angular/projects/cms-kit/karma.conf.js
@@ -0,0 +1,32 @@
+// Karma configuration file, see link for more information
+// https://karma-runner.github.io/1.0/config/configuration-file.html
+
+module.exports = function (config) {
+ config.set({
+ basePath: '',
+ frameworks: ['jasmine', '@angular-devkit/build-angular'],
+ plugins: [
+ require('karma-jasmine'),
+ require('karma-chrome-launcher'),
+ require('karma-jasmine-html-reporter'),
+ require('karma-coverage-istanbul-reporter'),
+ require('@angular-devkit/build-angular/plugins/karma')
+ ],
+ client: {
+ clearContext: false // leave Jasmine Spec Runner output visible in browser
+ },
+ coverageIstanbulReporter: {
+ dir: require('path').join(__dirname, '../../coverage/cms-kit'),
+ reports: ['html', 'lcovonly', 'text-summary'],
+ fixWebpackSourcePaths: true
+ },
+ reporters: ['progress', 'kjhtml'],
+ port: 9876,
+ colors: true,
+ logLevel: config.LOG_INFO,
+ autoWatch: true,
+ browsers: ['Chrome'],
+ singleRun: false,
+ restartOnFileChange: true
+ });
+};
diff --git a/modules/cms-kit/angular/projects/cms-kit/ng-package.json b/modules/cms-kit/angular/projects/cms-kit/ng-package.json
new file mode 100644
index 0000000000..26aa884e57
--- /dev/null
+++ b/modules/cms-kit/angular/projects/cms-kit/ng-package.json
@@ -0,0 +1,7 @@
+{
+ "$schema": "../../node_modules/ng-packagr/ng-package.schema.json",
+ "dest": "../../dist/cms-kit",
+ "lib": {
+ "entryFile": "src/public-api.ts"
+ }
+}
\ No newline at end of file
diff --git a/modules/cms-kit/angular/projects/cms-kit/ngcc.config.js b/modules/cms-kit/angular/projects/cms-kit/ngcc.config.js
new file mode 100644
index 0000000000..c34df8ab72
--- /dev/null
+++ b/modules/cms-kit/angular/projects/cms-kit/ngcc.config.js
@@ -0,0 +1,7 @@
+module.exports = {
+ entryPoints: {
+ ".": {},
+ "./config": {},
+ "./dist": { ignore: true },
+ },
+};
diff --git a/modules/cms-kit/angular/projects/cms-kit/package.json b/modules/cms-kit/angular/projects/cms-kit/package.json
new file mode 100644
index 0000000000..1dea156a57
--- /dev/null
+++ b/modules/cms-kit/angular/projects/cms-kit/package.json
@@ -0,0 +1,13 @@
+{
+ "name": "@my-company-name/cms-kit",
+ "version": "0.0.1",
+ "peerDependencies": {
+ "@angular/common": "^9.1.11",
+ "@angular/core": "^9.1.11",
+ "@abp/ng.core": ">=3.0.3",
+ "@abp/ng.theme.shared": ">=3.0.3"
+ },
+ "dependencies": {
+ "tslib": "^2.0.0"
+}
+}
diff --git a/modules/cms-kit/angular/projects/cms-kit/src/lib/cms-kit-routing.module.ts b/modules/cms-kit/angular/projects/cms-kit/src/lib/cms-kit-routing.module.ts
new file mode 100644
index 0000000000..7079b008ff
--- /dev/null
+++ b/modules/cms-kit/angular/projects/cms-kit/src/lib/cms-kit-routing.module.ts
@@ -0,0 +1,24 @@
+import { NgModule } from '@angular/core';
+import { DynamicLayoutComponent } from '@abp/ng.core';
+import { Routes, RouterModule } from '@angular/router';
+import { CmsKitComponent } from './components/cms-kit.component';
+
+const routes: Routes = [
+ {
+ path: '',
+ pathMatch: 'full',
+ component: DynamicLayoutComponent,
+ children: [
+ {
+ path: '',
+ component: CmsKitComponent,
+ },
+ ],
+ },
+];
+
+@NgModule({
+ imports: [RouterModule.forChild(routes)],
+ exports: [RouterModule],
+})
+export class CmsKitRoutingModule {}
diff --git a/modules/cms-kit/angular/projects/cms-kit/src/lib/cms-kit.component.spec.ts b/modules/cms-kit/angular/projects/cms-kit/src/lib/cms-kit.component.spec.ts
new file mode 100644
index 0000000000..acd7e447a2
--- /dev/null
+++ b/modules/cms-kit/angular/projects/cms-kit/src/lib/cms-kit.component.spec.ts
@@ -0,0 +1,25 @@
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { CmsKitComponent } from './cms-kit.component';
+
+describe('CmsKitComponent', () => {
+ let component: CmsKitComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [ CmsKitComponent ]
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(CmsKitComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/modules/cms-kit/angular/projects/cms-kit/src/lib/cms-kit.module.ts b/modules/cms-kit/angular/projects/cms-kit/src/lib/cms-kit.module.ts
new file mode 100644
index 0000000000..951dd8f33e
--- /dev/null
+++ b/modules/cms-kit/angular/projects/cms-kit/src/lib/cms-kit.module.ts
@@ -0,0 +1,23 @@
+import { NgModule, NgModuleFactory, ModuleWithProviders } from '@angular/core';
+import { CoreModule, LazyModuleFactory } from '@abp/ng.core';
+import { ThemeSharedModule } from '@abp/ng.theme.shared';
+import { CmsKitComponent } from './components/cms-kit.component';
+import { CmsKitRoutingModule } from './cms-kit-routing.module';
+
+@NgModule({
+ declarations: [CmsKitComponent],
+ imports: [CoreModule, ThemeSharedModule, CmsKitRoutingModule],
+ exports: [CmsKitComponent],
+})
+export class CmsKitModule {
+ static forChild(): ModuleWithProviders {
+ return {
+ ngModule: CmsKitModule,
+ providers: [],
+ };
+ }
+
+ static forLazy(): NgModuleFactory {
+ return new LazyModuleFactory(CmsKitModule.forChild());
+ }
+}
diff --git a/modules/cms-kit/angular/projects/cms-kit/src/lib/cms-kit.service.spec.ts b/modules/cms-kit/angular/projects/cms-kit/src/lib/cms-kit.service.spec.ts
new file mode 100644
index 0000000000..f488c97994
--- /dev/null
+++ b/modules/cms-kit/angular/projects/cms-kit/src/lib/cms-kit.service.spec.ts
@@ -0,0 +1,16 @@
+import { TestBed } from '@angular/core/testing';
+
+import { CmsKitService } from './cms-kit.service';
+
+describe('CmsKitService', () => {
+ let service: CmsKitService;
+
+ beforeEach(() => {
+ TestBed.configureTestingModule({});
+ service = TestBed.inject(CmsKitService);
+ });
+
+ it('should be created', () => {
+ expect(service).toBeTruthy();
+ });
+});
diff --git a/modules/cms-kit/angular/projects/cms-kit/src/lib/components/cms-kit.component.ts b/modules/cms-kit/angular/projects/cms-kit/src/lib/components/cms-kit.component.ts
new file mode 100644
index 0000000000..b6ef6589c5
--- /dev/null
+++ b/modules/cms-kit/angular/projects/cms-kit/src/lib/components/cms-kit.component.ts
@@ -0,0 +1,15 @@
+import { Component, OnInit } from '@angular/core';
+import { CmsKitService } from '../services/cms-kit.service';
+
+@Component({
+ selector: 'lib-cms-kit',
+ template: ` cms-kit works!
`,
+ styles: [],
+})
+export class CmsKitComponent implements OnInit {
+ constructor(private service: CmsKitService) {}
+
+ ngOnInit(): void {
+ this.service.sample().subscribe(console.log);
+ }
+}
diff --git a/modules/cms-kit/angular/projects/cms-kit/src/lib/services/cms-kit.service.ts b/modules/cms-kit/angular/projects/cms-kit/src/lib/services/cms-kit.service.ts
new file mode 100644
index 0000000000..9e966cfbe1
--- /dev/null
+++ b/modules/cms-kit/angular/projects/cms-kit/src/lib/services/cms-kit.service.ts
@@ -0,0 +1,18 @@
+import { Injectable } from '@angular/core';
+import { RestService } from '@abp/ng.core';
+
+@Injectable({
+ providedIn: 'root',
+})
+export class CmsKitService {
+ apiName = 'CmsKit';
+
+ constructor(private restService: RestService) {}
+
+ sample() {
+ return this.restService.request(
+ { method: 'GET', url: '/api/CmsKit/sample' },
+ { apiName: this.apiName }
+ );
+ }
+}
diff --git a/modules/cms-kit/angular/projects/cms-kit/src/public-api.ts b/modules/cms-kit/angular/projects/cms-kit/src/public-api.ts
new file mode 100644
index 0000000000..b07b030e09
--- /dev/null
+++ b/modules/cms-kit/angular/projects/cms-kit/src/public-api.ts
@@ -0,0 +1,7 @@
+/*
+ * Public API Surface of cms-kit
+ */
+
+export * from './lib/components/cms-kit.component';
+export * from './lib/services/cms-kit.service';
+export * from './lib/cms-kit.module';
diff --git a/modules/cms-kit/angular/projects/cms-kit/src/test.ts b/modules/cms-kit/angular/projects/cms-kit/src/test.ts
new file mode 100644
index 0000000000..303b32a220
--- /dev/null
+++ b/modules/cms-kit/angular/projects/cms-kit/src/test.ts
@@ -0,0 +1,26 @@
+// This file is required by karma.conf.js and loads recursively all the .spec and framework files
+
+import 'zone.js/dist/zone';
+import 'zone.js/dist/zone-testing';
+import { getTestBed } from '@angular/core/testing';
+import {
+ BrowserDynamicTestingModule,
+ platformBrowserDynamicTesting
+} from '@angular/platform-browser-dynamic/testing';
+
+declare const require: {
+ context(path: string, deep?: boolean, filter?: RegExp): {
+ keys(): string[];
+ (id: string): T;
+ };
+};
+
+// First, initialize the Angular testing environment.
+getTestBed().initTestEnvironment(
+ BrowserDynamicTestingModule,
+ platformBrowserDynamicTesting()
+);
+// Then we find all the tests.
+const context = require.context('./', true, /\.spec\.ts$/);
+// And load the modules.
+context.keys().map(context);
diff --git a/modules/cms-kit/angular/projects/cms-kit/tsconfig.lib.json b/modules/cms-kit/angular/projects/cms-kit/tsconfig.lib.json
new file mode 100644
index 0000000000..c433a69f62
--- /dev/null
+++ b/modules/cms-kit/angular/projects/cms-kit/tsconfig.lib.json
@@ -0,0 +1,17 @@
+{
+ "extends": "../../tsconfig.prod.json",
+ "compilerOptions": {
+ "outDir": "../../out-tsc/lib",
+ "target": "es2015",
+ "declaration": true,
+ "inlineSources": true,
+ "types": [],
+ "lib": ["dom", "es2018"]
+ },
+ "angularCompilerOptions": {
+ "skipTemplateCodegen": true,
+ "strictMetadataEmit": true,
+ "enableResourceInlining": true
+ },
+ "exclude": ["src/test.ts", "**/*.spec.ts"]
+}
diff --git a/modules/cms-kit/angular/projects/cms-kit/tsconfig.lib.prod.json b/modules/cms-kit/angular/projects/cms-kit/tsconfig.lib.prod.json
new file mode 100644
index 0000000000..cbae794224
--- /dev/null
+++ b/modules/cms-kit/angular/projects/cms-kit/tsconfig.lib.prod.json
@@ -0,0 +1,6 @@
+{
+ "extends": "./tsconfig.lib.json",
+ "angularCompilerOptions": {
+ "enableIvy": false
+ }
+}
diff --git a/modules/cms-kit/angular/projects/cms-kit/tsconfig.spec.json b/modules/cms-kit/angular/projects/cms-kit/tsconfig.spec.json
new file mode 100644
index 0000000000..a9ea5ea114
--- /dev/null
+++ b/modules/cms-kit/angular/projects/cms-kit/tsconfig.spec.json
@@ -0,0 +1,17 @@
+{
+ "extends": "../../tsconfig.base.json",
+ "compilerOptions": {
+ "outDir": "../../out-tsc/spec",
+ "types": [
+ "jasmine",
+ "node"
+ ]
+ },
+ "files": [
+ "src/test.ts"
+ ],
+ "include": [
+ "**/*.spec.ts",
+ "**/*.d.ts"
+ ]
+}
diff --git a/modules/cms-kit/angular/projects/cms-kit/tslint.json b/modules/cms-kit/angular/projects/cms-kit/tslint.json
new file mode 100644
index 0000000000..124133f849
--- /dev/null
+++ b/modules/cms-kit/angular/projects/cms-kit/tslint.json
@@ -0,0 +1,17 @@
+{
+ "extends": "../../tslint.json",
+ "rules": {
+ "directive-selector": [
+ true,
+ "attribute",
+ "lib",
+ "camelCase"
+ ],
+ "component-selector": [
+ true,
+ "element",
+ "lib",
+ "kebab-case"
+ ]
+ }
+}
diff --git a/modules/cms-kit/angular/projects/dev-app/.browserslistrc b/modules/cms-kit/angular/projects/dev-app/.browserslistrc
new file mode 100644
index 0000000000..80848532e4
--- /dev/null
+++ b/modules/cms-kit/angular/projects/dev-app/.browserslistrc
@@ -0,0 +1,12 @@
+# This file is used by the build system to adjust CSS and JS output to support the specified browsers below.
+# For additional information regarding the format and rule options, please see:
+# https://github.com/browserslist/browserslist#queries
+
+# You can see what browsers were selected by your queries by running:
+# npx browserslist
+
+> 0.5%
+last 2 versions
+Firefox ESR
+not dead
+not IE 9-11 # For IE 9-11 support, remove 'not'.
\ No newline at end of file
diff --git a/modules/cms-kit/angular/projects/dev-app/e2e/protractor.conf.js b/modules/cms-kit/angular/projects/dev-app/e2e/protractor.conf.js
new file mode 100644
index 0000000000..7c798cfff0
--- /dev/null
+++ b/modules/cms-kit/angular/projects/dev-app/e2e/protractor.conf.js
@@ -0,0 +1,32 @@
+// @ts-check
+// Protractor configuration file, see link for more information
+// https://github.com/angular/protractor/blob/master/lib/config.ts
+
+const { SpecReporter } = require('jasmine-spec-reporter');
+
+/**
+ * @type { import("protractor").Config }
+ */
+exports.config = {
+ allScriptsTimeout: 11000,
+ specs: [
+ './src/**/*.e2e-spec.ts'
+ ],
+ capabilities: {
+ browserName: 'chrome'
+ },
+ directConnect: true,
+ baseUrl: 'http://localhost:4200/',
+ framework: 'jasmine',
+ jasmineNodeOpts: {
+ showColors: true,
+ defaultTimeoutInterval: 30000,
+ print: function() {}
+ },
+ onPrepare() {
+ require('ts-node').register({
+ project: require('path').join(__dirname, './tsconfig.json')
+ });
+ jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } }));
+ }
+};
\ No newline at end of file
diff --git a/modules/cms-kit/angular/projects/dev-app/e2e/src/app.e2e-spec.ts b/modules/cms-kit/angular/projects/dev-app/e2e/src/app.e2e-spec.ts
new file mode 100644
index 0000000000..e8eda49d2a
--- /dev/null
+++ b/modules/cms-kit/angular/projects/dev-app/e2e/src/app.e2e-spec.ts
@@ -0,0 +1,23 @@
+import { AppPage } from './app.po';
+import { browser, logging } from 'protractor';
+
+describe('workspace-project App', () => {
+ let page: AppPage;
+
+ beforeEach(() => {
+ page = new AppPage();
+ });
+
+ it('should display welcome message', () => {
+ page.navigateTo();
+ expect(page.getTitleText()).toEqual('dev-app app is running!');
+ });
+
+ afterEach(async () => {
+ // Assert that there are no errors emitted from the browser
+ const logs = await browser.manage().logs().get(logging.Type.BROWSER);
+ expect(logs).not.toContain(jasmine.objectContaining({
+ level: logging.Level.SEVERE,
+ } as logging.Entry));
+ });
+});
diff --git a/modules/cms-kit/angular/projects/dev-app/e2e/src/app.po.ts b/modules/cms-kit/angular/projects/dev-app/e2e/src/app.po.ts
new file mode 100644
index 0000000000..b68475e0fc
--- /dev/null
+++ b/modules/cms-kit/angular/projects/dev-app/e2e/src/app.po.ts
@@ -0,0 +1,11 @@
+import { browser, by, element } from 'protractor';
+
+export class AppPage {
+ navigateTo(): Promise {
+ return browser.get(browser.baseUrl) as Promise;
+ }
+
+ getTitleText(): Promise {
+ return element(by.css('app-root .content span')).getText() as Promise;
+ }
+}
diff --git a/modules/cms-kit/angular/projects/dev-app/e2e/tsconfig.json b/modules/cms-kit/angular/projects/dev-app/e2e/tsconfig.json
new file mode 100644
index 0000000000..746a242801
--- /dev/null
+++ b/modules/cms-kit/angular/projects/dev-app/e2e/tsconfig.json
@@ -0,0 +1,13 @@
+{
+ "extends": "../../../tsconfig.base.json",
+ "compilerOptions": {
+ "outDir": "../../../out-tsc/e2e",
+ "module": "commonjs",
+ "target": "es2018",
+ "types": [
+ "jasmine",
+ "jasminewd2",
+ "node"
+ ]
+ }
+}
diff --git a/modules/cms-kit/angular/projects/dev-app/favicon.ico b/modules/cms-kit/angular/projects/dev-app/favicon.ico
new file mode 100644
index 0000000000..39695854d2
Binary files /dev/null and b/modules/cms-kit/angular/projects/dev-app/favicon.ico differ
diff --git a/modules/cms-kit/angular/projects/dev-app/karma.conf.js b/modules/cms-kit/angular/projects/dev-app/karma.conf.js
new file mode 100644
index 0000000000..6059f553f2
--- /dev/null
+++ b/modules/cms-kit/angular/projects/dev-app/karma.conf.js
@@ -0,0 +1,32 @@
+// Karma configuration file, see link for more information
+// https://karma-runner.github.io/1.0/config/configuration-file.html
+
+module.exports = function (config) {
+ config.set({
+ basePath: '',
+ frameworks: ['jasmine', '@angular-devkit/build-angular'],
+ plugins: [
+ require('karma-jasmine'),
+ require('karma-chrome-launcher'),
+ require('karma-jasmine-html-reporter'),
+ require('karma-coverage-istanbul-reporter'),
+ require('@angular-devkit/build-angular/plugins/karma')
+ ],
+ client: {
+ clearContext: false // leave Jasmine Spec Runner output visible in browser
+ },
+ coverageIstanbulReporter: {
+ dir: require('path').join(__dirname, '../../coverage/dev-app'),
+ reports: ['html', 'lcovonly', 'text-summary'],
+ fixWebpackSourcePaths: true
+ },
+ reporters: ['progress', 'kjhtml'],
+ port: 9876,
+ colors: true,
+ logLevel: config.LOG_INFO,
+ autoWatch: true,
+ browsers: ['Chrome'],
+ singleRun: false,
+ restartOnFileChange: true
+ });
+};
diff --git a/modules/cms-kit/angular/projects/dev-app/src/app/app-routing.module.ts b/modules/cms-kit/angular/projects/dev-app/src/app/app-routing.module.ts
new file mode 100644
index 0000000000..b2c95094c1
--- /dev/null
+++ b/modules/cms-kit/angular/projects/dev-app/src/app/app-routing.module.ts
@@ -0,0 +1,49 @@
+import { NgModule } from '@angular/core';
+import { RouterModule, Routes } from '@angular/router';
+
+const routes: Routes = [
+ {
+ path: '',
+ pathMatch: 'full',
+ loadChildren: () => import('./home/home.module').then((m) => m.HomeModule),
+ },
+ {
+ path: 'account',
+ loadChildren: () =>
+ import('@abp/ng.account').then((m) =>
+ m.AccountModule.forLazy({ redirectUrl: '/' })
+ ),
+ },
+ {
+ path: 'identity',
+ loadChildren: () =>
+ import('@abp/ng.identity').then((m) => m.IdentityModule.forLazy()),
+ },
+ {
+ path: 'tenant-management',
+ loadChildren: () =>
+ import('@abp/ng.tenant-management').then((m) =>
+ m.TenantManagementModule.forLazy()
+ ),
+ },
+ {
+ path: 'setting-management',
+ loadChildren: () =>
+ import('@abp/ng.setting-management').then((m) =>
+ m.SettingManagementModule.forLazy()
+ ),
+ },
+ {
+ path: 'cms-kit',
+ loadChildren: () =>
+ import('@my-company-name/cms-kit').then((m) =>
+ m.CmsKitModule.forLazy()
+ ),
+ },
+];
+
+@NgModule({
+ imports: [RouterModule.forRoot(routes)],
+ exports: [RouterModule],
+})
+export class AppRoutingModule {}
diff --git a/modules/cms-kit/angular/projects/dev-app/src/app/app.component.ts b/modules/cms-kit/angular/projects/dev-app/src/app/app.component.ts
new file mode 100644
index 0000000000..a26e745334
--- /dev/null
+++ b/modules/cms-kit/angular/projects/dev-app/src/app/app.component.ts
@@ -0,0 +1,10 @@
+import { Component } from '@angular/core';
+
+@Component({
+ selector: 'app-root',
+ template: `
+
+
+ `,
+})
+export class AppComponent {}
diff --git a/modules/cms-kit/angular/projects/dev-app/src/app/app.module.ts b/modules/cms-kit/angular/projects/dev-app/src/app/app.module.ts
new file mode 100644
index 0000000000..e97243133f
--- /dev/null
+++ b/modules/cms-kit/angular/projects/dev-app/src/app/app.module.ts
@@ -0,0 +1,41 @@
+import { AccountConfigModule } from '@abp/ng.account/config';
+import { CoreModule } from '@abp/ng.core';
+import { IdentityConfigModule } from '@abp/ng.identity/config';
+import { SettingManagementConfigModule } from '@abp/ng.setting-management/config';
+import { TenantManagementConfigModule } from '@abp/ng.tenant-management/config';
+import { ThemeSharedModule } from '@abp/ng.theme.shared';
+import { NgModule } from '@angular/core';
+import { BrowserModule } from '@angular/platform-browser';
+import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
+import { CmsKitConfigModule } from '@my-company-name/cms-kit/config';
+import { NgxsModule } from '@ngxs/store';
+import { environment } from '../environments/environment';
+import { AppRoutingModule } from './app-routing.module';
+import { AppComponent } from './app.component';
+import { APP_ROUTE_PROVIDER } from './route.provider';
+import { ThemeBasicModule } from '@abp/ng.theme.basic';
+
+@NgModule({
+ imports: [
+ BrowserModule,
+ BrowserAnimationsModule,
+ AppRoutingModule,
+ CoreModule.forRoot({
+ environment,
+ sendNullsAsQueryParam: false,
+ skipGetAppConfiguration: false,
+ }),
+ ThemeSharedModule.forRoot(),
+ AccountConfigModule.forRoot(),
+ IdentityConfigModule.forRoot(),
+ CmsKitConfigModule.forRoot(),
+ TenantManagementConfigModule.forRoot(),
+ SettingManagementConfigModule.forRoot(),
+ NgxsModule.forRoot(),
+ ThemeBasicModule.forRoot(),
+ ],
+ providers: [APP_ROUTE_PROVIDER],
+ declarations: [AppComponent],
+ bootstrap: [AppComponent],
+})
+export class AppModule {}
diff --git a/modules/cms-kit/angular/projects/dev-app/src/app/home/home-routing.module.ts b/modules/cms-kit/angular/projects/dev-app/src/app/home/home-routing.module.ts
new file mode 100644
index 0000000000..634706a36c
--- /dev/null
+++ b/modules/cms-kit/angular/projects/dev-app/src/app/home/home-routing.module.ts
@@ -0,0 +1,16 @@
+import { NgModule } from '@angular/core';
+import { Routes, RouterModule } from '@angular/router';
+import { HomeComponent } from './home.component';
+
+const routes: Routes = [
+ {
+ path: '',
+ children: [{ path: '', component: HomeComponent }],
+ },
+];
+
+@NgModule({
+ imports: [RouterModule.forChild(routes)],
+ exports: [RouterModule],
+})
+export class HomeRoutingModule {}
diff --git a/modules/cms-kit/angular/projects/dev-app/src/app/home/home.component.html b/modules/cms-kit/angular/projects/dev-app/src/app/home/home.component.html
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/modules/cms-kit/angular/projects/dev-app/src/app/home/home.component.ts b/modules/cms-kit/angular/projects/dev-app/src/app/home/home.component.ts
new file mode 100644
index 0000000000..ab1f354e89
--- /dev/null
+++ b/modules/cms-kit/angular/projects/dev-app/src/app/home/home.component.ts
@@ -0,0 +1,7 @@
+import { Component } from '@angular/core';
+
+@Component({
+ selector: 'app-home',
+ templateUrl: './home.component.html',
+})
+export class HomeComponent {}
diff --git a/modules/cms-kit/angular/projects/dev-app/src/app/home/home.module.ts b/modules/cms-kit/angular/projects/dev-app/src/app/home/home.module.ts
new file mode 100644
index 0000000000..72d20ccc65
--- /dev/null
+++ b/modules/cms-kit/angular/projects/dev-app/src/app/home/home.module.ts
@@ -0,0 +1,10 @@
+import { NgModule } from '@angular/core';
+import { SharedModule } from '../shared/shared.module';
+import { HomeRoutingModule } from './home-routing.module';
+import { HomeComponent } from './home.component';
+
+@NgModule({
+ declarations: [HomeComponent],
+ imports: [SharedModule, HomeRoutingModule],
+})
+export class HomeModule {}
diff --git a/modules/cms-kit/angular/projects/dev-app/src/app/route.provider.ts b/modules/cms-kit/angular/projects/dev-app/src/app/route.provider.ts
new file mode 100644
index 0000000000..a412259466
--- /dev/null
+++ b/modules/cms-kit/angular/projects/dev-app/src/app/route.provider.ts
@@ -0,0 +1,25 @@
+import { RoutesService, eLayoutType } from '@abp/ng.core';
+import { APP_INITIALIZER } from '@angular/core';
+
+export const APP_ROUTE_PROVIDER = [
+ {
+ provide: APP_INITIALIZER,
+ useFactory: configureRoutes,
+ deps: [RoutesService],
+ multi: true,
+ },
+];
+
+function configureRoutes(routes: RoutesService) {
+ return () => {
+ routes.add([
+ {
+ path: '/',
+ name: 'Home',
+ iconClass: 'fas fa-home',
+ order: 1,
+ layout: eLayoutType.application,
+ },
+ ]);
+ };
+}
diff --git a/modules/cms-kit/angular/projects/dev-app/src/app/shared/shared.module.ts b/modules/cms-kit/angular/projects/dev-app/src/app/shared/shared.module.ts
new file mode 100644
index 0000000000..1f268b4572
--- /dev/null
+++ b/modules/cms-kit/angular/projects/dev-app/src/app/shared/shared.module.ts
@@ -0,0 +1,26 @@
+import { CoreModule } from '@abp/ng.core';
+import { NgbDropdownModule } from '@ng-bootstrap/ng-bootstrap';
+import { NgModule } from '@angular/core';
+import { ThemeBasicModule } from '@abp/ng.theme.basic';
+import { ThemeSharedModule } from '@abp/ng.theme.shared';
+import { NgxValidateCoreModule } from '@ngx-validate/core';
+
+@NgModule({
+ declarations: [],
+ imports: [
+ CoreModule,
+ ThemeSharedModule,
+ ThemeBasicModule,
+ NgbDropdownModule,
+ NgxValidateCoreModule,
+ ],
+ exports: [
+ CoreModule,
+ ThemeSharedModule,
+ ThemeBasicModule,
+ NgbDropdownModule,
+ NgxValidateCoreModule,
+ ],
+ providers: [],
+})
+export class SharedModule {}
diff --git a/modules/cms-kit/angular/projects/dev-app/src/assets/.gitkeep b/modules/cms-kit/angular/projects/dev-app/src/assets/.gitkeep
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/modules/cms-kit/angular/projects/dev-app/src/environments/environment.prod.ts b/modules/cms-kit/angular/projects/dev-app/src/environments/environment.prod.ts
new file mode 100644
index 0000000000..6850f7102a
--- /dev/null
+++ b/modules/cms-kit/angular/projects/dev-app/src/environments/environment.prod.ts
@@ -0,0 +1,24 @@
+export const environment = {
+ production: true,
+ application: {
+ name: 'CmsKit',
+ logoUrl: '',
+ },
+ oAuthConfig: {
+ issuer: 'https://localhost:44318',
+ clientId: 'CmsKit_ConsoleTestApp',
+ dummyClientSecret: '1q2w3e*',
+ scope: 'CmsKit',
+ showDebugInformation: true,
+ oidc: false,
+ requireHttps: true,
+ },
+ apis: {
+ default: {
+ url: 'https://localhost:44318',
+ },
+ CmsKit: {
+ url: 'https://localhost:44371',
+ },
+ },
+};
diff --git a/modules/cms-kit/angular/projects/dev-app/src/environments/environment.ts b/modules/cms-kit/angular/projects/dev-app/src/environments/environment.ts
new file mode 100644
index 0000000000..f1381092b1
--- /dev/null
+++ b/modules/cms-kit/angular/projects/dev-app/src/environments/environment.ts
@@ -0,0 +1,24 @@
+export const environment = {
+ production: false,
+ application: {
+ name: 'CmsKit',
+ logoUrl: '',
+ },
+ oAuthConfig: {
+ issuer: 'https://localhost:44318',
+ clientId: 'CmsKit_ConsoleTestApp',
+ dummyClientSecret: '1q2w3e*',
+ scope: 'CmsKit',
+ showDebugInformation: true,
+ oidc: false,
+ requireHttps: true,
+ },
+ apis: {
+ default: {
+ url: 'https://localhost:44318',
+ },
+ CmsKit: {
+ url: 'https://localhost:44371',
+ },
+ },
+};
diff --git a/modules/cms-kit/angular/projects/dev-app/src/index.html b/modules/cms-kit/angular/projects/dev-app/src/index.html
new file mode 100644
index 0000000000..067936da71
--- /dev/null
+++ b/modules/cms-kit/angular/projects/dev-app/src/index.html
@@ -0,0 +1,13 @@
+
+
+
+
+ DevApp
+
+
+
+
+
+
+
+
diff --git a/modules/cms-kit/angular/projects/dev-app/src/main.ts b/modules/cms-kit/angular/projects/dev-app/src/main.ts
new file mode 100644
index 0000000000..c7b673cf44
--- /dev/null
+++ b/modules/cms-kit/angular/projects/dev-app/src/main.ts
@@ -0,0 +1,12 @@
+import { enableProdMode } from '@angular/core';
+import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
+
+import { AppModule } from './app/app.module';
+import { environment } from './environments/environment';
+
+if (environment.production) {
+ enableProdMode();
+}
+
+platformBrowserDynamic().bootstrapModule(AppModule)
+ .catch(err => console.error(err));
diff --git a/modules/cms-kit/angular/projects/dev-app/src/polyfills.ts b/modules/cms-kit/angular/projects/dev-app/src/polyfills.ts
new file mode 100644
index 0000000000..6e00c561ed
--- /dev/null
+++ b/modules/cms-kit/angular/projects/dev-app/src/polyfills.ts
@@ -0,0 +1,66 @@
+/***************************************************************************************************
+ * Load `$localize` onto the global scope - used if i18n tags appear in Angular templates.
+ */
+import '@angular/localize/init';
+/**
+ * This file includes polyfills needed by Angular and is loaded before the app.
+ * You can add your own extra polyfills to this file.
+ *
+ * This file is divided into 2 sections:
+ * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers.
+ * 2. Application imports. Files imported after ZoneJS that should be loaded before your main
+ * file.
+ *
+ * The current setup is for so-called "evergreen" browsers; the last versions of browsers that
+ * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera),
+ * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile.
+ *
+ * Learn more in https://angular.io/guide/browser-support
+ */
+
+/***************************************************************************************************
+ * BROWSER POLYFILLS
+ */
+
+/** IE10 and IE11 requires the following for NgClass support on SVG elements */
+// import 'classlist.js'; // Run `npm install --save classlist.js`.
+
+/**
+ * Web Animations `@angular/platform-browser/animations`
+ * Only required if AnimationBuilder is used within the application and using IE/Edge or Safari.
+ * Standard animation support in Angular DOES NOT require any polyfills (as of Angular 6.0).
+ */
+// import 'web-animations-js'; // Run `npm install --save web-animations-js`.
+
+/**
+ * By default, zone.js will patch all possible macroTask and DomEvents
+ * user can disable parts of macroTask/DomEvents patch by setting following flags
+ * because those flags need to be set before `zone.js` being loaded, and webpack
+ * will put import in the top of bundle, so user need to create a separate file
+ * in this directory (for example: zone-flags.ts), and put the following flags
+ * into that file, and then add the following code before importing zone.js.
+ * import './zone-flags';
+ *
+ * The flags allowed in zone-flags.ts are listed here.
+ *
+ * The following flags will work for all browsers.
+ *
+ * (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame
+ * (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick
+ * (window as any).__zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames
+ *
+ * in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js
+ * with the following flag, it will bypass `zone.js` patch for IE/Edge
+ *
+ * (window as any).__Zone_enable_cross_context_check = true;
+ *
+ */
+
+/***************************************************************************************************
+ * Zone JS is required by default for Angular itself.
+ */
+import 'zone.js/dist/zone'; // Included with Angular CLI.
+
+/***************************************************************************************************
+ * APPLICATION IMPORTS
+ */
diff --git a/modules/cms-kit/angular/projects/dev-app/src/styles.scss b/modules/cms-kit/angular/projects/dev-app/src/styles.scss
new file mode 100644
index 0000000000..90d4ee0072
--- /dev/null
+++ b/modules/cms-kit/angular/projects/dev-app/src/styles.scss
@@ -0,0 +1 @@
+/* You can add global styles to this file, and also import other style files */
diff --git a/modules/cms-kit/angular/projects/dev-app/src/test.ts b/modules/cms-kit/angular/projects/dev-app/src/test.ts
new file mode 100644
index 0000000000..50193eb0f2
--- /dev/null
+++ b/modules/cms-kit/angular/projects/dev-app/src/test.ts
@@ -0,0 +1,25 @@
+// This file is required by karma.conf.js and loads recursively all the .spec and framework files
+
+import 'zone.js/dist/zone-testing';
+import { getTestBed } from '@angular/core/testing';
+import {
+ BrowserDynamicTestingModule,
+ platformBrowserDynamicTesting
+} from '@angular/platform-browser-dynamic/testing';
+
+declare const require: {
+ context(path: string, deep?: boolean, filter?: RegExp): {
+ keys(): string[];
+ (id: string): T;
+ };
+};
+
+// First, initialize the Angular testing environment.
+getTestBed().initTestEnvironment(
+ BrowserDynamicTestingModule,
+ platformBrowserDynamicTesting()
+);
+// Then we find all the tests.
+const context = require.context('./', true, /\.spec\.ts$/);
+// And load the modules.
+context.keys().map(context);
diff --git a/modules/cms-kit/angular/projects/dev-app/tsconfig.app.json b/modules/cms-kit/angular/projects/dev-app/tsconfig.app.json
new file mode 100644
index 0000000000..406dd61a4a
--- /dev/null
+++ b/modules/cms-kit/angular/projects/dev-app/tsconfig.app.json
@@ -0,0 +1,14 @@
+{
+ "extends": "../../tsconfig.base.json",
+ "compilerOptions": {
+ "outDir": "../../out-tsc/app",
+ "types": []
+ },
+ "files": [
+ "src/main.ts",
+ "src/polyfills.ts"
+ ],
+ "include": [
+ "src/**/*.d.ts"
+ ]
+}
diff --git a/modules/cms-kit/angular/projects/dev-app/tsconfig.prod.json b/modules/cms-kit/angular/projects/dev-app/tsconfig.prod.json
new file mode 100644
index 0000000000..3d4cab2c18
--- /dev/null
+++ b/modules/cms-kit/angular/projects/dev-app/tsconfig.prod.json
@@ -0,0 +1,9 @@
+{
+ "extends": "../../tsconfig.prod.json",
+ "compilerOptions": {
+ "outDir": "../../out-tsc/app",
+ "types": []
+ },
+ "files": ["src/main.ts", "src/polyfills.ts"],
+ "include": ["src/**/*.d.ts"]
+}
diff --git a/modules/cms-kit/angular/projects/dev-app/tsconfig.spec.json b/modules/cms-kit/angular/projects/dev-app/tsconfig.spec.json
new file mode 100644
index 0000000000..ed5461c09c
--- /dev/null
+++ b/modules/cms-kit/angular/projects/dev-app/tsconfig.spec.json
@@ -0,0 +1,18 @@
+{
+ "extends": "../../tsconfig.base.json",
+ "compilerOptions": {
+ "outDir": "../../out-tsc/spec",
+ "types": [
+ "jasmine",
+ "node"
+ ]
+ },
+ "files": [
+ "src/test.ts",
+ "src/polyfills.ts"
+ ],
+ "include": [
+ "src/**/*.spec.ts",
+ "src/**/*.d.ts"
+ ]
+}
diff --git a/modules/cms-kit/angular/projects/dev-app/tslint.json b/modules/cms-kit/angular/projects/dev-app/tslint.json
new file mode 100644
index 0000000000..19e8161a0b
--- /dev/null
+++ b/modules/cms-kit/angular/projects/dev-app/tslint.json
@@ -0,0 +1,17 @@
+{
+ "extends": "../../tslint.json",
+ "rules": {
+ "directive-selector": [
+ true,
+ "attribute",
+ "app",
+ "camelCase"
+ ],
+ "component-selector": [
+ true,
+ "element",
+ "app",
+ "kebab-case"
+ ]
+ }
+}
diff --git a/modules/cms-kit/angular/tsconfig.base.json b/modules/cms-kit/angular/tsconfig.base.json
new file mode 100644
index 0000000000..c315ff5654
--- /dev/null
+++ b/modules/cms-kit/angular/tsconfig.base.json
@@ -0,0 +1,13 @@
+{
+ "extends": "./tsconfig.prod.json",
+ "compilerOptions": {
+ "paths": {
+ "@my-company-name/cms-kit": [
+ "projects/cms-kit/src/public-api.ts"
+ ],
+ "@my-company-name/cms-kit/config": [
+ "projects/cms-kit/config/src/public-api.ts"
+ ]
+ }
+ }
+}
diff --git a/modules/cms-kit/angular/tsconfig.json b/modules/cms-kit/angular/tsconfig.json
new file mode 100644
index 0000000000..3e169eac5c
--- /dev/null
+++ b/modules/cms-kit/angular/tsconfig.json
@@ -0,0 +1,23 @@
+/*
+ This is a "Solution Style" tsconfig.json file, and is used by editors and TypeScript’s language server to improve development experience.
+ It is not intended to be used to perform a compilation.
+
+ To learn more about this file see: https://angular.io/config/solution-tsconfig.
+*/
+{
+ "files": [],
+ "references": [
+ {
+ "path": "./projects/cms-kit/tsconfig.lib.json"
+ },
+ {
+ "path": "./projects/cms-kit/tsconfig.spec.json"
+ },
+ {
+ "path": "./projects/dev-app/tsconfig.app.json"
+ },
+ {
+ "path": "./projects/dev-app/tsconfig.spec.json"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/modules/cms-kit/angular/tsconfig.prod.json b/modules/cms-kit/angular/tsconfig.prod.json
new file mode 100644
index 0000000000..8cbc5cd8a7
--- /dev/null
+++ b/modules/cms-kit/angular/tsconfig.prod.json
@@ -0,0 +1,20 @@
+{
+ "compileOnSave": false,
+ "compilerOptions": {
+ "baseUrl": "./",
+ "outDir": "./dist/out-tsc",
+ "sourceMap": true,
+ "declaration": false,
+ "downlevelIteration": true,
+ "experimentalDecorators": true,
+ "module": "esnext",
+ "moduleResolution": "node",
+ "importHelpers": true,
+ "target": "es2015",
+ "lib": ["es2018", "dom"]
+ },
+ "angularCompilerOptions": {
+ "fullTemplateTypeCheck": true,
+ "strictInjectionParameters": true
+ }
+}
diff --git a/modules/cms-kit/angular/tslint.json b/modules/cms-kit/angular/tslint.json
new file mode 100644
index 0000000000..def88d1c87
--- /dev/null
+++ b/modules/cms-kit/angular/tslint.json
@@ -0,0 +1,136 @@
+{
+ "extends": "tslint:recommended",
+ "rulesDirectory": [
+ "codelyzer"
+ ],
+ "rules": {
+ "align": {
+ "options": [
+ "parameters",
+ "statements"
+ ]
+ },
+ "array-type": false,
+ "arrow-return-shorthand": true,
+ "curly": true,
+ "deprecation": {
+ "severity": "warning"
+ },
+ "eofline": true,
+ "import-blacklist": [
+ true,
+ "rxjs/Rx"
+ ],
+ "import-spacing": true,
+ "indent": {
+ "options": [
+ "spaces"
+ ]
+ },
+ "max-classes-per-file": false,
+ "max-line-length": [
+ true,
+ 140
+ ],
+ "member-ordering": [
+ true,
+ {
+ "order": [
+ "static-field",
+ "instance-field",
+ "static-method",
+ "instance-method"
+ ]
+ }
+ ],
+ "no-console": [
+ true,
+ "debug",
+ "info",
+ "time",
+ "timeEnd",
+ "trace"
+ ],
+ "no-empty": false,
+ "no-inferrable-types": [
+ true,
+ "ignore-params"
+ ],
+ "no-non-null-assertion": true,
+ "no-redundant-jsdoc": true,
+ "no-switch-case-fall-through": true,
+ "no-var-requires": false,
+ "object-literal-key-quotes": [
+ true,
+ "as-needed"
+ ],
+ "quotemark": [
+ true,
+ "single"
+ ],
+ "semicolon": {
+ "options": [
+ "always"
+ ]
+ },
+ "space-before-function-paren": {
+ "options": {
+ "anonymous": "never",
+ "asyncArrow": "always",
+ "constructor": "never",
+ "method": "never",
+ "named": "never"
+ }
+ },
+ "typedef-whitespace": {
+ "options": [
+ {
+ "call-signature": "nospace",
+ "index-signature": "nospace",
+ "parameter": "nospace",
+ "property-declaration": "nospace",
+ "variable-declaration": "nospace"
+ },
+ {
+ "call-signature": "onespace",
+ "index-signature": "onespace",
+ "parameter": "onespace",
+ "property-declaration": "onespace",
+ "variable-declaration": "onespace"
+ }
+ ]
+ },
+ "variable-name": {
+ "options": [
+ "ban-keywords",
+ "check-format",
+ "allow-pascal-case"
+ ]
+ },
+ "whitespace": {
+ "options": [
+ "check-branch",
+ "check-decl",
+ "check-operator",
+ "check-separator",
+ "check-type",
+ "check-typecast"
+ ]
+ },
+ "component-class-suffix": true,
+ "contextual-lifecycle": true,
+ "directive-class-suffix": true,
+ "no-conflicting-lifecycle": true,
+ "no-host-metadata-property": true,
+ "no-input-rename": true,
+ "no-inputs-metadata-property": true,
+ "no-output-native": true,
+ "no-output-on-prefix": true,
+ "no-output-rename": true,
+ "no-outputs-metadata-property": true,
+ "template-banana-in-box": true,
+ "template-no-negated-async": true,
+ "use-lifecycle-interface": true,
+ "use-pipe-transform-interface": true
+ }
+}
diff --git a/modules/cms-kit/common.props b/modules/cms-kit/common.props
new file mode 100644
index 0000000000..0e2bf35066
--- /dev/null
+++ b/modules/cms-kit/common.props
@@ -0,0 +1,13 @@
+
+
+ latest
+ 0.1.0
+ $(NoWarn);CS1591
+ module
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/modules/cms-kit/database/Dockerfile b/modules/cms-kit/database/Dockerfile
new file mode 100644
index 0000000000..6257db9899
--- /dev/null
+++ b/modules/cms-kit/database/Dockerfile
@@ -0,0 +1,20 @@
+FROM mcr.microsoft.com/dotnet/core/sdk:3.0-buster AS build
+COPY . .
+
+WORKDIR /templates/service/host/IdentityServerHost
+RUN dotnet restore
+RUN dotnet ef migrations script -i -o migrations-IdentityServerHost.sql
+
+WORKDIR /templates/service/host/Volo.CmsKit.Host
+RUN dotnet restore
+RUN dotnet ef migrations script -i -o migrations-CmsKit.sql
+
+FROM mcr.microsoft.com/mssql-tools AS final
+WORKDIR /src
+COPY --from=build /templates/service/host/IdentityServerHost/migrations-IdentityServerHost.sql migrations-IdentityServerHost.sql
+COPY --from=build /templates/service/host/Volo.CmsKit.Host/migrations-CmsKit.sql migrations-CmsKit.sql
+COPY --from=build /templates/service/database/entrypoint.sh .
+RUN /bin/bash -c "sed -i $'s/\r$//' entrypoint.sh"
+RUN chmod +x ./entrypoint.sh
+
+ENTRYPOINT ["./entrypoint.sh"]
\ No newline at end of file
diff --git a/modules/cms-kit/database/entrypoint.sh b/modules/cms-kit/database/entrypoint.sh
new file mode 100644
index 0000000000..dd9e4d6610
--- /dev/null
+++ b/modules/cms-kit/database/entrypoint.sh
@@ -0,0 +1,12 @@
+#!/bin/bash
+
+until /opt/mssql-tools/bin/sqlcmd -S sqlserver -U SA -P $SA_PASSWORD -Q 'SELECT name FROM master.sys.databases'; do
+>&2 echo "SQL Server is starting up"
+sleep 1
+done
+
+/opt/mssql-tools/bin/sqlcmd -S sqlserver -U SA -P $SA_PASSWORD -Q "CREATE DATABASE [$IdentityServer_DB]"
+/opt/mssql-tools/bin/sqlcmd -S sqlserver -U SA -P $SA_PASSWORD -Q "CREATE DATABASE [$CmsKit_DB]"
+
+/opt/mssql-tools/bin/sqlcmd -d $IdentityServer_DB -S sqlserver -U sa -P $SA_PASSWORD -i migrations-IdentityServerHost.sql
+/opt/mssql-tools/bin/sqlcmd -d $CmsKit_DB -S sqlserver -U sa -P $SA_PASSWORD -i migrations-CmsKit.sql
\ No newline at end of file
diff --git a/modules/cms-kit/docker-compose.migrations.yml b/modules/cms-kit/docker-compose.migrations.yml
new file mode 100644
index 0000000000..7897fdc250
--- /dev/null
+++ b/modules/cms-kit/docker-compose.migrations.yml
@@ -0,0 +1,13 @@
+version: '3.4'
+
+services:
+ migrations:
+ build:
+ context: ../../
+ dockerfile: templates/service/database/Dockerfile
+ depends_on:
+ - sqlserver
+ environment:
+ - IdentityServer_DB=CmsKit_Identity
+ - CmsKit_DB=CmsKit_ModuleDb
+ - SA_PASSWORD=yourStrong(!)Password
diff --git a/modules/cms-kit/docker-compose.override.yml b/modules/cms-kit/docker-compose.override.yml
new file mode 100644
index 0000000000..94b9df0c22
--- /dev/null
+++ b/modules/cms-kit/docker-compose.override.yml
@@ -0,0 +1,29 @@
+version: '3.4'
+
+services:
+ sqlserver:
+ environment:
+ - SA_PASSWORD=yourStrong(!)Password
+ - ACCEPT_EULA=Y
+ ports:
+ - "51599:1433"
+
+ identity-server:
+ environment:
+ - ASPNETCORE_URLS=http://0.0.0.0:80
+ - ConnectionStrings__Default=Server=sqlserver;Database=CmsKit_Identity;Trusted_Connection=True;MultipleActiveResultSets=true;User=sa;Password=yourStrong(!)Password;Integrated Security=false
+ - ConnectionStrings__SqlServerCache=Server=sqlserver;Database=CmsKit_Cache;Trusted_Connection=True;MultipleActiveResultSets=true;User=sa;Password=yourStrong(!)Password;Integrated Security=false
+ ports:
+ - "51600:80"
+
+ cms-kit:
+ environment:
+ - ASPNETCORE_URLS=http://0.0.0.0:80
+ - ConnectionStrings__Default=Server=sqlserver;Database=CmsKit_ModuleDb;Trusted_Connection=True;MultipleActiveResultSets=true;User=sa;Password=yourStrong(!)Password;Integrated Security=false
+ - ConnectionStrings__AbpSettingManagement=Server=sqlserver;Database=CmsKit_Identity;Trusted_Connection=True;MultipleActiveResultSets=true;User=sa;Password=yourStrong(!)Password;Integrated Security=false
+ - ConnectionStrings__AbpPermissionManagement=Server=sqlserver;Database=CmsKit_Identity;Trusted_Connection=True;MultipleActiveResultSets=true;User=sa;Password=yourStrong(!)Password;Integrated Security=false
+ - ConnectionStrings__AbpAuditLogging=Server=sqlserver;Database=CmsKit_Identity;Trusted_Connection=True;MultipleActiveResultSets=true;User=sa;Password=yourStrong(!)Password;Integrated Security=false
+ - ConnectionStrings__SqlServerCache=Server=sqlserver;Database=CmsKit_Cache;Trusted_Connection=True;MultipleActiveResultSets=true;User=sa;Password=yourStrong(!)Password;Integrated Security=false
+ - AuthServer__Authority=http://identity-server
+ ports:
+ - "51601:80"
\ No newline at end of file
diff --git a/modules/cms-kit/docker-compose.yml b/modules/cms-kit/docker-compose.yml
new file mode 100644
index 0000000000..564fd5ac06
--- /dev/null
+++ b/modules/cms-kit/docker-compose.yml
@@ -0,0 +1,25 @@
+version: '3.4'
+
+services:
+ sqlserver:
+ image: mcr.microsoft.com/mssql/server
+ volumes:
+ - dbdata:/var/opt/mssql
+
+ identity-server:
+ build:
+ context: ../../
+ dockerfile: templates/service/host/IdentityServerHost/Dockerfile
+ depends_on:
+ - sqlserver
+
+ cms-kit:
+ build:
+ context: ../../
+ dockerfile: templates/service/host/Volo.CmsKit.Host/Dockerfile
+ depends_on:
+ - sqlserver
+ - identity-server
+
+volumes:
+ dbdata:
\ No newline at end of file
diff --git a/modules/cms-kit/host/Volo.CmsKit.Host.Shared/MultiTenancy/MultiTenancyConsts.cs b/modules/cms-kit/host/Volo.CmsKit.Host.Shared/MultiTenancy/MultiTenancyConsts.cs
new file mode 100644
index 0000000000..8c222ee1ce
--- /dev/null
+++ b/modules/cms-kit/host/Volo.CmsKit.Host.Shared/MultiTenancy/MultiTenancyConsts.cs
@@ -0,0 +1,10 @@
+namespace Volo.CmsKit.MultiTenancy
+{
+ public static class MultiTenancyConsts
+ {
+ /* Enable/disable multi-tenancy in a single point
+ * to test your module with multi-tenancy.
+ */
+ public const bool IsEnabled = false;
+ }
+}
diff --git a/modules/cms-kit/host/Volo.CmsKit.Host.Shared/Volo.CmsKit.Host.Shared.csproj b/modules/cms-kit/host/Volo.CmsKit.Host.Shared/Volo.CmsKit.Host.Shared.csproj
new file mode 100644
index 0000000000..3f8c167b98
--- /dev/null
+++ b/modules/cms-kit/host/Volo.CmsKit.Host.Shared/Volo.CmsKit.Host.Shared.csproj
@@ -0,0 +1,10 @@
+
+
+
+
+
+ netstandard2.0
+ Volo.CmsKit
+
+
+
diff --git a/modules/cms-kit/host/Volo.CmsKit.HttpApi.Host/CmsKitHttpApiHostModule.cs b/modules/cms-kit/host/Volo.CmsKit.HttpApi.Host/CmsKitHttpApiHostModule.cs
new file mode 100644
index 0000000000..c63d28081f
--- /dev/null
+++ b/modules/cms-kit/host/Volo.CmsKit.HttpApi.Host/CmsKitHttpApiHostModule.cs
@@ -0,0 +1,185 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Security.Claims;
+using IdentityModel;
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Cors;
+using Microsoft.AspNetCore.DataProtection;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
+using Volo.CmsKit.EntityFrameworkCore;
+using Volo.CmsKit.MultiTenancy;
+using StackExchange.Redis;
+using Microsoft.OpenApi.Models;
+using Swashbuckle.AspNetCore.Swagger;
+using Volo.Abp;
+using Volo.Abp.AspNetCore.MultiTenancy;
+using Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy;
+using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared;
+using Volo.Abp.AspNetCore.Serilog;
+using Volo.Abp.AuditLogging.EntityFrameworkCore;
+using Volo.Abp.Autofac;
+using Volo.Abp.Caching;
+using Volo.Abp.Caching.StackExchangeRedis;
+using Volo.Abp.EntityFrameworkCore;
+using Volo.Abp.EntityFrameworkCore.SqlServer;
+using Volo.Abp.Localization;
+using Volo.Abp.Modularity;
+using Volo.Abp.MultiTenancy;
+using Volo.Abp.PermissionManagement.EntityFrameworkCore;
+using Volo.Abp.Security.Claims;
+using Volo.Abp.SettingManagement.EntityFrameworkCore;
+using Volo.Abp.VirtualFileSystem;
+
+namespace Volo.CmsKit
+{
+ [DependsOn(
+ typeof(CmsKitApplicationModule),
+ typeof(CmsKitEntityFrameworkCoreModule),
+ typeof(CmsKitHttpApiModule),
+ typeof(AbpAspNetCoreMvcUiMultiTenancyModule),
+ typeof(AbpAutofacModule),
+ typeof(AbpCachingStackExchangeRedisModule),
+ typeof(AbpEntityFrameworkCoreSqlServerModule),
+ typeof(AbpAuditLoggingEntityFrameworkCoreModule),
+ typeof(AbpPermissionManagementEntityFrameworkCoreModule),
+ typeof(AbpSettingManagementEntityFrameworkCoreModule),
+ typeof(AbpAspNetCoreSerilogModule)
+ )]
+ public class CmsKitHttpApiHostModule : AbpModule
+ {
+ private const string DefaultCorsPolicyName = "Default";
+
+ public override void ConfigureServices(ServiceConfigurationContext context)
+ {
+ var hostingEnvironment = context.Services.GetHostingEnvironment();
+ var configuration = context.Services.GetConfiguration();
+
+ Configure(options =>
+ {
+ options.UseSqlServer();
+ });
+
+ Configure(options =>
+ {
+ options.IsEnabled = MultiTenancyConsts.IsEnabled;
+ });
+
+ if (hostingEnvironment.IsDevelopment())
+ {
+ Configure(options =>
+ {
+ options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}..{0}src{0}Volo.CmsKit.Domain.Shared", Path.DirectorySeparatorChar)));
+ options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}..{0}src{0}Volo.CmsKit.Domain", Path.DirectorySeparatorChar)));
+ options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}..{0}src{0}Volo.CmsKit.Application.Contracts", Path.DirectorySeparatorChar)));
+ options.FileSets.ReplaceEmbeddedByPhysical(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}..{0}src{0}Volo.CmsKit.Application", Path.DirectorySeparatorChar)));
+ });
+ }
+
+ context.Services.AddSwaggerGen(
+ options =>
+ {
+ options.SwaggerDoc("v1", new OpenApiInfo { Title = "CmsKit API", Version = "v1" });
+ options.DocInclusionPredicate((docName, description) => true);
+ options.CustomSchemaIds(type => type.FullName);
+ });
+
+ Configure(options =>
+ {
+ options.Languages.Add(new LanguageInfo("cs", "cs", "Čeština"));
+ options.Languages.Add(new LanguageInfo("en", "en", "English"));
+ options.Languages.Add(new LanguageInfo("pt-BR", "pt-BR", "Português"));
+ options.Languages.Add(new LanguageInfo("ru", "ru", "Русский"));
+ options.Languages.Add(new LanguageInfo("tr", "tr", "Türkçe"));
+ options.Languages.Add(new LanguageInfo("zh-Hans", "zh-Hans", "简体中文"));
+ options.Languages.Add(new LanguageInfo("zh-Hant", "zh-Hant", "繁體中文"));
+ });
+
+ //Updates AbpClaimTypes to be compatible with identity server claims.
+ AbpClaimTypes.UserId = JwtClaimTypes.Subject;
+ AbpClaimTypes.UserName = JwtClaimTypes.Name;
+ AbpClaimTypes.Role = JwtClaimTypes.Role;
+ AbpClaimTypes.Email = JwtClaimTypes.Email;
+
+ context.Services.AddAuthentication("Bearer")
+ .AddIdentityServerAuthentication(options =>
+ {
+ options.Authority = configuration["AuthServer:Authority"];
+ options.RequireHttpsMetadata = false;
+ options.ApiName = "CmsKit";
+ });
+
+ Configure(options =>
+ {
+ options.KeyPrefix = "CmsKit:";
+ });
+
+ if (!hostingEnvironment.IsDevelopment())
+ {
+ var redis = ConnectionMultiplexer.Connect(configuration["Redis:Configuration"]);
+ context.Services
+ .AddDataProtection()
+ .PersistKeysToStackExchangeRedis(redis, "CmsKit-Protection-Keys");
+ }
+
+ context.Services.AddCors(options =>
+ {
+ options.AddPolicy(DefaultCorsPolicyName, builder =>
+ {
+ builder
+ .WithOrigins(
+ configuration["App:CorsOrigins"]
+ .Split(",", StringSplitOptions.RemoveEmptyEntries)
+ .Select(o => o.RemovePostFix("/"))
+ .ToArray()
+ )
+ .WithAbpExposedHeaders()
+ .SetIsOriginAllowedToAllowWildcardSubdomains()
+ .AllowAnyHeader()
+ .AllowAnyMethod()
+ .AllowCredentials();
+ });
+ });
+ }
+
+ public override void OnApplicationInitialization(ApplicationInitializationContext context)
+ {
+ var app = context.GetApplicationBuilder();
+ var env = context.GetEnvironment();
+
+ if (env.IsDevelopment())
+ {
+ app.UseDeveloperExceptionPage();
+ }
+ else
+ {
+ app.UseErrorPage();
+ app.UseHsts();
+ }
+
+ app.UseHttpsRedirection();
+ app.UseCorrelationId();
+ app.UseVirtualFiles();
+ app.UseRouting();
+ app.UseCors(DefaultCorsPolicyName);
+ app.UseAuthentication();
+ app.UseAbpClaimsMap();
+ if (MultiTenancyConsts.IsEnabled)
+ {
+ app.UseMultiTenancy();
+ }
+ app.UseAbpRequestLocalization();
+ app.UseAuthorization();
+ app.UseSwagger();
+ app.UseSwaggerUI(options =>
+ {
+ options.SwaggerEndpoint("/swagger/v1/swagger.json", "Support APP API");
+ });
+ app.UseAuditing();
+ app.UseAbpSerilogEnrichers();
+ app.UseConfiguredEndpoints();
+ }
+ }
+}
diff --git a/modules/cms-kit/host/Volo.CmsKit.HttpApi.Host/Controllers/HomeController.cs b/modules/cms-kit/host/Volo.CmsKit.HttpApi.Host/Controllers/HomeController.cs
new file mode 100644
index 0000000000..a9d544e8af
--- /dev/null
+++ b/modules/cms-kit/host/Volo.CmsKit.HttpApi.Host/Controllers/HomeController.cs
@@ -0,0 +1,13 @@
+using Microsoft.AspNetCore.Mvc;
+using Volo.Abp.AspNetCore.Mvc;
+
+namespace Volo.CmsKit.Controllers
+{
+ public class HomeController : AbpController
+ {
+ public ActionResult Index()
+ {
+ return Redirect("~/swagger");
+ }
+ }
+}
diff --git a/modules/cms-kit/host/Volo.CmsKit.HttpApi.Host/Dockerfile b/modules/cms-kit/host/Volo.CmsKit.HttpApi.Host/Dockerfile
new file mode 100644
index 0000000000..c13abce9a3
--- /dev/null
+++ b/modules/cms-kit/host/Volo.CmsKit.HttpApi.Host/Dockerfile
@@ -0,0 +1,18 @@
+FROM mcr.microsoft.com/dotnet/core/aspnet:3.0-buster-slim AS base
+WORKDIR /app
+EXPOSE 80
+
+FROM mcr.microsoft.com/dotnet/core/sdk:3.0-buster AS build
+WORKDIR /src
+COPY . .
+WORKDIR /src/templates/service/host/Volo.CmsKit.HttpApi.Host
+RUN dotnet restore -nowarn:msb3202,nu1503
+RUN dotnet build --no-restore -c Release -o /app
+
+FROM build AS publish
+RUN dotnet publish --no-restore -c Release -o /app
+
+FROM base AS final
+WORKDIR /app
+COPY --from=publish /app .
+ENTRYPOINT ["dotnet", "Volo.CmsKit.HttpApi.Host.dll"]
diff --git a/modules/cms-kit/host/Volo.CmsKit.HttpApi.Host/EntityFrameworkCore/CmsKitHttpApiHostMigrationsDbContext.cs b/modules/cms-kit/host/Volo.CmsKit.HttpApi.Host/EntityFrameworkCore/CmsKitHttpApiHostMigrationsDbContext.cs
new file mode 100644
index 0000000000..c31c977ebe
--- /dev/null
+++ b/modules/cms-kit/host/Volo.CmsKit.HttpApi.Host/EntityFrameworkCore/CmsKitHttpApiHostMigrationsDbContext.cs
@@ -0,0 +1,21 @@
+using Microsoft.EntityFrameworkCore;
+using Volo.Abp.EntityFrameworkCore;
+
+namespace Volo.CmsKit.EntityFrameworkCore
+{
+ public class CmsKitHttpApiHostMigrationsDbContext : AbpDbContext
+ {
+ public CmsKitHttpApiHostMigrationsDbContext(DbContextOptions options)
+ : base(options)
+ {
+
+ }
+
+ protected override void OnModelCreating(ModelBuilder modelBuilder)
+ {
+ base.OnModelCreating(modelBuilder);
+
+ modelBuilder.ConfigureCmsKit();
+ }
+ }
+}
diff --git a/modules/cms-kit/host/Volo.CmsKit.HttpApi.Host/EntityFrameworkCore/CmsKitHttpApiHostMigrationsDbContextFactory.cs b/modules/cms-kit/host/Volo.CmsKit.HttpApi.Host/EntityFrameworkCore/CmsKitHttpApiHostMigrationsDbContextFactory.cs
new file mode 100644
index 0000000000..3a6dbb47ad
--- /dev/null
+++ b/modules/cms-kit/host/Volo.CmsKit.HttpApi.Host/EntityFrameworkCore/CmsKitHttpApiHostMigrationsDbContextFactory.cs
@@ -0,0 +1,29 @@
+using System.IO;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Design;
+using Microsoft.Extensions.Configuration;
+
+namespace Volo.CmsKit.EntityFrameworkCore
+{
+ public class CmsKitHttpApiHostMigrationsDbContextFactory : IDesignTimeDbContextFactory
+ {
+ public CmsKitHttpApiHostMigrationsDbContext CreateDbContext(string[] args)
+ {
+ var configuration = BuildConfiguration();
+
+ var builder = new DbContextOptionsBuilder()
+ .UseSqlServer(configuration.GetConnectionString("CmsKit"));
+
+ return new CmsKitHttpApiHostMigrationsDbContext(builder.Options);
+ }
+
+ private static IConfigurationRoot BuildConfiguration()
+ {
+ var builder = new ConfigurationBuilder()
+ .SetBasePath(Directory.GetCurrentDirectory())
+ .AddJsonFile("appsettings.json", optional: false);
+
+ return builder.Build();
+ }
+ }
+}
diff --git a/modules/cms-kit/host/Volo.CmsKit.HttpApi.Host/Program.cs b/modules/cms-kit/host/Volo.CmsKit.HttpApi.Host/Program.cs
new file mode 100644
index 0000000000..7349f8eb0c
--- /dev/null
+++ b/modules/cms-kit/host/Volo.CmsKit.HttpApi.Host/Program.cs
@@ -0,0 +1,51 @@
+using System;
+using System.IO;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.Hosting;
+using Serilog;
+using Serilog.Events;
+
+namespace Volo.CmsKit
+{
+ public class Program
+ {
+ public static int Main(string[] args)
+ {
+ Log.Logger = new LoggerConfiguration()
+#if DEBUG
+ .MinimumLevel.Debug()
+#else
+ .MinimumLevel.Information()
+#endif
+ .MinimumLevel.Override("Microsoft", LogEventLevel.Information)
+ .Enrich.FromLogContext()
+ .WriteTo.File("Logs/logs.txt")
+ .CreateLogger();
+
+ try
+ {
+ Log.Information("Starting web host.");
+ CreateHostBuilder(args).Build().Run();
+ return 0;
+ }
+ catch (Exception ex)
+ {
+ Log.Fatal(ex, "Host terminated unexpectedly!");
+ return 1;
+ }
+ finally
+ {
+ Log.CloseAndFlush();
+ }
+ }
+
+ internal static IHostBuilder CreateHostBuilder(string[] args) =>
+ Host.CreateDefaultBuilder(args)
+ .ConfigureWebHostDefaults(webBuilder =>
+ {
+ webBuilder.UseStartup();
+ })
+ .UseAutofac()
+ .UseSerilog();
+ }
+}
diff --git a/modules/cms-kit/host/Volo.CmsKit.HttpApi.Host/Properties/launchSettings.json b/modules/cms-kit/host/Volo.CmsKit.HttpApi.Host/Properties/launchSettings.json
new file mode 100644
index 0000000000..48d1823cea
--- /dev/null
+++ b/modules/cms-kit/host/Volo.CmsKit.HttpApi.Host/Properties/launchSettings.json
@@ -0,0 +1,27 @@
+{
+ "iisSettings": {
+ "windowsAuthentication": false,
+ "anonymousAuthentication": true,
+ "iisExpress": {
+ "applicationUrl": "https://localhost:44371",
+ "sslPort": 44371
+ }
+ },
+ "profiles": {
+ "IIS Express": {
+ "commandName": "IISExpress",
+ "launchBrowser": true,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "Volo.CmsKit.DemoApp": {
+ "commandName": "Project",
+ "launchBrowser": true,
+ "applicationUrl": "https://localhost:44371",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/modules/cms-kit/host/Volo.CmsKit.HttpApi.Host/Startup.cs b/modules/cms-kit/host/Volo.CmsKit.HttpApi.Host/Startup.cs
new file mode 100644
index 0000000000..bfbaaadfa4
--- /dev/null
+++ b/modules/cms-kit/host/Volo.CmsKit.HttpApi.Host/Startup.cs
@@ -0,0 +1,21 @@
+using System;
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Logging;
+
+namespace Volo.CmsKit
+{
+ public class Startup
+ {
+ public void ConfigureServices(IServiceCollection services)
+ {
+ services.AddApplication();
+ }
+
+ public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory)
+ {
+ app.InitializeApplication();
+ }
+ }
+}
diff --git a/modules/cms-kit/host/Volo.CmsKit.HttpApi.Host/Volo.CmsKit.HttpApi.Host.csproj b/modules/cms-kit/host/Volo.CmsKit.HttpApi.Host/Volo.CmsKit.HttpApi.Host.csproj
new file mode 100644
index 0000000000..3fb091137d
--- /dev/null
+++ b/modules/cms-kit/host/Volo.CmsKit.HttpApi.Host/Volo.CmsKit.HttpApi.Host.csproj
@@ -0,0 +1,43 @@
+
+
+
+
+
+ netcoreapp3.1
+ Volo.CmsKit
+ true
+ Volo.CmsKit-c2d31439-b723-48e2-b061-5ebd7aeb6010
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/cms-kit/host/Volo.CmsKit.HttpApi.Host/appsettings.json b/modules/cms-kit/host/Volo.CmsKit.HttpApi.Host/appsettings.json
new file mode 100644
index 0000000000..e7fade92a5
--- /dev/null
+++ b/modules/cms-kit/host/Volo.CmsKit.HttpApi.Host/appsettings.json
@@ -0,0 +1,15 @@
+{
+ "App": {
+ "CorsOrigins": "https://*.CmsKit.com,http://localhost:4200"
+ },
+ "ConnectionStrings": {
+ "Default": "Server=(LocalDb)\\MSSQLLocalDB;Database=CmsKit_Main;Trusted_Connection=True;MultipleActiveResultSets=true",
+ "CmsKit": "Server=(LocalDb)\\MSSQLLocalDB;Database=CmsKit_Module;Trusted_Connection=True;MultipleActiveResultSets=true"
+ },
+ "Redis": {
+ "Configuration": "127.0.0.1"
+ },
+ "AuthServer": {
+ "Authority": "https://localhost:44318/"
+ }
+}
diff --git a/modules/cms-kit/host/Volo.CmsKit.HttpApi.Host/yarn.lock b/modules/cms-kit/host/Volo.CmsKit.HttpApi.Host/yarn.lock
new file mode 100644
index 0000000000..fb57ccd13a
--- /dev/null
+++ b/modules/cms-kit/host/Volo.CmsKit.HttpApi.Host/yarn.lock
@@ -0,0 +1,4 @@
+# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
+# yarn lockfile v1
+
+
diff --git a/modules/cms-kit/host/Volo.CmsKit.IdentityServer/CmsKitIdentityServerModule.cs b/modules/cms-kit/host/Volo.CmsKit.IdentityServer/CmsKitIdentityServerModule.cs
new file mode 100644
index 0000000000..faf90a3fc2
--- /dev/null
+++ b/modules/cms-kit/host/Volo.CmsKit.IdentityServer/CmsKitIdentityServerModule.cs
@@ -0,0 +1,222 @@
+using System;
+using System.Linq;
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Cors;
+using Microsoft.AspNetCore.DataProtection;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
+using Volo.CmsKit.MultiTenancy;
+using StackExchange.Redis;
+using Microsoft.OpenApi.Models;
+using Swashbuckle.AspNetCore.Swagger;
+using Volo.Abp;
+using Volo.Abp.Account;
+using Volo.Abp.Account.Web;
+using Volo.Abp.AspNetCore.Authentication.JwtBearer;
+using Volo.Abp.AspNetCore.Mvc;
+using Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy;
+using Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic;
+using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared;
+using Volo.Abp.AspNetCore.Serilog;
+using Volo.Abp.Auditing;
+using Volo.Abp.AuditLogging.EntityFrameworkCore;
+using Volo.Abp.Autofac;
+using Volo.Abp.Caching;
+using Volo.Abp.Caching.StackExchangeRedis;
+using Volo.Abp.Data;
+using Volo.Abp.EntityFrameworkCore;
+using Volo.Abp.EntityFrameworkCore.SqlServer;
+using Volo.Abp.FeatureManagement;
+using Volo.Abp.Identity;
+using Volo.Abp.Identity.EntityFrameworkCore;
+using Volo.Abp.IdentityServer.EntityFrameworkCore;
+using Volo.Abp.Localization;
+using Volo.Abp.Modularity;
+using Volo.Abp.MultiTenancy;
+using Volo.Abp.PermissionManagement;
+using Volo.Abp.PermissionManagement.EntityFrameworkCore;
+using Volo.Abp.PermissionManagement.HttpApi;
+using Volo.Abp.PermissionManagement.Identity;
+using Volo.Abp.SettingManagement.EntityFrameworkCore;
+using Volo.Abp.TenantManagement;
+using Volo.Abp.TenantManagement.EntityFrameworkCore;
+using Volo.Abp.Threading;
+using Volo.Abp.UI.Navigation.Urls;
+
+namespace Volo.CmsKit
+{
+ [DependsOn(
+ typeof(AbpAccountWebIdentityServerModule),
+ typeof(AbpAccountApplicationModule),
+ typeof(AbpAspNetCoreMvcUiMultiTenancyModule),
+ typeof(AbpAspNetCoreMvcModule),
+ typeof(AbpAspNetCoreMvcUiBasicThemeModule),
+ typeof(AbpAuditLoggingEntityFrameworkCoreModule),
+ typeof(AbpAutofacModule),
+ typeof(AbpCachingStackExchangeRedisModule),
+ typeof(AbpEntityFrameworkCoreSqlServerModule),
+ typeof(AbpIdentityEntityFrameworkCoreModule),
+ typeof(AbpIdentityApplicationModule),
+ typeof(AbpIdentityHttpApiModule),
+ typeof(AbpIdentityServerEntityFrameworkCoreModule),
+ typeof(AbpPermissionManagementDomainIdentityModule),
+ typeof(AbpPermissionManagementEntityFrameworkCoreModule),
+ typeof(AbpPermissionManagementApplicationModule),
+ typeof(AbpPermissionManagementHttpApiModule),
+ typeof(AbpSettingManagementEntityFrameworkCoreModule),
+ typeof(AbpFeatureManagementApplicationModule),
+ typeof(AbpTenantManagementEntityFrameworkCoreModule),
+ typeof(AbpTenantManagementApplicationModule),
+ typeof(AbpTenantManagementHttpApiModule),
+ typeof(AbpAspNetCoreAuthenticationJwtBearerModule),
+ typeof(CmsKitApplicationContractsModule),
+ typeof(AbpAspNetCoreSerilogModule)
+ )]
+ public class CmsKitIdentityServerModule : AbpModule
+ {
+ private const string DefaultCorsPolicyName = "Default";
+
+ public override void ConfigureServices(ServiceConfigurationContext context)
+ {
+ var hostingEnvironment = context.Services.GetHostingEnvironment();
+ var configuration = context.Services.GetConfiguration();
+
+ Configure(options =>
+ {
+ options.UseSqlServer();
+ });
+
+ context.Services.AddSwaggerGen(
+ options =>
+ {
+ options.SwaggerDoc("v1", new OpenApiInfo { Title = "CmsKit API", Version = "v1" });
+ options.DocInclusionPredicate((docName, description) => true);
+ options.CustomSchemaIds(type => type.FullName);
+ });
+
+ Configure(options =>
+ {
+ options.Languages.Add(new LanguageInfo("cs", "cs", "Čeština"));
+ options.Languages.Add(new LanguageInfo("en", "en", "English"));
+ options.Languages.Add(new LanguageInfo("pt-BR", "pt-BR", "Português"));
+ options.Languages.Add(new LanguageInfo("ru", "ru", "Русский"));
+ options.Languages.Add(new LanguageInfo("tr", "tr", "Türkçe"));
+ options.Languages.Add(new LanguageInfo("zh-Hans", "zh-Hans", "简体中文"));
+ options.Languages.Add(new LanguageInfo("zh-Hant", "zh-Hant", "繁體中文"));
+ });
+
+ Configure(options =>
+ {
+ //options.IsEnabledForGetRequests = true;
+ options.ApplicationName = "AuthServer";
+ });
+
+ Configure(options =>
+ {
+ options.Applications["MVC"].RootUrl = configuration["App:SelfUrl"];
+ });
+
+ context.Services.AddAuthentication()
+ .AddIdentityServerAuthentication(options =>
+ {
+ options.Authority = configuration["AuthServer:Authority"];
+ options.RequireHttpsMetadata = false;
+ options.ApiName = configuration["AuthServer:ApiName"];
+ });
+
+ Configure(options =>
+ {
+ options.KeyPrefix = "CmsKit:";
+ });
+
+ Configure(options =>
+ {
+ options.IsEnabled = MultiTenancyConsts.IsEnabled;
+ });
+
+ if (!hostingEnvironment.IsDevelopment())
+ {
+ var redis = ConnectionMultiplexer.Connect(configuration["Redis:Configuration"]);
+ context.Services
+ .AddDataProtection()
+ .PersistKeysToStackExchangeRedis(redis, "CmsKit-Protection-Keys");
+ }
+
+ context.Services.AddCors(options =>
+ {
+ options.AddPolicy(DefaultCorsPolicyName, builder =>
+ {
+ builder
+ .WithOrigins(
+ configuration["App:CorsOrigins"]
+ .Split(",", StringSplitOptions.RemoveEmptyEntries)
+ .Select(o => o.RemovePostFix("/"))
+ .ToArray()
+ )
+ .WithAbpExposedHeaders()
+ .SetIsOriginAllowedToAllowWildcardSubdomains()
+ .AllowAnyHeader()
+ .AllowAnyMethod()
+ .AllowCredentials();
+ });
+ });
+ }
+
+ public override void OnApplicationInitialization(ApplicationInitializationContext context)
+ {
+ var app = context.GetApplicationBuilder();
+ var env = context.GetEnvironment();
+
+ if (env.IsDevelopment())
+ {
+ app.UseDeveloperExceptionPage();
+ }
+ else
+ {
+ app.UseErrorPage();
+ app.UseHsts();
+ }
+
+ app.UseHttpsRedirection();
+ app.UseCorrelationId();
+ app.UseVirtualFiles();
+ app.UseRouting();
+ app.UseCors(DefaultCorsPolicyName);
+ app.UseAuthentication();
+ app.UseJwtTokenMiddleware();
+
+ if (MultiTenancyConsts.IsEnabled)
+ {
+ app.UseMultiTenancy();
+ }
+
+ app.UseAbpRequestLocalization();
+ app.UseIdentityServer();
+ app.UseAuthorization();
+ app.UseSwagger();
+ app.UseSwaggerUI(options =>
+ {
+ options.SwaggerEndpoint("/swagger/v1/swagger.json", "Support APP API");
+ });
+ app.UseAuditing();
+ app.UseAbpSerilogEnrichers();
+ app.UseConfiguredEndpoints();
+
+ SeedData(context);
+ }
+
+ private void SeedData(ApplicationInitializationContext context)
+ {
+ AsyncHelper.RunSync(async () =>
+ {
+ using (var scope = context.ServiceProvider.CreateScope())
+ {
+ await scope.ServiceProvider
+ .GetRequiredService()
+ .SeedAsync();
+ }
+ });
+ }
+ }
+}
diff --git a/modules/cms-kit/host/Volo.CmsKit.IdentityServer/Dockerfile b/modules/cms-kit/host/Volo.CmsKit.IdentityServer/Dockerfile
new file mode 100644
index 0000000000..bc353a0abd
--- /dev/null
+++ b/modules/cms-kit/host/Volo.CmsKit.IdentityServer/Dockerfile
@@ -0,0 +1,18 @@
+FROM mcr.microsoft.com/dotnet/core/aspnet:3.0-buster-slim AS base
+WORKDIR /app
+EXPOSE 80
+
+FROM mcr.microsoft.com/dotnet/core/sdk:3.0-buster AS build
+WORKDIR /src
+COPY . .
+WORKDIR /src/templates/service/host/Volo.CmsKit.IdentityServer
+RUN dotnet restore -nowarn:msb3202,nu1503
+RUN dotnet build --no-restore -c Release -o /app
+
+FROM build AS publish
+RUN dotnet publish --no-restore -c Release -o /app
+
+FROM base AS final
+WORKDIR /app
+COPY --from=publish /app .
+ENTRYPOINT ["dotnet", "Volo.CmsKit.IdentityServer.dll"]
diff --git a/modules/cms-kit/host/Volo.CmsKit.IdentityServer/EntityFrameworkCore/IdentityServerHostMigrationsDbContext.cs b/modules/cms-kit/host/Volo.CmsKit.IdentityServer/EntityFrameworkCore/IdentityServerHostMigrationsDbContext.cs
new file mode 100644
index 0000000000..b0bd516dee
--- /dev/null
+++ b/modules/cms-kit/host/Volo.CmsKit.IdentityServer/EntityFrameworkCore/IdentityServerHostMigrationsDbContext.cs
@@ -0,0 +1,32 @@
+using Microsoft.EntityFrameworkCore;
+using Volo.Abp.AuditLogging.EntityFrameworkCore;
+using Volo.Abp.EntityFrameworkCore;
+using Volo.Abp.Identity.EntityFrameworkCore;
+using Volo.Abp.IdentityServer.EntityFrameworkCore;
+using Volo.Abp.PermissionManagement.EntityFrameworkCore;
+using Volo.Abp.SettingManagement.EntityFrameworkCore;
+using Volo.Abp.TenantManagement.EntityFrameworkCore;
+
+namespace Volo.CmsKit.EntityFrameworkCore
+{
+ public class IdentityServerHostMigrationsDbContext : AbpDbContext
+ {
+ public IdentityServerHostMigrationsDbContext(DbContextOptions options)
+ : base(options)
+ {
+
+ }
+
+ protected override void OnModelCreating(ModelBuilder modelBuilder)
+ {
+ base.OnModelCreating(modelBuilder);
+
+ modelBuilder.ConfigurePermissionManagement();
+ modelBuilder.ConfigureSettingManagement();
+ modelBuilder.ConfigureAuditLogging();
+ modelBuilder.ConfigureIdentity();
+ modelBuilder.ConfigureIdentityServer();
+ modelBuilder.ConfigureTenantManagement();
+ }
+ }
+}
diff --git a/modules/cms-kit/host/Volo.CmsKit.IdentityServer/EntityFrameworkCore/IdentityServerHostMigrationsDbContextFactory.cs b/modules/cms-kit/host/Volo.CmsKit.IdentityServer/EntityFrameworkCore/IdentityServerHostMigrationsDbContextFactory.cs
new file mode 100644
index 0000000000..f6e80d62ec
--- /dev/null
+++ b/modules/cms-kit/host/Volo.CmsKit.IdentityServer/EntityFrameworkCore/IdentityServerHostMigrationsDbContextFactory.cs
@@ -0,0 +1,29 @@
+using System.IO;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Design;
+using Microsoft.Extensions.Configuration;
+
+namespace Volo.CmsKit.EntityFrameworkCore
+{
+ public class IdentityServerHostMigrationsDbContextFactory : IDesignTimeDbContextFactory
+ {
+ public IdentityServerHostMigrationsDbContext CreateDbContext(string[] args)
+ {
+ var configuration = BuildConfiguration();
+
+ var builder = new DbContextOptionsBuilder()
+ .UseSqlServer(configuration.GetConnectionString("Default"));
+
+ return new IdentityServerHostMigrationsDbContext(builder.Options);
+ }
+
+ private static IConfigurationRoot BuildConfiguration()
+ {
+ var builder = new ConfigurationBuilder()
+ .SetBasePath(Directory.GetCurrentDirectory())
+ .AddJsonFile("appsettings.json", optional: false);
+
+ return builder.Build();
+ }
+ }
+}
diff --git a/modules/cms-kit/host/Volo.CmsKit.IdentityServer/IdentityServer/IdentityServerDataSeedContributor.cs b/modules/cms-kit/host/Volo.CmsKit.IdentityServer/IdentityServer/IdentityServerDataSeedContributor.cs
new file mode 100644
index 0000000000..c245c663f8
--- /dev/null
+++ b/modules/cms-kit/host/Volo.CmsKit.IdentityServer/IdentityServer/IdentityServerDataSeedContributor.cs
@@ -0,0 +1,218 @@
+using Microsoft.Extensions.Configuration;
+using System;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using Volo.Abp.Authorization.Permissions;
+using Volo.Abp.Data;
+using Volo.Abp.DependencyInjection;
+using Volo.Abp.Guids;
+using Volo.Abp.IdentityServer.ApiResources;
+using Volo.Abp.IdentityServer.Clients;
+using Volo.Abp.IdentityServer.IdentityResources;
+using Volo.Abp.PermissionManagement;
+using Volo.Abp.Uow;
+
+namespace Volo.CmsKit.IdentityServer
+{
+ public class IdentityServerDataSeedContributor : IDataSeedContributor, ITransientDependency
+ {
+ private readonly IApiResourceRepository _apiResourceRepository;
+ private readonly IClientRepository _clientRepository;
+ private readonly IIdentityResourceDataSeeder _identityResourceDataSeeder;
+ private readonly IGuidGenerator _guidGenerator;
+ private readonly IPermissionDataSeeder _permissionDataSeeder;
+ private readonly IConfiguration _configuration;
+
+ public IdentityServerDataSeedContributor(
+ IClientRepository clientRepository,
+ IApiResourceRepository apiResourceRepository,
+ IIdentityResourceDataSeeder identityResourceDataSeeder,
+ IGuidGenerator guidGenerator,
+ IPermissionDataSeeder permissionDataSeeder,
+ IConfiguration configuration)
+ {
+ _clientRepository = clientRepository;
+ _apiResourceRepository = apiResourceRepository;
+ _identityResourceDataSeeder = identityResourceDataSeeder;
+ _guidGenerator = guidGenerator;
+ _permissionDataSeeder = permissionDataSeeder;
+ _configuration = configuration;
+ }
+
+ [UnitOfWork]
+ public virtual async Task SeedAsync(DataSeedContext context)
+ {
+ await _identityResourceDataSeeder.CreateStandardResourcesAsync();
+ await CreateApiResourcesAsync();
+ await CreateClientsAsync();
+ }
+
+ private async Task CreateApiResourcesAsync()
+ {
+ var commonApiUserClaims = new[]
+ {
+ "email",
+ "email_verified",
+ "name",
+ "phone_number",
+ "phone_number_verified",
+ "role"
+ };
+
+ await CreateApiResourceAsync("CmsKit", commonApiUserClaims);
+ }
+
+ private async Task CreateApiResourceAsync(string name, IEnumerable claims)
+ {
+ var apiResource = await _apiResourceRepository.FindByNameAsync(name);
+ if (apiResource == null)
+ {
+ apiResource = await _apiResourceRepository.InsertAsync(
+ new ApiResource(
+ _guidGenerator.Create(),
+ name,
+ name + " API"
+ ),
+ autoSave: true
+ );
+ }
+
+ foreach (var claim in claims)
+ {
+ if (apiResource.FindClaim(claim) == null)
+ {
+ apiResource.AddUserClaim(claim);
+ }
+ }
+
+ return await _apiResourceRepository.UpdateAsync(apiResource);
+ }
+
+ private async Task CreateClientsAsync()
+ {
+ const string commonSecret = "E5Xd4yMqjP5kjWFKrYgySBju6JVfCzMyFp7n2QmMrME=";
+
+ var commonScopes = new[]
+ {
+ "email",
+ "openid",
+ "profile",
+ "role",
+ "phone",
+ "address",
+ "CmsKit"
+ };
+
+ var configurationSection = _configuration.GetSection("IdentityServer:Clients");
+
+ //Web Client
+ var webClientId = configurationSection["CmsKit_Web:ClientId"];
+ if (!webClientId.IsNullOrWhiteSpace())
+ {
+ var webClientRootUrl = configurationSection["CmsKit_Web:RootUrl"].EnsureEndsWith('/');
+ await CreateClientAsync(
+ webClientId,
+ commonScopes,
+ new[] { "hybrid" },
+ commonSecret,
+ redirectUri: $"{webClientRootUrl}signin-oidc",
+ postLogoutRedirectUri: $"{webClientRootUrl}signout-callback-oidc"
+ );
+ }
+
+ //Console Test Client
+ var consoleClientId = configurationSection["CmsKit_ConsoleTestApp:ClientId"];
+ if (!consoleClientId.IsNullOrWhiteSpace())
+ {
+ await CreateClientAsync(
+ consoleClientId,
+ commonScopes,
+ new[] { "password", "client_credentials" },
+ commonSecret
+ );
+ }
+ }
+
+ private async Task CreateClientAsync(
+ string name,
+ IEnumerable scopes,
+ IEnumerable grantTypes,
+ string secret,
+ string redirectUri = null,
+ string postLogoutRedirectUri = null,
+ IEnumerable permissions = null)
+ {
+ var client = await _clientRepository.FindByCliendIdAsync(name);
+ if (client == null)
+ {
+ client = await _clientRepository.InsertAsync(
+ new Client(
+ _guidGenerator.Create(),
+ name
+ )
+ {
+ ClientName = name,
+ ProtocolType = "oidc",
+ Description = name,
+ AlwaysIncludeUserClaimsInIdToken = true,
+ AllowOfflineAccess = true,
+ AbsoluteRefreshTokenLifetime = 31536000, //365 days
+ AccessTokenLifetime = 31536000, //365 days
+ AuthorizationCodeLifetime = 300,
+ IdentityTokenLifetime = 300,
+ RequireConsent = false
+ },
+ autoSave: true
+ );
+ }
+
+ foreach (var scope in scopes)
+ {
+ if (client.FindScope(scope) == null)
+ {
+ client.AddScope(scope);
+ }
+ }
+
+ foreach (var grantType in grantTypes)
+ {
+ if (client.FindGrantType(grantType) == null)
+ {
+ client.AddGrantType(grantType);
+ }
+ }
+
+ if (client.FindSecret(secret) == null)
+ {
+ client.AddSecret(secret);
+ }
+
+ if (redirectUri != null)
+ {
+ if (client.FindRedirectUri(redirectUri) == null)
+ {
+ client.AddRedirectUri(redirectUri);
+ }
+ }
+
+ if (postLogoutRedirectUri != null)
+ {
+ if (client.FindPostLogoutRedirectUri(postLogoutRedirectUri) == null)
+ {
+ client.AddPostLogoutRedirectUri(postLogoutRedirectUri);
+ }
+ }
+
+ if (permissions != null)
+ {
+ await _permissionDataSeeder.SeedAsync(
+ ClientPermissionValueProvider.ProviderName,
+ name,
+ permissions
+ );
+ }
+
+ return await _clientRepository.UpdateAsync(client);
+ }
+ }
+}
diff --git a/modules/cms-kit/host/Volo.CmsKit.IdentityServer/Migrations/20200624023331_Initial.Designer.cs b/modules/cms-kit/host/Volo.CmsKit.IdentityServer/Migrations/20200624023331_Initial.Designer.cs
new file mode 100644
index 0000000000..406a3d3f68
--- /dev/null
+++ b/modules/cms-kit/host/Volo.CmsKit.IdentityServer/Migrations/20200624023331_Initial.Designer.cs
@@ -0,0 +1,1861 @@
+//
+using System;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Metadata;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+using Volo.CmsKit.EntityFrameworkCore;
+using Volo.Abp.EntityFrameworkCore;
+
+namespace Volo.CmsKit.Migrations
+{
+ [DbContext(typeof(IdentityServerHostMigrationsDbContext))]
+ [Migration("20200624023331_Initial")]
+ partial class Initial
+ {
+ protected override void BuildTargetModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder
+ .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.SqlServer)
+ .HasAnnotation("ProductVersion", "3.1.5")
+ .HasAnnotation("Relational:MaxIdentifierLength", 128)
+ .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
+
+ modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLog", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("ApplicationName")
+ .HasColumnName("ApplicationName")
+ .HasColumnType("nvarchar(96)")
+ .HasMaxLength(96);
+
+ b.Property("BrowserInfo")
+ .HasColumnName("BrowserInfo")
+ .HasColumnType("nvarchar(512)")
+ .HasMaxLength(512);
+
+ b.Property("ClientId")
+ .HasColumnName("ClientId")
+ .HasColumnType("nvarchar(64)")
+ .HasMaxLength(64);
+
+ b.Property("ClientIpAddress")
+ .HasColumnName("ClientIpAddress")
+ .HasColumnType("nvarchar(64)")
+ .HasMaxLength(64);
+
+ b.Property("ClientName")
+ .HasColumnName("ClientName")
+ .HasColumnType("nvarchar(128)")
+ .HasMaxLength(128);
+
+ b.Property("Comments")
+ .HasColumnName("Comments")
+ .HasColumnType("nvarchar(256)")
+ .HasMaxLength(256);
+
+ b.Property("ConcurrencyStamp")
+ .IsConcurrencyToken()
+ .HasColumnName("ConcurrencyStamp")
+ .HasColumnType("nvarchar(40)")
+ .HasMaxLength(40);
+
+ b.Property("CorrelationId")
+ .HasColumnName("CorrelationId")
+ .HasColumnType("nvarchar(64)")
+ .HasMaxLength(64);
+
+ b.Property("Exceptions")
+ .HasColumnName("Exceptions")
+ .HasColumnType("nvarchar(4000)")
+ .HasMaxLength(4000);
+
+ b.Property("ExecutionDuration")
+ .HasColumnName("ExecutionDuration")
+ .HasColumnType("int");
+
+ b.Property("ExecutionTime")
+ .HasColumnType("datetime2");
+
+ b.Property("ExtraProperties")
+ .HasColumnName("ExtraProperties")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("HttpMethod")
+ .HasColumnName("HttpMethod")
+ .HasColumnType("nvarchar(16)")
+ .HasMaxLength(16);
+
+ b.Property("HttpStatusCode")
+ .HasColumnName("HttpStatusCode")
+ .HasColumnType("int");
+
+ b.Property("ImpersonatorTenantId")
+ .HasColumnName("ImpersonatorTenantId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("ImpersonatorUserId")
+ .HasColumnName("ImpersonatorUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("TenantId")
+ .HasColumnName("TenantId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("TenantName")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("Url")
+ .HasColumnName("Url")
+ .HasColumnType("nvarchar(256)")
+ .HasMaxLength(256);
+
+ b.Property("UserId")
+ .HasColumnName("UserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("UserName")
+ .HasColumnName("UserName")
+ .HasColumnType("nvarchar(256)")
+ .HasMaxLength(256);
+
+ b.HasKey("Id");
+
+ b.HasIndex("TenantId", "ExecutionTime");
+
+ b.HasIndex("TenantId", "UserId", "ExecutionTime");
+
+ b.ToTable("AbpAuditLogs");
+ });
+
+ modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLogAction", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("AuditLogId")
+ .HasColumnName("AuditLogId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("ExecutionDuration")
+ .HasColumnName("ExecutionDuration")
+ .HasColumnType("int");
+
+ b.Property("ExecutionTime")
+ .HasColumnName("ExecutionTime")
+ .HasColumnType("datetime2");
+
+ b.Property("ExtraProperties")
+ .HasColumnName("ExtraProperties")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("MethodName")
+ .HasColumnName("MethodName")
+ .HasColumnType("nvarchar(128)")
+ .HasMaxLength(128);
+
+ b.Property("Parameters")
+ .HasColumnName("Parameters")
+ .HasColumnType("nvarchar(2000)")
+ .HasMaxLength(2000);
+
+ b.Property("ServiceName")
+ .HasColumnName("ServiceName")
+ .HasColumnType("nvarchar(256)")
+ .HasMaxLength(256);
+
+ b.Property("TenantId")
+ .HasColumnName("TenantId")
+ .HasColumnType("uniqueidentifier");
+
+ b.HasKey("Id");
+
+ b.HasIndex("AuditLogId");
+
+ b.HasIndex("TenantId", "ServiceName", "MethodName", "ExecutionTime");
+
+ b.ToTable("AbpAuditLogActions");
+ });
+
+ modelBuilder.Entity("Volo.Abp.AuditLogging.EntityChange", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("AuditLogId")
+ .HasColumnName("AuditLogId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("ChangeTime")
+ .HasColumnName("ChangeTime")
+ .HasColumnType("datetime2");
+
+ b.Property("ChangeType")
+ .HasColumnName("ChangeType")
+ .HasColumnType("tinyint");
+
+ b.Property("EntityId")
+ .IsRequired()
+ .HasColumnName("EntityId")
+ .HasColumnType("nvarchar(128)")
+ .HasMaxLength(128);
+
+ b.Property("EntityTenantId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("EntityTypeFullName")
+ .IsRequired()
+ .HasColumnName("EntityTypeFullName")
+ .HasColumnType("nvarchar(128)")
+ .HasMaxLength(128);
+
+ b.Property("ExtraProperties")
+ .HasColumnName("ExtraProperties")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("TenantId")
+ .HasColumnName("TenantId")
+ .HasColumnType("uniqueidentifier");
+
+ b.HasKey("Id");
+
+ b.HasIndex("AuditLogId");
+
+ b.HasIndex("TenantId", "EntityTypeFullName", "EntityId");
+
+ b.ToTable("AbpEntityChanges");
+ });
+
+ modelBuilder.Entity("Volo.Abp.AuditLogging.EntityPropertyChange", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("EntityChangeId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("NewValue")
+ .HasColumnName("NewValue")
+ .HasColumnType("nvarchar(512)")
+ .HasMaxLength(512);
+
+ b.Property("OriginalValue")
+ .HasColumnName("OriginalValue")
+ .HasColumnType("nvarchar(512)")
+ .HasMaxLength(512);
+
+ b.Property("PropertyName")
+ .IsRequired()
+ .HasColumnName("PropertyName")
+ .HasColumnType("nvarchar(128)")
+ .HasMaxLength(128);
+
+ b.Property("PropertyTypeFullName")
+ .IsRequired()
+ .HasColumnName("PropertyTypeFullName")
+ .HasColumnType("nvarchar(64)")
+ .HasMaxLength(64);
+
+ b.Property("TenantId")
+ .HasColumnName("TenantId")
+ .HasColumnType("uniqueidentifier");
+
+ b.HasKey("Id");
+
+ b.HasIndex("EntityChangeId");
+
+ b.ToTable("AbpEntityPropertyChanges");
+ });
+
+ modelBuilder.Entity("Volo.Abp.Identity.IdentityClaimType", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("ConcurrencyStamp")
+ .IsConcurrencyToken()
+ .HasColumnName("ConcurrencyStamp")
+ .HasColumnType("nvarchar(40)")
+ .HasMaxLength(40);
+
+ b.Property("Description")
+ .HasColumnType("nvarchar(256)")
+ .HasMaxLength(256);
+
+ b.Property("ExtraProperties")
+ .HasColumnName("ExtraProperties")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("IsStatic")
+ .HasColumnType("bit");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasColumnType("nvarchar(256)")
+ .HasMaxLength(256);
+
+ b.Property("Regex")
+ .HasColumnType("nvarchar(512)")
+ .HasMaxLength(512);
+
+ b.Property("RegexDescription")
+ .HasColumnType("nvarchar(128)")
+ .HasMaxLength(128);
+
+ b.Property("Required")
+ .HasColumnType("bit");
+
+ b.Property("ValueType")
+ .HasColumnType("int");
+
+ b.HasKey("Id");
+
+ b.ToTable("AbpClaimTypes");
+ });
+
+ modelBuilder.Entity("Volo.Abp.Identity.IdentityRole", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("ConcurrencyStamp")
+ .IsConcurrencyToken()
+ .HasColumnName("ConcurrencyStamp")
+ .HasColumnType("nvarchar(40)")
+ .HasMaxLength(40);
+
+ b.Property("ExtraProperties")
+ .HasColumnName("ExtraProperties")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("IsDefault")
+ .HasColumnName("IsDefault")
+ .HasColumnType("bit");
+
+ b.Property("IsPublic")
+ .HasColumnName("IsPublic")
+ .HasColumnType("bit");
+
+ b.Property("IsStatic")
+ .HasColumnName("IsStatic")
+ .HasColumnType("bit");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasColumnType("nvarchar(256)")
+ .HasMaxLength(256);
+
+ b.Property("NormalizedName")
+ .IsRequired()
+ .HasColumnType("nvarchar(256)")
+ .HasMaxLength(256);
+
+ b.Property("TenantId")
+ .HasColumnName("TenantId")
+ .HasColumnType("uniqueidentifier");
+
+ b.HasKey("Id");
+
+ b.HasIndex("NormalizedName");
+
+ b.ToTable("AbpRoles");
+ });
+
+ modelBuilder.Entity("Volo.Abp.Identity.IdentityRoleClaim", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("ClaimType")
+ .IsRequired()
+ .HasColumnType("nvarchar(256)")
+ .HasMaxLength(256);
+
+ b.Property("ClaimValue")
+ .HasColumnType("nvarchar(1024)")
+ .HasMaxLength(1024);
+
+ b.Property("RoleId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("TenantId")
+ .HasColumnName("TenantId")
+ .HasColumnType("uniqueidentifier");
+
+ b.HasKey("Id");
+
+ b.HasIndex("RoleId");
+
+ b.ToTable("AbpRoleClaims");
+ });
+
+ modelBuilder.Entity("Volo.Abp.Identity.IdentityUser", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("AccessFailedCount")
+ .ValueGeneratedOnAdd()
+ .HasColumnName("AccessFailedCount")
+ .HasColumnType("int")
+ .HasDefaultValue(0);
+
+ b.Property("ConcurrencyStamp")
+ .IsConcurrencyToken()
+ .HasColumnName("ConcurrencyStamp")
+ .HasColumnType("nvarchar(40)")
+ .HasMaxLength(40);
+
+ b.Property("CreationTime")
+ .HasColumnName("CreationTime")
+ .HasColumnType("datetime2");
+
+ b.Property("CreatorId")
+ .HasColumnName("CreatorId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("DeleterId")
+ .HasColumnName("DeleterId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("DeletionTime")
+ .HasColumnName("DeletionTime")
+ .HasColumnType("datetime2");
+
+ b.Property("Email")
+ .IsRequired()
+ .HasColumnName("Email")
+ .HasColumnType("nvarchar(256)")
+ .HasMaxLength(256);
+
+ b.Property("EmailConfirmed")
+ .ValueGeneratedOnAdd()
+ .HasColumnName("EmailConfirmed")
+ .HasColumnType("bit")
+ .HasDefaultValue(false);
+
+ b.Property("ExtraProperties")
+ .HasColumnName("ExtraProperties")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("IsDeleted")
+ .ValueGeneratedOnAdd()
+ .HasColumnName("IsDeleted")
+ .HasColumnType("bit")
+ .HasDefaultValue(false);
+
+ b.Property("LastModificationTime")
+ .HasColumnName("LastModificationTime")
+ .HasColumnType("datetime2");
+
+ b.Property("LastModifierId")
+ .HasColumnName("LastModifierId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("LockoutEnabled")
+ .ValueGeneratedOnAdd()
+ .HasColumnName("LockoutEnabled")
+ .HasColumnType("bit")
+ .HasDefaultValue(false);
+
+ b.Property("LockoutEnd")
+ .HasColumnType("datetimeoffset");
+
+ b.Property("Name")
+ .HasColumnName("Name")
+ .HasColumnType("nvarchar(64)")
+ .HasMaxLength(64);
+
+ b.Property("NormalizedEmail")
+ .IsRequired()
+ .HasColumnName("NormalizedEmail")
+ .HasColumnType("nvarchar(256)")
+ .HasMaxLength(256);
+
+ b.Property("NormalizedUserName")
+ .IsRequired()
+ .HasColumnName("NormalizedUserName")
+ .HasColumnType("nvarchar(256)")
+ .HasMaxLength(256);
+
+ b.Property("PasswordHash")
+ .HasColumnName("PasswordHash")
+ .HasColumnType("nvarchar(256)")
+ .HasMaxLength(256);
+
+ b.Property("PhoneNumber")
+ .HasColumnName("PhoneNumber")
+ .HasColumnType("nvarchar(16)")
+ .HasMaxLength(16);
+
+ b.Property("PhoneNumberConfirmed")
+ .ValueGeneratedOnAdd()
+ .HasColumnName("PhoneNumberConfirmed")
+ .HasColumnType("bit")
+ .HasDefaultValue(false);
+
+ b.Property("SecurityStamp")
+ .IsRequired()
+ .HasColumnName("SecurityStamp")
+ .HasColumnType("nvarchar(256)")
+ .HasMaxLength(256);
+
+ b.Property("Surname")
+ .HasColumnName("Surname")
+ .HasColumnType("nvarchar(64)")
+ .HasMaxLength(64);
+
+ b.Property("TenantId")
+ .HasColumnName("TenantId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("TwoFactorEnabled")
+ .ValueGeneratedOnAdd()
+ .HasColumnName("TwoFactorEnabled")
+ .HasColumnType("bit")
+ .HasDefaultValue(false);
+
+ b.Property("UserName")
+ .IsRequired()
+ .HasColumnName("UserName")
+ .HasColumnType("nvarchar(256)")
+ .HasMaxLength(256);
+
+ b.HasKey("Id");
+
+ b.HasIndex("Email");
+
+ b.HasIndex("NormalizedEmail");
+
+ b.HasIndex("NormalizedUserName");
+
+ b.HasIndex("UserName");
+
+ b.ToTable("AbpUsers");
+ });
+
+ modelBuilder.Entity("Volo.Abp.Identity.IdentityUserClaim", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("ClaimType")
+ .IsRequired()
+ .HasColumnType("nvarchar(256)")
+ .HasMaxLength(256);
+
+ b.Property("ClaimValue")
+ .HasColumnType("nvarchar(1024)")
+ .HasMaxLength(1024);
+
+ b.Property("TenantId")
+ .HasColumnName("TenantId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("UserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.HasKey("Id");
+
+ b.HasIndex("UserId");
+
+ b.ToTable("AbpUserClaims");
+ });
+
+ modelBuilder.Entity("Volo.Abp.Identity.IdentityUserLogin", b =>
+ {
+ b.Property("UserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("LoginProvider")
+ .HasColumnType("nvarchar(64)")
+ .HasMaxLength(64);
+
+ b.Property("ProviderDisplayName")
+ .HasColumnType("nvarchar(128)")
+ .HasMaxLength(128);
+
+ b.Property("ProviderKey")
+ .IsRequired()
+ .HasColumnType("nvarchar(196)")
+ .HasMaxLength(196);
+
+ b.Property("TenantId")
+ .HasColumnName("TenantId")
+ .HasColumnType("uniqueidentifier");
+
+ b.HasKey("UserId", "LoginProvider");
+
+ b.HasIndex("LoginProvider", "ProviderKey");
+
+ b.ToTable("AbpUserLogins");
+ });
+
+ modelBuilder.Entity("Volo.Abp.Identity.IdentityUserOrganizationUnit", b =>
+ {
+ b.Property("OrganizationUnitId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("UserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("CreationTime")
+ .HasColumnName("CreationTime")
+ .HasColumnType("datetime2");
+
+ b.Property("CreatorId")
+ .HasColumnName("CreatorId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("TenantId")
+ .HasColumnName("TenantId")
+ .HasColumnType("uniqueidentifier");
+
+ b.HasKey("OrganizationUnitId", "UserId");
+
+ b.HasIndex("UserId", "OrganizationUnitId");
+
+ b.ToTable("AbpUserOrganizationUnits");
+ });
+
+ modelBuilder.Entity("Volo.Abp.Identity.IdentityUserRole", b =>
+ {
+ b.Property("UserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("RoleId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("TenantId")
+ .HasColumnName("TenantId")
+ .HasColumnType("uniqueidentifier");
+
+ b.HasKey("UserId", "RoleId");
+
+ b.HasIndex("RoleId", "UserId");
+
+ b.ToTable("AbpUserRoles");
+ });
+
+ modelBuilder.Entity("Volo.Abp.Identity.IdentityUserToken", b =>
+ {
+ b.Property("UserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("LoginProvider")
+ .HasColumnType("nvarchar(64)")
+ .HasMaxLength(64);
+
+ b.Property("Name")
+ .HasColumnType("nvarchar(128)")
+ .HasMaxLength(128);
+
+ b.Property("TenantId")
+ .HasColumnName("TenantId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("Value")
+ .HasColumnType("nvarchar(max)");
+
+ b.HasKey("UserId", "LoginProvider", "Name");
+
+ b.ToTable("AbpUserTokens");
+ });
+
+ modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("Code")
+ .IsRequired()
+ .HasColumnName("Code")
+ .HasColumnType("nvarchar(95)")
+ .HasMaxLength(95);
+
+ b.Property("ConcurrencyStamp")
+ .IsConcurrencyToken()
+ .HasColumnName("ConcurrencyStamp")
+ .HasColumnType("nvarchar(40)")
+ .HasMaxLength(40);
+
+ b.Property("CreationTime")
+ .HasColumnName("CreationTime")
+ .HasColumnType("datetime2");
+
+ b.Property("CreatorId")
+ .HasColumnName("CreatorId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("DeleterId")
+ .HasColumnName("DeleterId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("DeletionTime")
+ .HasColumnName("DeletionTime")
+ .HasColumnType("datetime2");
+
+ b.Property("DisplayName")
+ .IsRequired()
+ .HasColumnName("DisplayName")
+ .HasColumnType("nvarchar(128)")
+ .HasMaxLength(128);
+
+ b.Property("ExtraProperties")
+ .HasColumnName("ExtraProperties")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("IsDeleted")
+ .ValueGeneratedOnAdd()
+ .HasColumnName("IsDeleted")
+ .HasColumnType("bit")
+ .HasDefaultValue(false);
+
+ b.Property("LastModificationTime")
+ .HasColumnName("LastModificationTime")
+ .HasColumnType("datetime2");
+
+ b.Property("LastModifierId")
+ .HasColumnName("LastModifierId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("ParentId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("TenantId")
+ .HasColumnName("TenantId")
+ .HasColumnType("uniqueidentifier");
+
+ b.HasKey("Id");
+
+ b.HasIndex("Code");
+
+ b.HasIndex("ParentId");
+
+ b.ToTable("AbpOrganizationUnits");
+ });
+
+ modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnitRole", b =>
+ {
+ b.Property("OrganizationUnitId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("RoleId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("CreationTime")
+ .HasColumnName("CreationTime")
+ .HasColumnType("datetime2");
+
+ b.Property("CreatorId")
+ .HasColumnName("CreatorId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("TenantId")
+ .HasColumnName("TenantId")
+ .HasColumnType("uniqueidentifier");
+
+ b.HasKey("OrganizationUnitId", "RoleId");
+
+ b.HasIndex("RoleId", "OrganizationUnitId");
+
+ b.ToTable("AbpOrganizationUnitRoles");
+ });
+
+ modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiResource", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("ConcurrencyStamp")
+ .IsConcurrencyToken()
+ .HasColumnName("ConcurrencyStamp")
+ .HasColumnType("nvarchar(40)")
+ .HasMaxLength(40);
+
+ b.Property("CreationTime")
+ .HasColumnName("CreationTime")
+ .HasColumnType("datetime2");
+
+ b.Property("CreatorId")
+ .HasColumnName("CreatorId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("DeleterId")
+ .HasColumnName("DeleterId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("DeletionTime")
+ .HasColumnName("DeletionTime")
+ .HasColumnType("datetime2");
+
+ b.Property("Description")
+ .HasColumnType("nvarchar(1000)")
+ .HasMaxLength(1000);
+
+ b.Property("DisplayName")
+ .HasColumnType("nvarchar(200)")
+ .HasMaxLength(200);
+
+ b.Property("Enabled")
+ .HasColumnType("bit");
+
+ b.Property("ExtraProperties")
+ .HasColumnName("ExtraProperties")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("IsDeleted")
+ .ValueGeneratedOnAdd()
+ .HasColumnName("IsDeleted")
+ .HasColumnType("bit")
+ .HasDefaultValue(false);
+
+ b.Property("LastModificationTime")
+ .HasColumnName("LastModificationTime")
+ .HasColumnType("datetime2");
+
+ b.Property("LastModifierId")
+ .HasColumnName("LastModifierId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasColumnType("nvarchar(200)")
+ .HasMaxLength(200);
+
+ b.Property("Properties")
+ .HasColumnType("nvarchar(max)");
+
+ b.HasKey("Id");
+
+ b.ToTable("IdentityServerApiResources");
+ });
+
+ modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiResourceClaim", b =>
+ {
+ b.Property("ApiResourceId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("Type")
+ .HasColumnType("nvarchar(200)")
+ .HasMaxLength(200);
+
+ b.HasKey("ApiResourceId", "Type");
+
+ b.ToTable("IdentityServerApiClaims");
+ });
+
+ modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiScope", b =>
+ {
+ b.Property("ApiResourceId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("Name")
+ .HasColumnType("nvarchar(200)")
+ .HasMaxLength(200);
+
+ b.Property("Description")
+ .HasColumnType("nvarchar(1000)")
+ .HasMaxLength(1000);
+
+ b.Property("DisplayName")
+ .HasColumnType("nvarchar(200)")
+ .HasMaxLength(200);
+
+ b.Property("Emphasize")
+ .HasColumnType("bit");
+
+ b.Property("Required")
+ .HasColumnType("bit");
+
+ b.Property("ShowInDiscoveryDocument")
+ .HasColumnType("bit");
+
+ b.HasKey("ApiResourceId", "Name");
+
+ b.ToTable("IdentityServerApiScopes");
+ });
+
+ modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiScopeClaim", b =>
+ {
+ b.Property("ApiResourceId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("Name")
+ .HasColumnType("nvarchar(200)")
+ .HasMaxLength(200);
+
+ b.Property("Type")
+ .HasColumnType("nvarchar(200)")
+ .HasMaxLength(200);
+
+ b.HasKey("ApiResourceId", "Name", "Type");
+
+ b.ToTable("IdentityServerApiScopeClaims");
+ });
+
+ modelBuilder.Entity("Volo.Abp.IdentityServer.ApiResources.ApiSecret", b =>
+ {
+ b.Property("ApiResourceId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("Type")
+ .HasColumnType("nvarchar(250)")
+ .HasMaxLength(250);
+
+ b.Property("Value")
+ .HasColumnType("nvarchar(4000)")
+ .HasMaxLength(4000);
+
+ b.Property("Description")
+ .HasColumnType("nvarchar(2000)")
+ .HasMaxLength(2000);
+
+ b.Property("Expiration")
+ .HasColumnType("datetime2");
+
+ b.HasKey("ApiResourceId", "Type", "Value");
+
+ b.ToTable("IdentityServerApiSecrets");
+ });
+
+ modelBuilder.Entity("Volo.Abp.IdentityServer.Clients.Client", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("AbsoluteRefreshTokenLifetime")
+ .HasColumnType("int");
+
+ b.Property("AccessTokenLifetime")
+ .HasColumnType("int");
+
+ b.Property("AccessTokenType")
+ .HasColumnType("int");
+
+ b.Property("AllowAccessTokensViaBrowser")
+ .HasColumnType("bit");
+
+ b.Property("AllowOfflineAccess")
+ .HasColumnType("bit");
+
+ b.Property("AllowPlainTextPkce")
+ .HasColumnType("bit");
+
+ b.Property("AllowRememberConsent")
+ .HasColumnType("bit");
+
+ b.Property("AlwaysIncludeUserClaimsInIdToken")
+ .HasColumnType("bit");
+
+ b.Property("AlwaysSendClientClaims")
+ .HasColumnType("bit");
+
+ b.Property("AuthorizationCodeLifetime")
+ .HasColumnType("int");
+
+ b.Property("BackChannelLogoutSessionRequired")
+ .HasColumnType("bit");
+
+ b.Property("BackChannelLogoutUri")
+ .HasColumnType("nvarchar(2000)")
+ .HasMaxLength(2000);
+
+ b.Property("ClientClaimsPrefix")
+ .HasColumnType("nvarchar(200)")
+ .HasMaxLength(200);
+
+ b.Property("ClientId")
+ .IsRequired()
+ .HasColumnType("nvarchar(200)")
+ .HasMaxLength(200);
+
+ b.Property("ClientName")
+ .HasColumnType("nvarchar(200)")
+ .HasMaxLength(200);
+
+ b.Property("ClientUri")
+ .HasColumnType("nvarchar(2000)")
+ .HasMaxLength(2000);
+
+ b.Property("ConcurrencyStamp")
+ .IsConcurrencyToken()
+ .HasColumnName("ConcurrencyStamp")
+ .HasColumnType("nvarchar(40)")
+ .HasMaxLength(40);
+
+ b.Property("ConsentLifetime")
+ .HasColumnType("int");
+
+ b.Property("CreationTime")
+ .HasColumnName("CreationTime")
+ .HasColumnType("datetime2");
+
+ b.Property("CreatorId")
+ .HasColumnName("CreatorId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("DeleterId")
+ .HasColumnName("DeleterId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("DeletionTime")
+ .HasColumnName("DeletionTime")
+ .HasColumnType("datetime2");
+
+ b.Property("Description")
+ .HasColumnType("nvarchar(1000)")
+ .HasMaxLength(1000);
+
+ b.Property("DeviceCodeLifetime")
+ .HasColumnType("int");
+
+ b.Property("EnableLocalLogin")
+ .HasColumnType("bit");
+
+ b.Property("Enabled")
+ .HasColumnType("bit");
+
+ b.Property("ExtraProperties")
+ .HasColumnName("ExtraProperties")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("FrontChannelLogoutSessionRequired")
+ .HasColumnType("bit");
+
+ b.Property("FrontChannelLogoutUri")
+ .HasColumnType("nvarchar(2000)")
+ .HasMaxLength(2000);
+
+ b.Property("IdentityTokenLifetime")
+ .HasColumnType("int");
+
+ b.Property("IncludeJwtId")
+ .HasColumnType("bit");
+
+ b.Property("IsDeleted")
+ .ValueGeneratedOnAdd()
+ .HasColumnName("IsDeleted")
+ .HasColumnType("bit")
+ .HasDefaultValue(false);
+
+ b.Property("LastModificationTime")
+ .HasColumnName("LastModificationTime")
+ .HasColumnType("datetime2");
+
+ b.Property("LastModifierId")
+ .HasColumnName("LastModifierId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("LogoUri")
+ .HasColumnType("nvarchar(2000)")
+ .HasMaxLength(2000);
+
+ b.Property("PairWiseSubjectSalt")
+ .HasColumnType("nvarchar(200)")
+ .HasMaxLength(200);
+
+ b.Property("ProtocolType")
+ .IsRequired()
+ .HasColumnType("nvarchar(200)")
+ .HasMaxLength(200);
+
+ b.Property("RefreshTokenExpiration")
+ .HasColumnType("int");
+
+ b.Property("RefreshTokenUsage")
+ .HasColumnType("int");
+
+ b.Property