diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..c941e52
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1 @@
+**/wwwroot/libs/** linguist-vendored
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..122cefe
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,265 @@
+## 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
+
+# AbpSample
+src/AbpSample.Web/Logs/*
+src/AbpSample.Web.Host/Logs/*
+src/AbpSample.AuthServer/Logs/*
+src/AbpSample.HttpApi.Host/Logs/*
+src/AbpSample.HttpApi.Host/Logs/*
+src/AbpSample.DbMigrator/Logs/*
+src/AbpSample.Blazor.Server/Logs/*
+src/AbpSample.Blazor.Server.Tiered/Logs/*
+
+# Use abp install-libs to restore.
+**/wwwroot/libs/*
diff --git a/NuGet.Config b/NuGet.Config
new file mode 100644
index 0000000..bdc4519
--- /dev/null
+++ b/NuGet.Config
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/Sample.sln b/Sample.sln
new file mode 100644
index 0000000..a73f2af
--- /dev/null
+++ b/Sample.sln
@@ -0,0 +1,157 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.6.33723.286
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sample.Domain", "host\src\Sample.Domain\Sample.Domain.csproj", "{554AD327-6DBA-4F8F-96F8-81CE7A0C863F}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sample.Application", "host\src\Sample.Application\Sample.Application.csproj", "{1A94A50E-06DC-43C1-80B5-B662820EC3EB}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sample.EntityFrameworkCore", "host\src\Sample.EntityFrameworkCore\Sample.EntityFrameworkCore.csproj", "{C956DD76-69C8-4A9C-83EA-D17DF83340FD}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "host", "host", "{CA9AC87F-097E-4F15-8393-4BC07735A5B0}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sample.Domain.Shared", "host\src\Sample.Domain.Shared\Sample.Domain.Shared.csproj", "{42F719ED-8413-4895-B5B4-5AB56079BC66}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sample.Application.Contracts", "host\src\Sample.Application.Contracts\Sample.Application.Contracts.csproj", "{520659C8-C734-4298-A3DA-B539DB9DFC0B}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sample.HttpApi", "host\src\Sample.HttpApi\Sample.HttpApi.csproj", "{4164BDF7-F527-4E85-9CE6-E3C2D7426A27}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sample.HttpApi.Client", "host\src\Sample.HttpApi.Client\Sample.HttpApi.Client.csproj", "{3B5A0094-670D-4BB1-BFDD-61B88A8773DC}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sample.DbMigrator", "host\src\Sample.DbMigrator\Sample.DbMigrator.csproj", "{AA94D832-1CCC-4715-95A9-A483F23A1A5D}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sample.HttpApi.Host", "host\src\Sample.HttpApi.Host\Sample.HttpApi.Host.csproj", "{748584B1-BA69-4F6A-81AA-F4BDE6BCE29D}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "modules", "modules", "{9EAC2FB6-A28A-4851-B809-BF8216AAAFE0}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "file-management", "file-management", "{DB8C2DD9-8574-494D-9C22-28043410E149}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Passingwind.Abp.FileManagement.Domain.Shared", "modules\file-management\src\Passingwind.Abp.FileManagement.Domain.Shared\Passingwind.Abp.FileManagement.Domain.Shared.csproj", "{D64C1577-4929-4B60-939E-96DE1534891A}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Passingwind.Abp.FileManagement.Domain", "modules\file-management\src\Passingwind.Abp.FileManagement.Domain\Passingwind.Abp.FileManagement.Domain.csproj", "{F2840BC7-0188-4606-9126-DADD0F5ABF7A}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Passingwind.Abp.FileManagement.Application.Contracts", "modules\file-management\src\Passingwind.Abp.FileManagement.Application.Contracts\Passingwind.Abp.FileManagement.Application.Contracts.csproj", "{BD65D04F-08D5-40C1-8C24-77CA0BACB877}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Passingwind.Abp.FileManagement.Application", "modules\file-management\src\Passingwind.Abp.FileManagement.Application\Passingwind.Abp.FileManagement.Application.csproj", "{78040F9E-3501-4A40-82DF-00A597710F35}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Passingwind.Abp.FileManagement.EntityFrameworkCore", "modules\file-management\src\Passingwind.Abp.FileManagement.EntityFrameworkCore\Passingwind.Abp.FileManagement.EntityFrameworkCore.csproj", "{0CE86223-D31D-4315-A1F5-87BA3EE1B844}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Passingwind.Abp.FileManagement.MongoDB", "modules\file-management\src\Passingwind.Abp.FileManagement.MongoDB\Passingwind.Abp.FileManagement.MongoDB.csproj", "{F1C58097-4C08-4D88-8976-6B3389391481}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Passingwind.Abp.FileManagement.HttpApi", "modules\file-management\src\Passingwind.Abp.FileManagement.HttpApi\Passingwind.Abp.FileManagement.HttpApi.csproj", "{077AA5F8-8B61-420C-A6B5-0150A66FDB34}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Passingwind.Abp.FileManagement.HttpApi.Client", "modules\file-management\src\Passingwind.Abp.FileManagement.HttpApi.Client\Passingwind.Abp.FileManagement.HttpApi.Client.csproj", "{36E2735F-CEAB-44C8-A6D1-2CDAFF399751}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Passingwind.Abp.FileManagement.Installer", "modules\file-management\src\Passingwind.Abp.FileManagement.Installer\Passingwind.Abp.FileManagement.Installer.csproj", "{BE39FD00-745B-4049-8161-FC129817CBE4}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{099118E5-14DC-42A3-AC87-AECAFE06A1A9}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {554AD327-6DBA-4F8F-96F8-81CE7A0C863F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {554AD327-6DBA-4F8F-96F8-81CE7A0C863F}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {554AD327-6DBA-4F8F-96F8-81CE7A0C863F}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {554AD327-6DBA-4F8F-96F8-81CE7A0C863F}.Release|Any CPU.Build.0 = Release|Any CPU
+ {1A94A50E-06DC-43C1-80B5-B662820EC3EB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {1A94A50E-06DC-43C1-80B5-B662820EC3EB}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {1A94A50E-06DC-43C1-80B5-B662820EC3EB}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {1A94A50E-06DC-43C1-80B5-B662820EC3EB}.Release|Any CPU.Build.0 = Release|Any CPU
+ {C956DD76-69C8-4A9C-83EA-D17DF83340FD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {C956DD76-69C8-4A9C-83EA-D17DF83340FD}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {C956DD76-69C8-4A9C-83EA-D17DF83340FD}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {C956DD76-69C8-4A9C-83EA-D17DF83340FD}.Release|Any CPU.Build.0 = Release|Any CPU
+ {42F719ED-8413-4895-B5B4-5AB56079BC66}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {42F719ED-8413-4895-B5B4-5AB56079BC66}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {42F719ED-8413-4895-B5B4-5AB56079BC66}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {42F719ED-8413-4895-B5B4-5AB56079BC66}.Release|Any CPU.Build.0 = Release|Any CPU
+ {520659C8-C734-4298-A3DA-B539DB9DFC0B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {520659C8-C734-4298-A3DA-B539DB9DFC0B}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {520659C8-C734-4298-A3DA-B539DB9DFC0B}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {520659C8-C734-4298-A3DA-B539DB9DFC0B}.Release|Any CPU.Build.0 = Release|Any CPU
+ {4164BDF7-F527-4E85-9CE6-E3C2D7426A27}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {4164BDF7-F527-4E85-9CE6-E3C2D7426A27}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {4164BDF7-F527-4E85-9CE6-E3C2D7426A27}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {4164BDF7-F527-4E85-9CE6-E3C2D7426A27}.Release|Any CPU.Build.0 = Release|Any CPU
+ {3B5A0094-670D-4BB1-BFDD-61B88A8773DC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {3B5A0094-670D-4BB1-BFDD-61B88A8773DC}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {3B5A0094-670D-4BB1-BFDD-61B88A8773DC}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {3B5A0094-670D-4BB1-BFDD-61B88A8773DC}.Release|Any CPU.Build.0 = Release|Any CPU
+ {AA94D832-1CCC-4715-95A9-A483F23A1A5D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {AA94D832-1CCC-4715-95A9-A483F23A1A5D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {AA94D832-1CCC-4715-95A9-A483F23A1A5D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {AA94D832-1CCC-4715-95A9-A483F23A1A5D}.Release|Any CPU.Build.0 = Release|Any CPU
+ {748584B1-BA69-4F6A-81AA-F4BDE6BCE29D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {748584B1-BA69-4F6A-81AA-F4BDE6BCE29D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {748584B1-BA69-4F6A-81AA-F4BDE6BCE29D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {748584B1-BA69-4F6A-81AA-F4BDE6BCE29D}.Release|Any CPU.Build.0 = Release|Any CPU
+ {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
+ {BE39FD00-745B-4049-8161-FC129817CBE4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {BE39FD00-745B-4049-8161-FC129817CBE4}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {BE39FD00-745B-4049-8161-FC129817CBE4}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {BE39FD00-745B-4049-8161-FC129817CBE4}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(NestedProjects) = preSolution
+ {554AD327-6DBA-4F8F-96F8-81CE7A0C863F} = {CA9AC87F-097E-4F15-8393-4BC07735A5B0}
+ {1A94A50E-06DC-43C1-80B5-B662820EC3EB} = {CA9AC87F-097E-4F15-8393-4BC07735A5B0}
+ {C956DD76-69C8-4A9C-83EA-D17DF83340FD} = {CA9AC87F-097E-4F15-8393-4BC07735A5B0}
+ {42F719ED-8413-4895-B5B4-5AB56079BC66} = {CA9AC87F-097E-4F15-8393-4BC07735A5B0}
+ {520659C8-C734-4298-A3DA-B539DB9DFC0B} = {CA9AC87F-097E-4F15-8393-4BC07735A5B0}
+ {4164BDF7-F527-4E85-9CE6-E3C2D7426A27} = {CA9AC87F-097E-4F15-8393-4BC07735A5B0}
+ {3B5A0094-670D-4BB1-BFDD-61B88A8773DC} = {CA9AC87F-097E-4F15-8393-4BC07735A5B0}
+ {AA94D832-1CCC-4715-95A9-A483F23A1A5D} = {CA9AC87F-097E-4F15-8393-4BC07735A5B0}
+ {748584B1-BA69-4F6A-81AA-F4BDE6BCE29D} = {CA9AC87F-097E-4F15-8393-4BC07735A5B0}
+ {DB8C2DD9-8574-494D-9C22-28043410E149} = {9EAC2FB6-A28A-4851-B809-BF8216AAAFE0}
+ {D64C1577-4929-4B60-939E-96DE1534891A} = {099118E5-14DC-42A3-AC87-AECAFE06A1A9}
+ {F2840BC7-0188-4606-9126-DADD0F5ABF7A} = {099118E5-14DC-42A3-AC87-AECAFE06A1A9}
+ {BD65D04F-08D5-40C1-8C24-77CA0BACB877} = {099118E5-14DC-42A3-AC87-AECAFE06A1A9}
+ {78040F9E-3501-4A40-82DF-00A597710F35} = {099118E5-14DC-42A3-AC87-AECAFE06A1A9}
+ {0CE86223-D31D-4315-A1F5-87BA3EE1B844} = {099118E5-14DC-42A3-AC87-AECAFE06A1A9}
+ {F1C58097-4C08-4D88-8976-6B3389391481} = {099118E5-14DC-42A3-AC87-AECAFE06A1A9}
+ {077AA5F8-8B61-420C-A6B5-0150A66FDB34} = {099118E5-14DC-42A3-AC87-AECAFE06A1A9}
+ {36E2735F-CEAB-44C8-A6D1-2CDAFF399751} = {099118E5-14DC-42A3-AC87-AECAFE06A1A9}
+ {BE39FD00-745B-4049-8161-FC129817CBE4} = {099118E5-14DC-42A3-AC87-AECAFE06A1A9}
+ {099118E5-14DC-42A3-AC87-AECAFE06A1A9} = {DB8C2DD9-8574-494D-9C22-28043410E149}
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {28315BFD-90E7-4E14-A2EA-F3D23AF4126F}
+ EndGlobalSection
+EndGlobal
diff --git a/Sample.sln.DotSettings b/Sample.sln.DotSettings
new file mode 100644
index 0000000..cb0b2c9
--- /dev/null
+++ b/Sample.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/host/.prettierrc b/host/.prettierrc
new file mode 100644
index 0000000..56af76b
--- /dev/null
+++ b/host/.prettierrc
@@ -0,0 +1,5 @@
+{
+ "singleQuote": true,
+ "useTabs": false,
+ "tabWidth": 4
+}
diff --git a/host/common.props b/host/common.props
new file mode 100644
index 0000000..7e89c3a
--- /dev/null
+++ b/host/common.props
@@ -0,0 +1,19 @@
+
+
+ latest
+ 1.0.0
+ $(NoWarn);CS1591
+ app
+
+
+
+
+ $(NoWarn);0436
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/host/src/Sample.Application.Contracts/Permissions/SamplePermissionDefinitionProvider.cs b/host/src/Sample.Application.Contracts/Permissions/SamplePermissionDefinitionProvider.cs
new file mode 100644
index 0000000..c268d15
--- /dev/null
+++ b/host/src/Sample.Application.Contracts/Permissions/SamplePermissionDefinitionProvider.cs
@@ -0,0 +1,20 @@
+using Sample.Localization;
+using Volo.Abp.Authorization.Permissions;
+using Volo.Abp.Localization;
+
+namespace Sample.Permissions;
+
+public class SamplePermissionDefinitionProvider : PermissionDefinitionProvider
+{
+ public override void Define(IPermissionDefinitionContext context)
+ {
+ var myGroup = context.AddGroup(SamplePermissions.GroupName);
+ //Define your own permissions here. Example:
+ //myGroup.AddPermission(SamplePermissions.MyPermission1, L("Permission:MyPermission1"));
+ }
+
+ private static LocalizableString L(string name)
+ {
+ return LocalizableString.Create(name);
+ }
+}
diff --git a/host/src/Sample.Application.Contracts/Permissions/SamplePermissions.cs b/host/src/Sample.Application.Contracts/Permissions/SamplePermissions.cs
new file mode 100644
index 0000000..511825b
--- /dev/null
+++ b/host/src/Sample.Application.Contracts/Permissions/SamplePermissions.cs
@@ -0,0 +1,9 @@
+namespace Sample.Permissions;
+
+public static class SamplePermissions
+{
+ public const string GroupName = "Sample";
+
+ //Add your own permission names. Example:
+ //public const string MyPermission1 = GroupName + ".MyPermission1";
+}
diff --git a/host/src/Sample.Application.Contracts/Sample.Application.Contracts.csproj b/host/src/Sample.Application.Contracts/Sample.Application.Contracts.csproj
new file mode 100644
index 0000000..7405bd0
--- /dev/null
+++ b/host/src/Sample.Application.Contracts/Sample.Application.Contracts.csproj
@@ -0,0 +1,25 @@
+
+
+
+
+
+ netstandard2.0
+ enable
+ Sample
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/host/src/Sample.Application.Contracts/SampleApplicationContractsModule.cs b/host/src/Sample.Application.Contracts/SampleApplicationContractsModule.cs
new file mode 100644
index 0000000..eb9b083
--- /dev/null
+++ b/host/src/Sample.Application.Contracts/SampleApplicationContractsModule.cs
@@ -0,0 +1,28 @@
+using Volo.Abp.Account;
+using Volo.Abp.FeatureManagement;
+using Volo.Abp.Identity;
+using Volo.Abp.Modularity;
+using Volo.Abp.ObjectExtending;
+using Volo.Abp.PermissionManagement;
+using Volo.Abp.SettingManagement;
+using Volo.Abp.TenantManagement;
+
+namespace Sample;
+
+[DependsOn(
+ typeof(SampleDomainSharedModule),
+ typeof(AbpAccountApplicationContractsModule),
+ typeof(AbpFeatureManagementApplicationContractsModule),
+ typeof(AbpIdentityApplicationContractsModule),
+ typeof(AbpPermissionManagementApplicationContractsModule),
+ typeof(AbpSettingManagementApplicationContractsModule),
+ typeof(AbpTenantManagementApplicationContractsModule),
+ typeof(AbpObjectExtendingModule)
+)]
+public class SampleApplicationContractsModule : AbpModule
+{
+ public override void PreConfigureServices(ServiceConfigurationContext context)
+ {
+ SampleDtoExtensions.Configure();
+ }
+}
diff --git a/host/src/Sample.Application.Contracts/SampleDtoExtensions.cs b/host/src/Sample.Application.Contracts/SampleDtoExtensions.cs
new file mode 100644
index 0000000..ee55860
--- /dev/null
+++ b/host/src/Sample.Application.Contracts/SampleDtoExtensions.cs
@@ -0,0 +1,28 @@
+using Volo.Abp.Identity;
+using Volo.Abp.ObjectExtending;
+using Volo.Abp.Threading;
+
+namespace Sample;
+
+public static class SampleDtoExtensions
+{
+ private static readonly OneTimeRunner OneTimeRunner = new OneTimeRunner();
+
+ public static void Configure()
+ {
+ OneTimeRunner.Run(() =>
+ {
+ /* You can add extension properties to DTOs
+ * defined in the depended modules.
+ *
+ * Example:
+ *
+ * ObjectExtensionManager.Instance
+ * .AddOrUpdateProperty("Title");
+ *
+ * See the documentation for more:
+ * https://docs.abp.io/en/abp/latest/Object-Extensions
+ */
+ });
+ }
+}
diff --git a/host/src/Sample.Application/Properties/AssemblyInfo.cs b/host/src/Sample.Application/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..efc7bb3
--- /dev/null
+++ b/host/src/Sample.Application/Properties/AssemblyInfo.cs
@@ -0,0 +1,2 @@
+using System.Runtime.CompilerServices;
+[assembly:InternalsVisibleToAttribute("Sample.Application.Tests")]
diff --git a/host/src/Sample.Application/Sample.Application.csproj b/host/src/Sample.Application/Sample.Application.csproj
new file mode 100644
index 0000000..a50e7a6
--- /dev/null
+++ b/host/src/Sample.Application/Sample.Application.csproj
@@ -0,0 +1,25 @@
+
+
+
+
+
+ net7.0
+ enable
+ Sample
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/host/src/Sample.Application/SampleAppService.cs b/host/src/Sample.Application/SampleAppService.cs
new file mode 100644
index 0000000..82a420c
--- /dev/null
+++ b/host/src/Sample.Application/SampleAppService.cs
@@ -0,0 +1,17 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using Sample.Localization;
+using Volo.Abp.Application.Services;
+
+namespace Sample;
+
+/* Inherit your application services from this class.
+ */
+public abstract class SampleAppService : ApplicationService
+{
+ protected SampleAppService()
+ {
+ LocalizationResource = typeof(SampleResource);
+ }
+}
diff --git a/host/src/Sample.Application/SampleApplicationAutoMapperProfile.cs b/host/src/Sample.Application/SampleApplicationAutoMapperProfile.cs
new file mode 100644
index 0000000..a39676a
--- /dev/null
+++ b/host/src/Sample.Application/SampleApplicationAutoMapperProfile.cs
@@ -0,0 +1,13 @@
+using AutoMapper;
+
+namespace Sample;
+
+public class SampleApplicationAutoMapperProfile : Profile
+{
+ public SampleApplicationAutoMapperProfile()
+ {
+ /* You can configure your AutoMapper mapping configuration here.
+ * Alternatively, you can split your mapping configurations
+ * into multiple profile classes for a better organization. */
+ }
+}
diff --git a/host/src/Sample.Application/SampleApplicationModule.cs b/host/src/Sample.Application/SampleApplicationModule.cs
new file mode 100644
index 0000000..fa81d66
--- /dev/null
+++ b/host/src/Sample.Application/SampleApplicationModule.cs
@@ -0,0 +1,31 @@
+using Volo.Abp.Account;
+using Volo.Abp.AutoMapper;
+using Volo.Abp.FeatureManagement;
+using Volo.Abp.Identity;
+using Volo.Abp.Modularity;
+using Volo.Abp.PermissionManagement;
+using Volo.Abp.SettingManagement;
+using Volo.Abp.TenantManagement;
+
+namespace Sample;
+
+[DependsOn(
+ typeof(SampleDomainModule),
+ typeof(AbpAccountApplicationModule),
+ typeof(SampleApplicationContractsModule),
+ typeof(AbpIdentityApplicationModule),
+ typeof(AbpPermissionManagementApplicationModule),
+ typeof(AbpTenantManagementApplicationModule),
+ typeof(AbpFeatureManagementApplicationModule),
+ typeof(AbpSettingManagementApplicationModule)
+ )]
+public class SampleApplicationModule : AbpModule
+{
+ public override void ConfigureServices(ServiceConfigurationContext context)
+ {
+ Configure(options =>
+ {
+ options.AddMaps();
+ });
+ }
+}
diff --git a/host/src/Sample.DbMigrator/DbMigratorHostedService.cs b/host/src/Sample.DbMigrator/DbMigratorHostedService.cs
new file mode 100644
index 0000000..2b9f1f3
--- /dev/null
+++ b/host/src/Sample.DbMigrator/DbMigratorHostedService.cs
@@ -0,0 +1,51 @@
+using System.Threading;
+using System.Threading.Tasks;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
+using Sample.Data;
+using Serilog;
+using Volo.Abp;
+using Volo.Abp.Data;
+
+namespace Sample.DbMigrator;
+
+public class DbMigratorHostedService : IHostedService
+{
+ private readonly IHostApplicationLifetime _hostApplicationLifetime;
+ private readonly IConfiguration _configuration;
+
+ public DbMigratorHostedService(IHostApplicationLifetime hostApplicationLifetime, IConfiguration configuration)
+ {
+ _hostApplicationLifetime = hostApplicationLifetime;
+ _configuration = configuration;
+ }
+
+ public async Task StartAsync(CancellationToken cancellationToken)
+ {
+ using (var application = await AbpApplicationFactory.CreateAsync(options =>
+ {
+ options.Services.ReplaceConfiguration(_configuration);
+ options.UseAutofac();
+ options.Services.AddLogging(c => c.AddSerilog());
+ options.AddDataMigrationEnvironment();
+ }))
+ {
+ await application.InitializeAsync();
+
+ await application
+ .ServiceProvider
+ .GetRequiredService()
+ .MigrateAsync();
+
+ await application.ShutdownAsync();
+
+ _hostApplicationLifetime.StopApplication();
+ }
+ }
+
+ public Task StopAsync(CancellationToken cancellationToken)
+ {
+ return Task.CompletedTask;
+ }
+}
diff --git a/host/src/Sample.DbMigrator/Logs/logs.txt b/host/src/Sample.DbMigrator/Logs/logs.txt
new file mode 100644
index 0000000..0072980
--- /dev/null
+++ b/host/src/Sample.DbMigrator/Logs/logs.txt
@@ -0,0 +1,6 @@
+2023-07-07 11:13:55.907 +08:00 [INF] Started database migrations...
+2023-07-07 11:13:55.911 +08:00 [INF] Migrating schema for host database...
+2023-07-07 11:14:00.414 +08:00 [INF] Executing host database seed...
+2023-07-07 11:14:02.583 +08:00 [INF] Successfully completed host database migrations.
+2023-07-07 11:14:02.870 +08:00 [INF] Successfully completed all database migrations.
+2023-07-07 11:14:02.870 +08:00 [INF] You can safely end this process...
diff --git a/host/src/Sample.DbMigrator/Program.cs b/host/src/Sample.DbMigrator/Program.cs
new file mode 100644
index 0000000..6b06943
--- /dev/null
+++ b/host/src/Sample.DbMigrator/Program.cs
@@ -0,0 +1,41 @@
+using System.IO;
+using System.Threading.Tasks;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
+using Microsoft.Extensions.Logging;
+using Serilog;
+using Serilog.Events;
+
+namespace Sample.DbMigrator;
+
+class Program
+{
+ static async Task Main(string[] args)
+ {
+ Log.Logger = new LoggerConfiguration()
+ .MinimumLevel.Information()
+ .MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
+ .MinimumLevel.Override("Volo.Abp", LogEventLevel.Warning)
+#if DEBUG
+ .MinimumLevel.Override("Sample", LogEventLevel.Debug)
+#else
+ .MinimumLevel.Override("Sample", LogEventLevel.Information)
+#endif
+ .Enrich.FromLogContext()
+ .WriteTo.Async(c => c.File("Logs/logs.txt"))
+ .WriteTo.Async(c => c.Console())
+ .CreateLogger();
+
+ await CreateHostBuilder(args).RunConsoleAsync();
+ }
+
+ public static IHostBuilder CreateHostBuilder(string[] args) =>
+ Host.CreateDefaultBuilder(args)
+ .AddAppSettingsSecretsJson()
+ .ConfigureLogging((context, logging) => logging.ClearProviders())
+ .ConfigureServices((hostContext, services) =>
+ {
+ services.AddHostedService();
+ });
+}
diff --git a/host/src/Sample.DbMigrator/Properties/launchSettings.json b/host/src/Sample.DbMigrator/Properties/launchSettings.json
new file mode 100644
index 0000000..33504c9
--- /dev/null
+++ b/host/src/Sample.DbMigrator/Properties/launchSettings.json
@@ -0,0 +1,8 @@
+{
+ "profiles": {
+ "WSL": {
+ "commandName": "WSL2",
+ "distributionName": ""
+ }
+ }
+}
\ No newline at end of file
diff --git a/host/src/Sample.DbMigrator/Sample.DbMigrator.csproj b/host/src/Sample.DbMigrator/Sample.DbMigrator.csproj
new file mode 100644
index 0000000..2537a01
--- /dev/null
+++ b/host/src/Sample.DbMigrator/Sample.DbMigrator.csproj
@@ -0,0 +1,45 @@
+
+
+
+
+
+ Exe
+ net7.0
+ enable
+
+
+
+
+
+ PreserveNewest
+ Always
+
+
+
+ PreserveNewest
+ Always
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/host/src/Sample.DbMigrator/SampleDbMigratorModule.cs b/host/src/Sample.DbMigrator/SampleDbMigratorModule.cs
new file mode 100644
index 0000000..b5c338b
--- /dev/null
+++ b/host/src/Sample.DbMigrator/SampleDbMigratorModule.cs
@@ -0,0 +1,15 @@
+using Sample.EntityFrameworkCore;
+using Volo.Abp.Autofac;
+using Volo.Abp.Modularity;
+
+namespace Sample.DbMigrator;
+
+[DependsOn(
+ typeof(AbpAutofacModule),
+ typeof(SampleEntityFrameworkCoreModule),
+ typeof(SampleApplicationContractsModule)
+ )]
+public class SampleDbMigratorModule : AbpModule
+{
+
+}
diff --git a/host/src/Sample.DbMigrator/appsettings.json b/host/src/Sample.DbMigrator/appsettings.json
new file mode 100644
index 0000000..e0e2903
--- /dev/null
+++ b/host/src/Sample.DbMigrator/appsettings.json
@@ -0,0 +1,27 @@
+{
+ "ConnectionStrings": {
+ "Default": "Server=(LocalDb)\\MSSQLLocalDB;Database=Sample;Trusted_Connection=True;TrustServerCertificate=True"
+ },
+ "OpenIddict": {
+ "Applications": {
+ "Sample_Web": {
+ "ClientId": "Sample_Web",
+ "ClientSecret": "1q2w3e*",
+ "RootUrl": "https://localhost:44335"
+ },
+ "Sample_App": {
+ "ClientId": "Sample_App",
+ "RootUrl": "http://localhost:4200"
+ },
+ "Sample_BlazorServerTiered": {
+ "ClientId": "Sample_BlazorServerTiered",
+ "ClientSecret": "1q2w3e*",
+ "RootUrl": "https://localhost:44381"
+ },
+ "Sample_Swagger": {
+ "ClientId": "Sample_Swagger",
+ "RootUrl": "https://localhost:44336"
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/host/src/Sample.DbMigrator/appsettings.secrets.json b/host/src/Sample.DbMigrator/appsettings.secrets.json
new file mode 100644
index 0000000..7a73a41
--- /dev/null
+++ b/host/src/Sample.DbMigrator/appsettings.secrets.json
@@ -0,0 +1,2 @@
+{
+}
\ No newline at end of file
diff --git a/host/src/Sample.Domain.Shared/Localization/Sample/ar.json b/host/src/Sample.Domain.Shared/Localization/Sample/ar.json
new file mode 100644
index 0000000..96bbf80
--- /dev/null
+++ b/host/src/Sample.Domain.Shared/Localization/Sample/ar.json
@@ -0,0 +1,8 @@
+{
+ "culture": "ar",
+ "texts": {
+ "Menu:Home": "الرئيسية",
+ "Menu:Home": "الصفحة الرئيسية",
+ "LongWelcomeMessage": "مرحبا بكم في التطبيق. هذا مشروع بدء تشغيل يعتمد على إطار عمل ABP. لمزيد من المعلومات ، يرجى زيارة abp.io."
+ }
+}
diff --git a/host/src/Sample.Domain.Shared/Localization/Sample/cs.json b/host/src/Sample.Domain.Shared/Localization/Sample/cs.json
new file mode 100644
index 0000000..5a0bbf6
--- /dev/null
+++ b/host/src/Sample.Domain.Shared/Localization/Sample/cs.json
@@ -0,0 +1,8 @@
+{
+ "culture": "cs",
+ "texts": {
+ "Menu:Home": "Úvod",
+ "Welcome": "Vítejte",
+ "LongWelcomeMessage": "Vítejte v aplikaci. Toto je startovací projekt založený na ABP frameworku. Pro více informací, navštivte abp.io."
+ }
+}
diff --git a/host/src/Sample.Domain.Shared/Localization/Sample/de.json b/host/src/Sample.Domain.Shared/Localization/Sample/de.json
new file mode 100644
index 0000000..831493b
--- /dev/null
+++ b/host/src/Sample.Domain.Shared/Localization/Sample/de.json
@@ -0,0 +1,8 @@
+{
+ "culture": "de",
+ "texts": {
+ "Menu:Home": "Home",
+ "Welcome": "Willkommen",
+ "LongWelcomeMessage": "Willkommen bei der Anwendung. Dies ist ein Startup-Projekt, das auf dem ABP-Framework basiert. Weitere Informationen finden Sie unter abp.io."
+ }
+}
\ No newline at end of file
diff --git a/host/src/Sample.Domain.Shared/Localization/Sample/en-GB.json b/host/src/Sample.Domain.Shared/Localization/Sample/en-GB.json
new file mode 100644
index 0000000..d2ca079
--- /dev/null
+++ b/host/src/Sample.Domain.Shared/Localization/Sample/en-GB.json
@@ -0,0 +1,8 @@
+{
+ "culture": "en-GB",
+ "texts": {
+ "Menu:Home": "Home",
+ "Welcome": "Welcome",
+ "LongWelcomeMessage": "Welcome to the application. This is a startup project based on the ABP framework. For more information, visit abp.io."
+ }
+}
\ No newline at end of file
diff --git a/host/src/Sample.Domain.Shared/Localization/Sample/en.json b/host/src/Sample.Domain.Shared/Localization/Sample/en.json
new file mode 100644
index 0000000..d2a6a98
--- /dev/null
+++ b/host/src/Sample.Domain.Shared/Localization/Sample/en.json
@@ -0,0 +1,8 @@
+{
+ "culture": "en",
+ "texts": {
+ "Menu:Home": "Home",
+ "Welcome": "Welcome",
+ "LongWelcomeMessage": "Welcome to the application. This is a startup project based on the ABP framework. For more information, visit abp.io."
+ }
+}
diff --git a/host/src/Sample.Domain.Shared/Localization/Sample/es.json b/host/src/Sample.Domain.Shared/Localization/Sample/es.json
new file mode 100644
index 0000000..31b4b59
--- /dev/null
+++ b/host/src/Sample.Domain.Shared/Localization/Sample/es.json
@@ -0,0 +1,8 @@
+{
+ "culture": "es",
+ "texts": {
+ "Menu:Home": "Inicio",
+ "Welcome": "Bienvenido",
+ "LongWelcomeMessage": "Bienvenido a la aplicación, este es un proyecto base basado en el framework ABP. Para más información, visita abp.io."
+ }
+}
\ No newline at end of file
diff --git a/host/src/Sample.Domain.Shared/Localization/Sample/fi.json b/host/src/Sample.Domain.Shared/Localization/Sample/fi.json
new file mode 100644
index 0000000..a318859
--- /dev/null
+++ b/host/src/Sample.Domain.Shared/Localization/Sample/fi.json
@@ -0,0 +1,8 @@
+{
+ "culture": "fi",
+ "texts": {
+ "Menu:Home": "Koti",
+ "Welcome": "Tervetuloa",
+ "LongWelcomeMessage": "Tervetuloa sovellukseen. Tämä on ABP-kehykseen perustuva käynnistysprojekti. Lisätietoja on osoitteessa abp.io."
+ }
+}
\ No newline at end of file
diff --git a/host/src/Sample.Domain.Shared/Localization/Sample/fr.json b/host/src/Sample.Domain.Shared/Localization/Sample/fr.json
new file mode 100644
index 0000000..e76eac0
--- /dev/null
+++ b/host/src/Sample.Domain.Shared/Localization/Sample/fr.json
@@ -0,0 +1,8 @@
+{
+ "culture": "fr",
+ "texts": {
+ "Menu:Home": "Accueil",
+ "Welcome": "Bienvenue",
+ "LongWelcomeMessage": "Bienvenue dans l'application. Il s'agit d'un projet de démarrage basé sur le framework ABP. Pour plus d'informations, visitez abp.io."
+ }
+}
\ No newline at end of file
diff --git a/host/src/Sample.Domain.Shared/Localization/Sample/hi.json b/host/src/Sample.Domain.Shared/Localization/Sample/hi.json
new file mode 100644
index 0000000..a1676bf
--- /dev/null
+++ b/host/src/Sample.Domain.Shared/Localization/Sample/hi.json
@@ -0,0 +1,8 @@
+{
+ "culture": "hi",
+ "texts": {
+ "Menu:Home": "घर",
+ "Welcome": "स्वागत हे",
+ "LongWelcomeMessage": "आवेदन करने के लिए आपका स्वागत है। यह एबीपी ढांचे पर आधारित एक स्टार्टअप परियोजना है। अधिक जानकारी के लिए, abp.io पर जाएं।"
+ }
+}
\ No newline at end of file
diff --git a/host/src/Sample.Domain.Shared/Localization/Sample/hr.json b/host/src/Sample.Domain.Shared/Localization/Sample/hr.json
new file mode 100644
index 0000000..fa8efab
--- /dev/null
+++ b/host/src/Sample.Domain.Shared/Localization/Sample/hr.json
@@ -0,0 +1,8 @@
+{
+ "culture": "hr",
+ "texts": {
+ "Menu:Home": "Početna",
+ "Welcome": "Dobrodošli",
+ "LongWelcomeMessage": "Dobrodošli u aplikaciju. Ovo je startup projekt temeljen na ABP framework-u. Za više informacija posjetite abp.io."
+ }
+}
diff --git a/host/src/Sample.Domain.Shared/Localization/Sample/hu.json b/host/src/Sample.Domain.Shared/Localization/Sample/hu.json
new file mode 100644
index 0000000..c7b6a33
--- /dev/null
+++ b/host/src/Sample.Domain.Shared/Localization/Sample/hu.json
@@ -0,0 +1,8 @@
+{
+ "culture": "hu",
+ "texts": {
+ "Menu:Home": "Kezdőlap",
+ "Welcome": "Üdvözlöm",
+ "LongWelcomeMessage": "Üdvözöljük az alkalmazásban. Ez egy ABP keretrendszeren alapuló startup projekt. További információkért látogasson el az abp.io oldalra."
+ }
+}
\ No newline at end of file
diff --git a/host/src/Sample.Domain.Shared/Localization/Sample/is.json b/host/src/Sample.Domain.Shared/Localization/Sample/is.json
new file mode 100644
index 0000000..190df90
--- /dev/null
+++ b/host/src/Sample.Domain.Shared/Localization/Sample/is.json
@@ -0,0 +1,8 @@
+{
+ "culture": "is",
+ "texts": {
+ "Menu:Home": "Heim",
+ "Welcome": "Velkomin",
+ "LongWelcomeMessage": "Verið velkomin í forritið. Þetta er startup verkefni sem byggir á ABP. Nánari upplýsingar er að finna á abp.io."
+ }
+}
\ No newline at end of file
diff --git a/host/src/Sample.Domain.Shared/Localization/Sample/it.json b/host/src/Sample.Domain.Shared/Localization/Sample/it.json
new file mode 100644
index 0000000..82ce42b
--- /dev/null
+++ b/host/src/Sample.Domain.Shared/Localization/Sample/it.json
@@ -0,0 +1,8 @@
+{
+ "culture": "it",
+ "texts": {
+ "Menu:Home": "Home",
+ "Welcome": "Benvenuto",
+ "LongWelcomeMessage": "Benvenuto nell'applicazione. Questo è un progetto di avvio basato sul framework ABP. Per ulteriori informazioni, visita abp.io."
+ }
+}
\ No newline at end of file
diff --git a/host/src/Sample.Domain.Shared/Localization/Sample/nl.json b/host/src/Sample.Domain.Shared/Localization/Sample/nl.json
new file mode 100644
index 0000000..9ba8da4
--- /dev/null
+++ b/host/src/Sample.Domain.Shared/Localization/Sample/nl.json
@@ -0,0 +1,8 @@
+{
+ "culture": "nl",
+ "texts": {
+ "Menu:Home": "Home",
+ "Welcome": "Welkom",
+ "LongWelcomeMessage": "Welkom bij de applicatie. Dit is een startup-project gebaseerd op het ABP-framework. Bezoek abp.io voor meer informatie."
+ }
+}
\ No newline at end of file
diff --git a/host/src/Sample.Domain.Shared/Localization/Sample/pl-PL.json b/host/src/Sample.Domain.Shared/Localization/Sample/pl-PL.json
new file mode 100644
index 0000000..33412f3
--- /dev/null
+++ b/host/src/Sample.Domain.Shared/Localization/Sample/pl-PL.json
@@ -0,0 +1,8 @@
+{
+ "culture": "pl-PL",
+ "texts": {
+ "Menu:Home": "Home",
+ "Welcome": "Witaj",
+ "LongWelcomeMessage": "Witaj w aplikacji. To jest inicjalny projekt bazujący na ABP framework. Po więcej informacji odwiedź stronę abp.io."
+ }
+}
\ No newline at end of file
diff --git a/host/src/Sample.Domain.Shared/Localization/Sample/pt-BR.json b/host/src/Sample.Domain.Shared/Localization/Sample/pt-BR.json
new file mode 100644
index 0000000..8c818a0
--- /dev/null
+++ b/host/src/Sample.Domain.Shared/Localization/Sample/pt-BR.json
@@ -0,0 +1,8 @@
+{
+ "culture": "pt-BR",
+ "texts": {
+ "Menu:Home": "Principal",
+ "Welcome": "Seja bem-vindo!",
+ "LongWelcomeMessage": "Bem-vindo a esta aplicação. Este é um projeto inicial baseado no ABP framework. Para mais informações, visite abp.io."
+ }
+}
\ No newline at end of file
diff --git a/host/src/Sample.Domain.Shared/Localization/Sample/ro-RO.json b/host/src/Sample.Domain.Shared/Localization/Sample/ro-RO.json
new file mode 100644
index 0000000..1fe5601
--- /dev/null
+++ b/host/src/Sample.Domain.Shared/Localization/Sample/ro-RO.json
@@ -0,0 +1,8 @@
+{
+ "culture": "ro-RO",
+ "texts": {
+ "Menu:Home": "Acasă",
+ "Welcome": "Bun venit",
+ "LongWelcomeMessage": "Bun venit la aplicaţie. Acesta este un proiect de pornire bazat pe framework-ul ABP. Pentru mai multe informaţii, vizitaţi, visit abp.io."
+ }
+}
\ No newline at end of file
diff --git a/host/src/Sample.Domain.Shared/Localization/Sample/ru.json b/host/src/Sample.Domain.Shared/Localization/Sample/ru.json
new file mode 100644
index 0000000..8464e44
--- /dev/null
+++ b/host/src/Sample.Domain.Shared/Localization/Sample/ru.json
@@ -0,0 +1,8 @@
+{
+ "culture": "ru",
+ "texts": {
+ "Menu:Home": "Главная",
+ "Welcome": "Добро пожаловать",
+ "LongWelcomeMessage": "Добро пожаловать в приложение. Этот запущенный проект основан на фреймворке ABP. Для получения дополнительной информации посетите сайт abp.io."
+ }
+}
diff --git a/host/src/Sample.Domain.Shared/Localization/Sample/sk.json b/host/src/Sample.Domain.Shared/Localization/Sample/sk.json
new file mode 100644
index 0000000..4f35aaf
--- /dev/null
+++ b/host/src/Sample.Domain.Shared/Localization/Sample/sk.json
@@ -0,0 +1,8 @@
+{
+ "culture": "sk",
+ "texts": {
+ "Menu:Home": "Domov",
+ "Welcome": "Vitajte",
+ "LongWelcomeMessage": "Vitajte v aplikácii. Toto je štartovací projekt založený na ABP frameworku. Viac informácií nájdete na stránke abp.io."
+ }
+}
\ No newline at end of file
diff --git a/host/src/Sample.Domain.Shared/Localization/Sample/sl.json b/host/src/Sample.Domain.Shared/Localization/Sample/sl.json
new file mode 100644
index 0000000..a066ef2
--- /dev/null
+++ b/host/src/Sample.Domain.Shared/Localization/Sample/sl.json
@@ -0,0 +1,8 @@
+{
+ "culture": "sl",
+ "texts": {
+ "Menu:Home": "Domov",
+ "Welcome": "Dobrodošli",
+ "LongWelcomeMessage": "Dobrodošli v aplikaciji. To je začetni projekt na osnovi okolja ABP. Za več informacij obiščite abp.io."
+ }
+}
diff --git a/host/src/Sample.Domain.Shared/Localization/Sample/tr.json b/host/src/Sample.Domain.Shared/Localization/Sample/tr.json
new file mode 100644
index 0000000..2cc911e
--- /dev/null
+++ b/host/src/Sample.Domain.Shared/Localization/Sample/tr.json
@@ -0,0 +1,8 @@
+{
+ "culture": "tr",
+ "texts": {
+ "Menu:Home": "Ana sayfa",
+ "Welcome": "Hoşgeldiniz",
+ "LongWelcomeMessage": "Uygulamaya hoşgeldiniz. Bu, ABP framework'ü üzerine bina edilmiş bir başlangıç projesidir. Daha fazla bilgi için abp.io adresini ziyaret edebilirsiniz."
+ }
+}
\ No newline at end of file
diff --git a/host/src/Sample.Domain.Shared/Localization/Sample/vi.json b/host/src/Sample.Domain.Shared/Localization/Sample/vi.json
new file mode 100644
index 0000000..c115a35
--- /dev/null
+++ b/host/src/Sample.Domain.Shared/Localization/Sample/vi.json
@@ -0,0 +1,8 @@
+{
+ "culture": "vi",
+ "texts": {
+ "Menu:Home": "Trang chủ",
+ "Welcome": "Chào mừng bạn",
+ "LongWelcomeMessage": "Chào mừng bạn đến ứng dụng. Đây là một dự án khởi nghiệp dựa trên khung ABP. Để biết thêm thông tin, hãy truy cập abp.io."
+ }
+}
diff --git a/host/src/Sample.Domain.Shared/Localization/Sample/zh-Hans.json b/host/src/Sample.Domain.Shared/Localization/Sample/zh-Hans.json
new file mode 100644
index 0000000..23790bd
--- /dev/null
+++ b/host/src/Sample.Domain.Shared/Localization/Sample/zh-Hans.json
@@ -0,0 +1,8 @@
+{
+ "culture": "zh-Hans",
+ "texts": {
+ "Menu:Home": "首页",
+ "Welcome": "欢迎",
+ "LongWelcomeMessage": "欢迎来到该应用程序. 这是一个基于ABP框架的启动项目. 有关更多信息, 请访问 abp.io."
+ }
+ }
\ No newline at end of file
diff --git a/host/src/Sample.Domain.Shared/Localization/Sample/zh-Hant.json b/host/src/Sample.Domain.Shared/Localization/Sample/zh-Hant.json
new file mode 100644
index 0000000..31e0ab5
--- /dev/null
+++ b/host/src/Sample.Domain.Shared/Localization/Sample/zh-Hant.json
@@ -0,0 +1,8 @@
+{
+ "culture": "zh-Hant",
+ "texts": {
+ "Menu:Home": "首頁",
+ "Welcome": "歡迎",
+ "LongWelcomeMessage": "歡迎來到此應用程式. 這是一個基於ABP框架的起始專案. 有關更多訊息, 請瀏覽 abp.io."
+ }
+ }
\ No newline at end of file
diff --git a/host/src/Sample.Domain.Shared/Localization/SampleResource.cs b/host/src/Sample.Domain.Shared/Localization/SampleResource.cs
new file mode 100644
index 0000000..c8a3547
--- /dev/null
+++ b/host/src/Sample.Domain.Shared/Localization/SampleResource.cs
@@ -0,0 +1,9 @@
+using Volo.Abp.Localization;
+
+namespace Sample.Localization;
+
+[LocalizationResourceName("Sample")]
+public class SampleResource
+{
+
+}
diff --git a/host/src/Sample.Domain.Shared/MultiTenancy/MultiTenancyConsts.cs b/host/src/Sample.Domain.Shared/MultiTenancy/MultiTenancyConsts.cs
new file mode 100644
index 0000000..a2ecd64
--- /dev/null
+++ b/host/src/Sample.Domain.Shared/MultiTenancy/MultiTenancyConsts.cs
@@ -0,0 +1,10 @@
+namespace Sample.MultiTenancy;
+
+public static class MultiTenancyConsts
+{
+ /* Enable/disable multi-tenancy easily in a single point.
+ * If you will never need to multi-tenancy, you can remove
+ * related modules and code parts, including this file.
+ */
+ public const bool IsEnabled = true;
+}
diff --git a/host/src/Sample.Domain.Shared/Sample.Domain.Shared.csproj b/host/src/Sample.Domain.Shared/Sample.Domain.Shared.csproj
new file mode 100644
index 0000000..70fa045
--- /dev/null
+++ b/host/src/Sample.Domain.Shared/Sample.Domain.Shared.csproj
@@ -0,0 +1,32 @@
+
+
+
+
+
+ netstandard2.0
+ enable
+ Sample
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/host/src/Sample.Domain.Shared/SampleDomainErrorCodes.cs b/host/src/Sample.Domain.Shared/SampleDomainErrorCodes.cs
new file mode 100644
index 0000000..7577685
--- /dev/null
+++ b/host/src/Sample.Domain.Shared/SampleDomainErrorCodes.cs
@@ -0,0 +1,6 @@
+namespace Sample;
+
+public static class SampleDomainErrorCodes
+{
+ /* You can add your business exception error codes here, as constants */
+}
diff --git a/host/src/Sample.Domain.Shared/SampleDomainSharedModule.cs b/host/src/Sample.Domain.Shared/SampleDomainSharedModule.cs
new file mode 100644
index 0000000..8ce9972
--- /dev/null
+++ b/host/src/Sample.Domain.Shared/SampleDomainSharedModule.cs
@@ -0,0 +1,58 @@
+using Sample.Localization;
+using Volo.Abp.AuditLogging;
+using Volo.Abp.BackgroundJobs;
+using Volo.Abp.FeatureManagement;
+using Volo.Abp.Identity;
+using Volo.Abp.Localization;
+using Volo.Abp.Localization.ExceptionHandling;
+using Volo.Abp.Modularity;
+using Volo.Abp.OpenIddict;
+using Volo.Abp.PermissionManagement;
+using Volo.Abp.SettingManagement;
+using Volo.Abp.TenantManagement;
+using Volo.Abp.Validation.Localization;
+using Volo.Abp.VirtualFileSystem;
+
+namespace Sample;
+
+[DependsOn(
+ typeof(AbpAuditLoggingDomainSharedModule),
+ typeof(AbpBackgroundJobsDomainSharedModule),
+ typeof(AbpFeatureManagementDomainSharedModule),
+ typeof(AbpIdentityDomainSharedModule),
+ typeof(AbpOpenIddictDomainSharedModule),
+ typeof(AbpPermissionManagementDomainSharedModule),
+ typeof(AbpSettingManagementDomainSharedModule),
+ typeof(AbpTenantManagementDomainSharedModule)
+ )]
+public class SampleDomainSharedModule : AbpModule
+{
+ public override void PreConfigureServices(ServiceConfigurationContext context)
+ {
+ SampleGlobalFeatureConfigurator.Configure();
+ SampleModuleExtensionConfigurator.Configure();
+ }
+
+ public override void ConfigureServices(ServiceConfigurationContext context)
+ {
+ Configure(options =>
+ {
+ options.FileSets.AddEmbedded();
+ });
+
+ Configure(options =>
+ {
+ options.Resources
+ .Add("en")
+ .AddBaseTypes(typeof(AbpValidationResource))
+ .AddVirtualJson("/Localization/Sample");
+
+ options.DefaultResourceType = typeof(SampleResource);
+ });
+
+ Configure(options =>
+ {
+ options.MapCodeNamespace("Sample", typeof(SampleResource));
+ });
+ }
+}
diff --git a/host/src/Sample.Domain.Shared/SampleGlobalFeatureConfigurator.cs b/host/src/Sample.Domain.Shared/SampleGlobalFeatureConfigurator.cs
new file mode 100644
index 0000000..58227b6
--- /dev/null
+++ b/host/src/Sample.Domain.Shared/SampleGlobalFeatureConfigurator.cs
@@ -0,0 +1,22 @@
+using Volo.Abp.Threading;
+
+namespace Sample;
+
+public static class SampleGlobalFeatureConfigurator
+{
+ private static readonly OneTimeRunner OneTimeRunner = new OneTimeRunner();
+
+ public static void Configure()
+ {
+ OneTimeRunner.Run(() =>
+ {
+ /* You can configure (enable/disable) global features of the used modules here.
+ *
+ * YOU CAN SAFELY DELETE THIS CLASS AND REMOVE ITS USAGES IF YOU DON'T NEED TO IT!
+ *
+ * Please refer to the documentation to lear more about the Global Features System:
+ * https://docs.abp.io/en/abp/latest/Global-Features
+ */
+ });
+ }
+}
diff --git a/host/src/Sample.Domain.Shared/SampleModuleExtensionConfigurator.cs b/host/src/Sample.Domain.Shared/SampleModuleExtensionConfigurator.cs
new file mode 100644
index 0000000..35a86fe
--- /dev/null
+++ b/host/src/Sample.Domain.Shared/SampleModuleExtensionConfigurator.cs
@@ -0,0 +1,73 @@
+using System.ComponentModel.DataAnnotations;
+using Volo.Abp.Identity;
+using Volo.Abp.ObjectExtending;
+using Volo.Abp.Threading;
+
+namespace Sample;
+
+public static class SampleModuleExtensionConfigurator
+{
+ private static readonly OneTimeRunner OneTimeRunner = new OneTimeRunner();
+
+ public static void Configure()
+ {
+ OneTimeRunner.Run(() =>
+ {
+ ConfigureExistingProperties();
+ ConfigureExtraProperties();
+ });
+ }
+
+ private static void ConfigureExistingProperties()
+ {
+ /* You can change max lengths for properties of the
+ * entities defined in the modules used by your application.
+ *
+ * Example: Change user and role name max lengths
+
+ IdentityUserConsts.MaxNameLength = 99;
+ IdentityRoleConsts.MaxNameLength = 99;
+
+ * Notice: It is not suggested to change property lengths
+ * unless you really need it. Go with the standard values wherever possible.
+ *
+ * If you are using EF Core, you will need to run the add-migration command after your changes.
+ */
+ }
+
+ private static void ConfigureExtraProperties()
+ {
+ /* You can configure extra properties for the
+ * entities defined in the modules used by your application.
+ *
+ * This class can be used to define these extra properties
+ * with a high level, easy to use API.
+ *
+ * Example: Add a new property to the user entity of the identity module
+
+ ObjectExtensionManager.Instance.Modules()
+ .ConfigureIdentity(identity =>
+ {
+ identity.ConfigureUser(user =>
+ {
+ user.AddOrUpdateProperty( //property type: string
+ "SocialSecurityNumber", //property name
+ property =>
+ {
+ //validation rules
+ property.Attributes.Add(new RequiredAttribute());
+ property.Attributes.Add(new StringLengthAttribute(64) {MinimumLength = 4});
+
+ property.Configuration[IdentityModuleExtensionConsts.ConfigurationNames.AllowUserToEdit] = true;
+
+ //...other configurations for this property
+ }
+ );
+ });
+ });
+
+ * See the documentation for more:
+ * https://docs.abp.io/en/abp/latest/Module-Entity-Extensions
+ */
+ }
+}
diff --git a/host/src/Sample.Domain/Data/ISampleDbSchemaMigrator.cs b/host/src/Sample.Domain/Data/ISampleDbSchemaMigrator.cs
new file mode 100644
index 0000000..df36767
--- /dev/null
+++ b/host/src/Sample.Domain/Data/ISampleDbSchemaMigrator.cs
@@ -0,0 +1,8 @@
+using System.Threading.Tasks;
+
+namespace Sample.Data;
+
+public interface ISampleDbSchemaMigrator
+{
+ Task MigrateAsync();
+}
diff --git a/host/src/Sample.Domain/Data/NullSampleDbSchemaMigrator.cs b/host/src/Sample.Domain/Data/NullSampleDbSchemaMigrator.cs
new file mode 100644
index 0000000..b9daf03
--- /dev/null
+++ b/host/src/Sample.Domain/Data/NullSampleDbSchemaMigrator.cs
@@ -0,0 +1,15 @@
+using System.Threading.Tasks;
+using Volo.Abp.DependencyInjection;
+
+namespace Sample.Data;
+
+/* This is used if database provider does't define
+ * ISampleDbSchemaMigrator implementation.
+ */
+public class NullSampleDbSchemaMigrator : ISampleDbSchemaMigrator, ITransientDependency
+{
+ public Task MigrateAsync()
+ {
+ return Task.CompletedTask;
+ }
+}
diff --git a/host/src/Sample.Domain/Data/SampleDbMigrationService.cs b/host/src/Sample.Domain/Data/SampleDbMigrationService.cs
new file mode 100644
index 0000000..81b3187
--- /dev/null
+++ b/host/src/Sample.Domain/Data/SampleDbMigrationService.cs
@@ -0,0 +1,218 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Threading.Tasks;
+using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Logging.Abstractions;
+using Volo.Abp.Data;
+using Volo.Abp.DependencyInjection;
+using Volo.Abp.Identity;
+using Volo.Abp.MultiTenancy;
+using Volo.Abp.TenantManagement;
+
+namespace Sample.Data;
+
+public class SampleDbMigrationService : ITransientDependency
+{
+ public ILogger Logger { get; set; }
+
+ private readonly IDataSeeder _dataSeeder;
+ private readonly IEnumerable _dbSchemaMigrators;
+ private readonly ITenantRepository _tenantRepository;
+ private readonly ICurrentTenant _currentTenant;
+
+ public SampleDbMigrationService(
+ IDataSeeder dataSeeder,
+ IEnumerable dbSchemaMigrators,
+ ITenantRepository tenantRepository,
+ ICurrentTenant currentTenant)
+ {
+ _dataSeeder = dataSeeder;
+ _dbSchemaMigrators = dbSchemaMigrators;
+ _tenantRepository = tenantRepository;
+ _currentTenant = currentTenant;
+
+ Logger = NullLogger.Instance;
+ }
+
+ public async Task MigrateAsync()
+ {
+ var initialMigrationAdded = AddInitialMigrationIfNotExist();
+
+ if (initialMigrationAdded)
+ {
+ return;
+ }
+
+ Logger.LogInformation("Started database migrations...");
+
+ await MigrateDatabaseSchemaAsync();
+ await SeedDataAsync();
+
+ Logger.LogInformation($"Successfully completed host database migrations.");
+
+ var tenants = await _tenantRepository.GetListAsync(includeDetails: true);
+
+ var migratedDatabaseSchemas = new HashSet();
+ foreach (var tenant in tenants)
+ {
+ using (_currentTenant.Change(tenant.Id))
+ {
+ if (tenant.ConnectionStrings.Any())
+ {
+ var tenantConnectionStrings = tenant.ConnectionStrings
+ .Select(x => x.Value)
+ .ToList();
+
+ if (!migratedDatabaseSchemas.IsSupersetOf(tenantConnectionStrings))
+ {
+ await MigrateDatabaseSchemaAsync(tenant);
+
+ migratedDatabaseSchemas.AddIfNotContains(tenantConnectionStrings);
+ }
+ }
+
+ await SeedDataAsync(tenant);
+ }
+
+ Logger.LogInformation($"Successfully completed {tenant.Name} tenant database migrations.");
+ }
+
+ Logger.LogInformation("Successfully completed all database migrations.");
+ Logger.LogInformation("You can safely end this process...");
+ }
+
+ private async Task MigrateDatabaseSchemaAsync(Tenant? tenant = null)
+ {
+ Logger.LogInformation(
+ $"Migrating schema for {(tenant == null ? "host" : tenant.Name + " tenant")} database...");
+
+ foreach (var migrator in _dbSchemaMigrators)
+ {
+ await migrator.MigrateAsync();
+ }
+ }
+
+ private async Task SeedDataAsync(Tenant? tenant = null)
+ {
+ Logger.LogInformation($"Executing {(tenant == null ? "host" : tenant.Name + " tenant")} database seed...");
+
+ await _dataSeeder.SeedAsync(new DataSeedContext(tenant?.Id)
+ .WithProperty(IdentityDataSeedContributor.AdminEmailPropertyName, IdentityDataSeedContributor.AdminEmailDefaultValue)
+ .WithProperty(IdentityDataSeedContributor.AdminPasswordPropertyName, IdentityDataSeedContributor.AdminPasswordDefaultValue)
+ );
+ }
+
+ private bool AddInitialMigrationIfNotExist()
+ {
+ try
+ {
+ if (!DbMigrationsProjectExists())
+ {
+ return false;
+ }
+ }
+ catch (Exception)
+ {
+ return false;
+ }
+
+ try
+ {
+ if (!MigrationsFolderExists())
+ {
+ AddInitialMigration();
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ catch (Exception e)
+ {
+ Logger.LogWarning("Couldn't determinate if any migrations exist : " + e.Message);
+ return false;
+ }
+ }
+
+ private bool DbMigrationsProjectExists()
+ {
+ var dbMigrationsProjectFolder = GetEntityFrameworkCoreProjectFolderPath();
+
+ return dbMigrationsProjectFolder != null;
+ }
+
+ private bool MigrationsFolderExists()
+ {
+ var dbMigrationsProjectFolder = GetEntityFrameworkCoreProjectFolderPath();
+ return dbMigrationsProjectFolder != null && Directory.Exists(Path.Combine(dbMigrationsProjectFolder, "Migrations"));
+ }
+
+ private void AddInitialMigration()
+ {
+ Logger.LogInformation("Creating initial migration...");
+
+ string argumentPrefix;
+ string fileName;
+
+ if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX) || RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
+ {
+ argumentPrefix = "-c";
+ fileName = "/bin/bash";
+ }
+ else
+ {
+ argumentPrefix = "/C";
+ fileName = "cmd.exe";
+ }
+
+ var procStartInfo = new ProcessStartInfo(fileName,
+ $"{argumentPrefix} \"abp create-migration-and-run-migrator \"{GetEntityFrameworkCoreProjectFolderPath()}\"\""
+ );
+
+ try
+ {
+ Process.Start(procStartInfo);
+ }
+ catch (Exception)
+ {
+ throw new Exception("Couldn't run ABP CLI...");
+ }
+ }
+
+ private string? GetEntityFrameworkCoreProjectFolderPath()
+ {
+ var slnDirectoryPath = GetSolutionDirectoryPath();
+
+ if (slnDirectoryPath == null)
+ {
+ throw new Exception("Solution folder not found!");
+ }
+
+ var srcDirectoryPath = Path.Combine(slnDirectoryPath, "src");
+
+ return Directory.GetDirectories(srcDirectoryPath)
+ .FirstOrDefault(d => d.EndsWith(".EntityFrameworkCore"));
+ }
+
+ private string? GetSolutionDirectoryPath()
+ {
+ var currentDirectory = new DirectoryInfo(Directory.GetCurrentDirectory());
+
+ while (currentDirectory != null && Directory.GetParent(currentDirectory.FullName) != null)
+ {
+ currentDirectory = Directory.GetParent(currentDirectory.FullName);
+
+ if (currentDirectory != null && Directory.GetFiles(currentDirectory.FullName).FirstOrDefault(f => f.EndsWith(".sln")) != null)
+ {
+ return currentDirectory.FullName;
+ }
+ }
+
+ return null;
+ }
+}
diff --git a/host/src/Sample.Domain/OpenIddict/OpenIddictDataSeedContributor.cs b/host/src/Sample.Domain/OpenIddict/OpenIddictDataSeedContributor.cs
new file mode 100644
index 0000000..f73b07c
--- /dev/null
+++ b/host/src/Sample.Domain/OpenIddict/OpenIddictDataSeedContributor.cs
@@ -0,0 +1,405 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using JetBrains.Annotations;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.Localization;
+using OpenIddict.Abstractions;
+using Volo.Abp;
+using Volo.Abp.Authorization.Permissions;
+using Volo.Abp.Data;
+using Volo.Abp.DependencyInjection;
+using Volo.Abp.OpenIddict.Applications;
+using Volo.Abp.PermissionManagement;
+using Volo.Abp.Uow;
+
+namespace Sample.OpenIddict;
+
+/* Creates initial data that is needed to property run the application
+ * and make client-to-server communication possible.
+ */
+public class OpenIddictDataSeedContributor : IDataSeedContributor, ITransientDependency
+{
+ private readonly IConfiguration _configuration;
+ private readonly IAbpApplicationManager _applicationManager;
+ private readonly IOpenIddictScopeManager _scopeManager;
+ private readonly IPermissionDataSeeder _permissionDataSeeder;
+ private readonly IStringLocalizer L;
+
+ public OpenIddictDataSeedContributor(
+ IConfiguration configuration,
+ IAbpApplicationManager applicationManager,
+ IOpenIddictScopeManager scopeManager,
+ IPermissionDataSeeder permissionDataSeeder,
+ IStringLocalizer l)
+ {
+ _configuration = configuration;
+ _applicationManager = applicationManager;
+ _scopeManager = scopeManager;
+ _permissionDataSeeder = permissionDataSeeder;
+ L = l;
+ }
+
+ [UnitOfWork]
+ public virtual async Task SeedAsync(DataSeedContext context)
+ {
+ await CreateScopesAsync();
+ await CreateApplicationsAsync();
+ }
+
+ private async Task CreateScopesAsync()
+ {
+ if (await _scopeManager.FindByNameAsync("Sample") == null)
+ {
+ await _scopeManager.CreateAsync(new OpenIddictScopeDescriptor
+ {
+ Name = "Sample",
+ DisplayName = "Sample API",
+ Resources =
+ {
+ "Sample"
+ }
+ });
+ }
+ }
+
+ private async Task CreateApplicationsAsync()
+ {
+ var commonScopes = new List
+ {
+ OpenIddictConstants.Permissions.Scopes.Address,
+ OpenIddictConstants.Permissions.Scopes.Email,
+ OpenIddictConstants.Permissions.Scopes.Phone,
+ OpenIddictConstants.Permissions.Scopes.Profile,
+ OpenIddictConstants.Permissions.Scopes.Roles,
+ "Sample"
+ };
+
+ var configurationSection = _configuration.GetSection("OpenIddict:Applications");
+
+ //Web Client
+ var webClientId = configurationSection["Sample_Web:ClientId"];
+ if (!webClientId.IsNullOrWhiteSpace())
+ {
+ var webClientRootUrl = configurationSection["Sample_Web:RootUrl"].EnsureEndsWith('/');
+
+ /* Sample_Web client is only needed if you created a tiered
+ * solution. Otherwise, you can delete this client. */
+ await CreateApplicationAsync(
+ name: webClientId!,
+ type: OpenIddictConstants.ClientTypes.Confidential,
+ consentType: OpenIddictConstants.ConsentTypes.Implicit,
+ displayName: "Web Application",
+ secret: configurationSection["Sample_Web:ClientSecret"] ?? "1q2w3e*",
+ grantTypes: new List //Hybrid flow
+ {
+ OpenIddictConstants.GrantTypes.AuthorizationCode,
+ OpenIddictConstants.GrantTypes.Implicit
+ },
+ scopes: commonScopes,
+ redirectUri: $"{webClientRootUrl}signin-oidc",
+ clientUri: webClientRootUrl,
+ postLogoutRedirectUri: $"{webClientRootUrl}signout-callback-oidc"
+ );
+ }
+
+ //Console Test / Angular Client
+ var consoleAndAngularClientId = configurationSection["Sample_App:ClientId"];
+ if (!consoleAndAngularClientId.IsNullOrWhiteSpace())
+ {
+ var consoleAndAngularClientRootUrl = configurationSection["Sample_App:RootUrl"]?.TrimEnd('/');
+ await CreateApplicationAsync(
+ name: consoleAndAngularClientId!,
+ type: OpenIddictConstants.ClientTypes.Public,
+ consentType: OpenIddictConstants.ConsentTypes.Implicit,
+ displayName: "Console Test / Angular Application",
+ secret: null,
+ grantTypes: new List
+ {
+ OpenIddictConstants.GrantTypes.AuthorizationCode,
+ OpenIddictConstants.GrantTypes.Password,
+ OpenIddictConstants.GrantTypes.ClientCredentials,
+ OpenIddictConstants.GrantTypes.RefreshToken
+ },
+ scopes: commonScopes,
+ redirectUri: consoleAndAngularClientRootUrl,
+ clientUri: consoleAndAngularClientRootUrl,
+ postLogoutRedirectUri: consoleAndAngularClientRootUrl
+ );
+ }
+
+ // Blazor Client
+ var blazorClientId = configurationSection["Sample_Blazor:ClientId"];
+ if (!blazorClientId.IsNullOrWhiteSpace())
+ {
+ var blazorRootUrl = configurationSection["Sample_Blazor:RootUrl"]?.TrimEnd('/');
+
+ await CreateApplicationAsync(
+ name: blazorClientId!,
+ type: OpenIddictConstants.ClientTypes.Public,
+ consentType: OpenIddictConstants.ConsentTypes.Implicit,
+ displayName: "Blazor Application",
+ secret: null,
+ grantTypes: new List
+ {
+ OpenIddictConstants.GrantTypes.AuthorizationCode,
+ },
+ scopes: commonScopes,
+ redirectUri: $"{blazorRootUrl}/authentication/login-callback",
+ clientUri: blazorRootUrl,
+ postLogoutRedirectUri: $"{blazorRootUrl}/authentication/logout-callback"
+ );
+ }
+
+ // Blazor Server Tiered Client
+ var blazorServerTieredClientId = configurationSection["Sample_BlazorServerTiered:ClientId"];
+ if (!blazorServerTieredClientId.IsNullOrWhiteSpace())
+ {
+ var blazorServerTieredRootUrl = configurationSection["Sample_BlazorServerTiered:RootUrl"].EnsureEndsWith('/');
+
+ await CreateApplicationAsync(
+ name: blazorServerTieredClientId!,
+ type: OpenIddictConstants.ClientTypes.Confidential,
+ consentType: OpenIddictConstants.ConsentTypes.Implicit,
+ displayName: "Blazor Server Application",
+ secret: configurationSection["Sample_BlazorServerTiered:ClientSecret"] ?? "1q2w3e*",
+ grantTypes: new List //Hybrid flow
+ {
+ OpenIddictConstants.GrantTypes.AuthorizationCode,
+ OpenIddictConstants.GrantTypes.Implicit
+ },
+ scopes: commonScopes,
+ redirectUri: $"{blazorServerTieredRootUrl}signin-oidc",
+ clientUri: blazorServerTieredRootUrl,
+ postLogoutRedirectUri: $"{blazorServerTieredRootUrl}signout-callback-oidc"
+ );
+ }
+
+ // Swagger Client
+ var swaggerClientId = configurationSection["Sample_Swagger:ClientId"];
+ if (!swaggerClientId.IsNullOrWhiteSpace())
+ {
+ var swaggerRootUrl = configurationSection["Sample_Swagger:RootUrl"]?.TrimEnd('/');
+
+ await CreateApplicationAsync(
+ name: swaggerClientId!,
+ type: OpenIddictConstants.ClientTypes.Public,
+ consentType: OpenIddictConstants.ConsentTypes.Implicit,
+ displayName: "Swagger Application",
+ secret: null,
+ grantTypes: new List
+ {
+ OpenIddictConstants.GrantTypes.AuthorizationCode,
+ },
+ scopes: commonScopes,
+ redirectUri: $"{swaggerRootUrl}/swagger/oauth2-redirect.html",
+ clientUri: swaggerRootUrl
+ );
+ }
+ }
+
+ private async Task CreateApplicationAsync(
+ [NotNull] string name,
+ [NotNull] string type,
+ [NotNull] string consentType,
+ string displayName,
+ string? secret,
+ List grantTypes,
+ List scopes,
+ string? clientUri = null,
+ string? redirectUri = null,
+ string? postLogoutRedirectUri = null,
+ List? permissions = null)
+ {
+ if (!string.IsNullOrEmpty(secret) && string.Equals(type, OpenIddictConstants.ClientTypes.Public, StringComparison.OrdinalIgnoreCase))
+ {
+ throw new BusinessException(L["NoClientSecretCanBeSetForPublicApplications"]);
+ }
+
+ if (string.IsNullOrEmpty(secret) && string.Equals(type, OpenIddictConstants.ClientTypes.Confidential, StringComparison.OrdinalIgnoreCase))
+ {
+ throw new BusinessException(L["TheClientSecretIsRequiredForConfidentialApplications"]);
+ }
+
+ if (!string.IsNullOrEmpty(name) && await _applicationManager.FindByClientIdAsync(name) != null)
+ {
+ return;
+ //throw new BusinessException(L["TheClientIdentifierIsAlreadyTakenByAnotherApplication"]);
+ }
+
+ var client = await _applicationManager.FindByClientIdAsync(name);
+ if (client == null)
+ {
+ var application = new AbpApplicationDescriptor
+ {
+ ClientId = name,
+ Type = type,
+ ClientSecret = secret,
+ ConsentType = consentType,
+ DisplayName = displayName,
+ ClientUri = clientUri,
+ };
+
+ Check.NotNullOrEmpty(grantTypes, nameof(grantTypes));
+ Check.NotNullOrEmpty(scopes, nameof(scopes));
+
+ if (new [] { OpenIddictConstants.GrantTypes.AuthorizationCode, OpenIddictConstants.GrantTypes.Implicit }.All(grantTypes.Contains))
+ {
+ application.Permissions.Add(OpenIddictConstants.Permissions.ResponseTypes.CodeIdToken);
+
+ if (string.Equals(type, OpenIddictConstants.ClientTypes.Public, StringComparison.OrdinalIgnoreCase))
+ {
+ application.Permissions.Add(OpenIddictConstants.Permissions.ResponseTypes.CodeIdTokenToken);
+ application.Permissions.Add(OpenIddictConstants.Permissions.ResponseTypes.CodeToken);
+ }
+ }
+
+ if (!redirectUri.IsNullOrWhiteSpace() || !postLogoutRedirectUri.IsNullOrWhiteSpace())
+ {
+ application.Permissions.Add(OpenIddictConstants.Permissions.Endpoints.Logout);
+ }
+
+ var buildInGrantTypes = new []
+ {
+ OpenIddictConstants.GrantTypes.Implicit,
+ OpenIddictConstants.GrantTypes.Password,
+ OpenIddictConstants.GrantTypes.AuthorizationCode,
+ OpenIddictConstants.GrantTypes.ClientCredentials,
+ OpenIddictConstants.GrantTypes.DeviceCode,
+ OpenIddictConstants.GrantTypes.RefreshToken
+ };
+
+ foreach (var grantType in grantTypes)
+ {
+ if (grantType == OpenIddictConstants.GrantTypes.AuthorizationCode)
+ {
+ application.Permissions.Add(OpenIddictConstants.Permissions.GrantTypes.AuthorizationCode);
+ application.Permissions.Add(OpenIddictConstants.Permissions.ResponseTypes.Code);
+ }
+
+ if (grantType == OpenIddictConstants.GrantTypes.AuthorizationCode || grantType == OpenIddictConstants.GrantTypes.Implicit)
+ {
+ application.Permissions.Add(OpenIddictConstants.Permissions.Endpoints.Authorization);
+ }
+
+ if (grantType == OpenIddictConstants.GrantTypes.AuthorizationCode ||
+ grantType == OpenIddictConstants.GrantTypes.ClientCredentials ||
+ grantType == OpenIddictConstants.GrantTypes.Password ||
+ grantType == OpenIddictConstants.GrantTypes.RefreshToken ||
+ grantType == OpenIddictConstants.GrantTypes.DeviceCode)
+ {
+ application.Permissions.Add(OpenIddictConstants.Permissions.Endpoints.Token);
+ application.Permissions.Add(OpenIddictConstants.Permissions.Endpoints.Revocation);
+ application.Permissions.Add(OpenIddictConstants.Permissions.Endpoints.Introspection);
+ }
+
+ if (grantType == OpenIddictConstants.GrantTypes.ClientCredentials)
+ {
+ application.Permissions.Add(OpenIddictConstants.Permissions.GrantTypes.ClientCredentials);
+ }
+
+ if (grantType == OpenIddictConstants.GrantTypes.Implicit)
+ {
+ application.Permissions.Add(OpenIddictConstants.Permissions.GrantTypes.Implicit);
+ }
+
+ if (grantType == OpenIddictConstants.GrantTypes.Password)
+ {
+ application.Permissions.Add(OpenIddictConstants.Permissions.GrantTypes.Password);
+ }
+
+ if (grantType == OpenIddictConstants.GrantTypes.RefreshToken)
+ {
+ application.Permissions.Add(OpenIddictConstants.Permissions.GrantTypes.RefreshToken);
+ }
+
+ if (grantType == OpenIddictConstants.GrantTypes.DeviceCode)
+ {
+ application.Permissions.Add(OpenIddictConstants.Permissions.GrantTypes.DeviceCode);
+ application.Permissions.Add(OpenIddictConstants.Permissions.Endpoints.Device);
+ }
+
+ if (grantType == OpenIddictConstants.GrantTypes.Implicit)
+ {
+ application.Permissions.Add(OpenIddictConstants.Permissions.ResponseTypes.IdToken);
+ if (string.Equals(type, OpenIddictConstants.ClientTypes.Public, StringComparison.OrdinalIgnoreCase))
+ {
+ application.Permissions.Add(OpenIddictConstants.Permissions.ResponseTypes.IdTokenToken);
+ application.Permissions.Add(OpenIddictConstants.Permissions.ResponseTypes.Token);
+ }
+ }
+
+ if (!buildInGrantTypes.Contains(grantType))
+ {
+ application.Permissions.Add(OpenIddictConstants.Permissions.Prefixes.GrantType + grantType);
+ }
+ }
+
+ var buildInScopes = new []
+ {
+ OpenIddictConstants.Permissions.Scopes.Address,
+ OpenIddictConstants.Permissions.Scopes.Email,
+ OpenIddictConstants.Permissions.Scopes.Phone,
+ OpenIddictConstants.Permissions.Scopes.Profile,
+ OpenIddictConstants.Permissions.Scopes.Roles
+ };
+
+ foreach (var scope in scopes)
+ {
+ if (buildInScopes.Contains(scope))
+ {
+ application.Permissions.Add(scope);
+ }
+ else
+ {
+ application.Permissions.Add(OpenIddictConstants.Permissions.Prefixes.Scope + scope);
+ }
+ }
+
+ if (redirectUri != null)
+ {
+ if (!redirectUri.IsNullOrEmpty())
+ {
+ if (!Uri.TryCreate(redirectUri, UriKind.Absolute, out var uri) || !uri.IsWellFormedOriginalString())
+ {
+ throw new BusinessException(L["InvalidRedirectUri", redirectUri]);
+ }
+
+ if (application.RedirectUris.All(x => x != uri))
+ {
+ application.RedirectUris.Add(uri);
+ }
+ }
+ }
+
+ if (postLogoutRedirectUri != null)
+ {
+ if (!postLogoutRedirectUri.IsNullOrEmpty())
+ {
+ if (!Uri.TryCreate(postLogoutRedirectUri, UriKind.Absolute, out var uri) || !uri.IsWellFormedOriginalString())
+ {
+ throw new BusinessException(L["InvalidPostLogoutRedirectUri", postLogoutRedirectUri]);
+ }
+
+ if (application.PostLogoutRedirectUris.All(x => x != uri))
+ {
+ application.PostLogoutRedirectUris.Add(uri);
+ }
+ }
+ }
+
+ if (permissions != null)
+ {
+ await _permissionDataSeeder.SeedAsync(
+ ClientPermissionValueProvider.ProviderName,
+ name,
+ permissions,
+ null
+ );
+ }
+
+ await _applicationManager.CreateAsync(application);
+ }
+ }
+}
diff --git a/host/src/Sample.Domain/Properties/AssemblyInfo.cs b/host/src/Sample.Domain/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..ee174f1
--- /dev/null
+++ b/host/src/Sample.Domain/Properties/AssemblyInfo.cs
@@ -0,0 +1,3 @@
+using System.Runtime.CompilerServices;
+[assembly:InternalsVisibleToAttribute("Sample.Domain.Tests")]
+[assembly:InternalsVisibleToAttribute("Sample.TestBase")]
diff --git a/host/src/Sample.Domain/Sample.Domain.csproj b/host/src/Sample.Domain/Sample.Domain.csproj
new file mode 100644
index 0000000..791f1f3
--- /dev/null
+++ b/host/src/Sample.Domain/Sample.Domain.csproj
@@ -0,0 +1,28 @@
+
+
+
+
+
+ net7.0
+ enable
+ Sample
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/host/src/Sample.Domain/SampleConsts.cs b/host/src/Sample.Domain/SampleConsts.cs
new file mode 100644
index 0000000..e5d6320
--- /dev/null
+++ b/host/src/Sample.Domain/SampleConsts.cs
@@ -0,0 +1,8 @@
+namespace Sample;
+
+public static class SampleConsts
+{
+ public const string DbTablePrefix = "App";
+
+ public const string DbSchema = null;
+}
diff --git a/host/src/Sample.Domain/SampleDomainModule.cs b/host/src/Sample.Domain/SampleDomainModule.cs
new file mode 100644
index 0000000..1990591
--- /dev/null
+++ b/host/src/Sample.Domain/SampleDomainModule.cs
@@ -0,0 +1,68 @@
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.DependencyInjection.Extensions;
+using Sample.MultiTenancy;
+using Volo.Abp.AuditLogging;
+using Volo.Abp.BackgroundJobs;
+using Volo.Abp.Emailing;
+using Volo.Abp.FeatureManagement;
+using Volo.Abp.Identity;
+using Volo.Abp.Localization;
+using Volo.Abp.Modularity;
+using Volo.Abp.MultiTenancy;
+using Volo.Abp.OpenIddict;
+using Volo.Abp.PermissionManagement.Identity;
+using Volo.Abp.PermissionManagement.OpenIddict;
+using Volo.Abp.SettingManagement;
+using Volo.Abp.TenantManagement;
+
+namespace Sample;
+
+[DependsOn(
+ typeof(SampleDomainSharedModule),
+ typeof(AbpAuditLoggingDomainModule),
+ typeof(AbpBackgroundJobsDomainModule),
+ typeof(AbpFeatureManagementDomainModule),
+ typeof(AbpIdentityDomainModule),
+ typeof(AbpOpenIddictDomainModule),
+ typeof(AbpPermissionManagementDomainOpenIddictModule),
+ typeof(AbpPermissionManagementDomainIdentityModule),
+ typeof(AbpSettingManagementDomainModule),
+ typeof(AbpTenantManagementDomainModule),
+ typeof(AbpEmailingModule)
+)]
+public class SampleDomainModule : AbpModule
+{
+ public override void ConfigureServices(ServiceConfigurationContext context)
+ {
+ Configure(options =>
+ {
+ options.Languages.Add(new LanguageInfo("ar", "ar", "العربية", "ae"));
+ options.Languages.Add(new LanguageInfo("cs", "cs", "Čeština"));
+ options.Languages.Add(new LanguageInfo("en", "en", "English", "gb"));
+ options.Languages.Add(new LanguageInfo("en-GB", "en-GB", "English (UK)"));
+ options.Languages.Add(new LanguageInfo("hu", "hu", "Magyar"));
+ options.Languages.Add(new LanguageInfo("hr", "hr", "Croatian"));
+ options.Languages.Add(new LanguageInfo("fi", "fi", "Finnish", "fi"));
+ options.Languages.Add(new LanguageInfo("fr", "fr", "Français", "fr"));
+ options.Languages.Add(new LanguageInfo("hi", "hi", "Hindi", "in"));
+ options.Languages.Add(new LanguageInfo("it", "it", "Italiano", "it"));
+ options.Languages.Add(new LanguageInfo("pt-BR", "pt-BR", "Português"));
+ options.Languages.Add(new LanguageInfo("ru", "ru", "Русский", "ru"));
+ options.Languages.Add(new LanguageInfo("sk", "sk", "Slovak", "sk"));
+ options.Languages.Add(new LanguageInfo("tr", "tr", "Türkçe", "tr"));
+ options.Languages.Add(new LanguageInfo("zh-Hans", "zh-Hans", "简体中文"));
+ options.Languages.Add(new LanguageInfo("zh-Hant", "zh-Hant", "繁體中文"));
+ options.Languages.Add(new LanguageInfo("de-DE", "de-DE", "Deutsch", "de"));
+ options.Languages.Add(new LanguageInfo("es", "es", "Español"));
+ });
+
+ Configure(options =>
+ {
+ options.IsEnabled = MultiTenancyConsts.IsEnabled;
+ });
+
+#if DEBUG
+ context.Services.Replace(ServiceDescriptor.Singleton());
+#endif
+ }
+}
diff --git a/host/src/Sample.Domain/Settings/SampleSettingDefinitionProvider.cs b/host/src/Sample.Domain/Settings/SampleSettingDefinitionProvider.cs
new file mode 100644
index 0000000..a32730e
--- /dev/null
+++ b/host/src/Sample.Domain/Settings/SampleSettingDefinitionProvider.cs
@@ -0,0 +1,12 @@
+using Volo.Abp.Settings;
+
+namespace Sample.Settings;
+
+public class SampleSettingDefinitionProvider : SettingDefinitionProvider
+{
+ public override void Define(ISettingDefinitionContext context)
+ {
+ //Define your own settings here. Example:
+ //context.Add(new SettingDefinition(SampleSettings.MySetting1));
+ }
+}
diff --git a/host/src/Sample.Domain/Settings/SampleSettings.cs b/host/src/Sample.Domain/Settings/SampleSettings.cs
new file mode 100644
index 0000000..1d233ee
--- /dev/null
+++ b/host/src/Sample.Domain/Settings/SampleSettings.cs
@@ -0,0 +1,9 @@
+namespace Sample.Settings;
+
+public static class SampleSettings
+{
+ private const string Prefix = "Sample";
+
+ //Add your own setting names here. Example:
+ //public const string MySetting1 = Prefix + ".MySetting1";
+}
diff --git a/host/src/Sample.EntityFrameworkCore/EntityFrameworkCore/EntityFrameworkCoreSampleDbSchemaMigrator.cs b/host/src/Sample.EntityFrameworkCore/EntityFrameworkCore/EntityFrameworkCoreSampleDbSchemaMigrator.cs
new file mode 100644
index 0000000..498f3fd
--- /dev/null
+++ b/host/src/Sample.EntityFrameworkCore/EntityFrameworkCore/EntityFrameworkCoreSampleDbSchemaMigrator.cs
@@ -0,0 +1,34 @@
+using System;
+using System.Threading.Tasks;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.Extensions.DependencyInjection;
+using Sample.Data;
+using Volo.Abp.DependencyInjection;
+
+namespace Sample.EntityFrameworkCore;
+
+public class EntityFrameworkCoreSampleDbSchemaMigrator
+ : ISampleDbSchemaMigrator, ITransientDependency
+{
+ private readonly IServiceProvider _serviceProvider;
+
+ public EntityFrameworkCoreSampleDbSchemaMigrator(
+ IServiceProvider serviceProvider)
+ {
+ _serviceProvider = serviceProvider;
+ }
+
+ public async Task MigrateAsync()
+ {
+ /* We intentionally resolving the SampleDbContext
+ * from IServiceProvider (instead of directly injecting it)
+ * to properly get the connection string of the current tenant in the
+ * current scope.
+ */
+
+ await _serviceProvider
+ .GetRequiredService()
+ .Database
+ .MigrateAsync();
+ }
+}
diff --git a/host/src/Sample.EntityFrameworkCore/EntityFrameworkCore/SampleDbContext.cs b/host/src/Sample.EntityFrameworkCore/EntityFrameworkCore/SampleDbContext.cs
new file mode 100644
index 0000000..d345e4b
--- /dev/null
+++ b/host/src/Sample.EntityFrameworkCore/EntityFrameworkCore/SampleDbContext.cs
@@ -0,0 +1,86 @@
+using Microsoft.EntityFrameworkCore;
+using Volo.Abp.AuditLogging.EntityFrameworkCore;
+using Volo.Abp.BackgroundJobs.EntityFrameworkCore;
+using Volo.Abp.Data;
+using Volo.Abp.DependencyInjection;
+using Volo.Abp.EntityFrameworkCore;
+using Volo.Abp.FeatureManagement.EntityFrameworkCore;
+using Volo.Abp.Identity;
+using Volo.Abp.Identity.EntityFrameworkCore;
+using Volo.Abp.OpenIddict.EntityFrameworkCore;
+using Volo.Abp.PermissionManagement.EntityFrameworkCore;
+using Volo.Abp.SettingManagement.EntityFrameworkCore;
+using Volo.Abp.TenantManagement;
+using Volo.Abp.TenantManagement.EntityFrameworkCore;
+
+namespace Sample.EntityFrameworkCore;
+
+[ReplaceDbContext(typeof(IIdentityDbContext))]
+[ReplaceDbContext(typeof(ITenantManagementDbContext))]
+[ConnectionStringName("Default")]
+public class SampleDbContext :
+ AbpDbContext,
+ IIdentityDbContext,
+ ITenantManagementDbContext
+{
+ /* Add DbSet properties for your Aggregate Roots / Entities here. */
+
+ #region Entities from the modules
+
+ /* Notice: We only implemented IIdentityDbContext and ITenantManagementDbContext
+ * and replaced them for this DbContext. This allows you to perform JOIN
+ * queries for the entities of these modules over the repositories easily. You
+ * typically don't need that for other modules. But, if you need, you can
+ * implement the DbContext interface of the needed module and use ReplaceDbContext
+ * attribute just like IIdentityDbContext and ITenantManagementDbContext.
+ *
+ * More info: Replacing a DbContext of a module ensures that the related module
+ * uses this DbContext on runtime. Otherwise, it will use its own DbContext class.
+ */
+
+ //Identity
+ public DbSet Users { get; set; }
+ public DbSet Roles { get; set; }
+ public DbSet ClaimTypes { get; set; }
+ public DbSet OrganizationUnits { get; set; }
+ public DbSet SecurityLogs { get; set; }
+ public DbSet LinkUsers { get; set; }
+ public DbSet UserDelegations { get; set; }
+
+ // Tenant Management
+ public DbSet Tenants { get; set; }
+ public DbSet TenantConnectionStrings { get; set; }
+
+ #endregion
+
+ public SampleDbContext(DbContextOptions options)
+ : base(options)
+ {
+
+ }
+
+ protected override void OnModelCreating(ModelBuilder builder)
+ {
+ base.OnModelCreating(builder);
+
+ /* Include modules to your migration db context */
+
+ builder.ConfigurePermissionManagement();
+ builder.ConfigureSettingManagement();
+ builder.ConfigureBackgroundJobs();
+ builder.ConfigureAuditLogging();
+ builder.ConfigureIdentity();
+ builder.ConfigureOpenIddict();
+ builder.ConfigureFeatureManagement();
+ builder.ConfigureTenantManagement();
+
+ /* Configure your own tables/entities inside here */
+
+ //builder.Entity(b =>
+ //{
+ // b.ToTable(SampleConsts.DbTablePrefix + "YourEntities", SampleConsts.DbSchema);
+ // b.ConfigureByConvention(); //auto configure for the base class props
+ // //...
+ //});
+ }
+}
diff --git a/host/src/Sample.EntityFrameworkCore/EntityFrameworkCore/SampleDbContextFactory.cs b/host/src/Sample.EntityFrameworkCore/EntityFrameworkCore/SampleDbContextFactory.cs
new file mode 100644
index 0000000..61c7ce7
--- /dev/null
+++ b/host/src/Sample.EntityFrameworkCore/EntityFrameworkCore/SampleDbContextFactory.cs
@@ -0,0 +1,33 @@
+using System;
+using System.IO;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Design;
+using Microsoft.Extensions.Configuration;
+
+namespace Sample.EntityFrameworkCore;
+
+/* This class is needed for EF Core console commands
+ * (like Add-Migration and Update-Database commands) */
+public class SampleDbContextFactory : IDesignTimeDbContextFactory
+{
+ public SampleDbContext CreateDbContext(string[] args)
+ {
+ SampleEfCoreEntityExtensionMappings.Configure();
+
+ var configuration = BuildConfiguration();
+
+ var builder = new DbContextOptionsBuilder()
+ .UseSqlServer(configuration.GetConnectionString("Default"));
+
+ return new SampleDbContext(builder.Options);
+ }
+
+ private static IConfigurationRoot BuildConfiguration()
+ {
+ var builder = new ConfigurationBuilder()
+ .SetBasePath(Path.Combine(Directory.GetCurrentDirectory(), "../Sample.DbMigrator/"))
+ .AddJsonFile("appsettings.json", optional: false);
+
+ return builder.Build();
+ }
+}
diff --git a/host/src/Sample.EntityFrameworkCore/EntityFrameworkCore/SampleEfCoreEntityExtensionMappings.cs b/host/src/Sample.EntityFrameworkCore/EntityFrameworkCore/SampleEfCoreEntityExtensionMappings.cs
new file mode 100644
index 0000000..88f78c2
--- /dev/null
+++ b/host/src/Sample.EntityFrameworkCore/EntityFrameworkCore/SampleEfCoreEntityExtensionMappings.cs
@@ -0,0 +1,44 @@
+using Microsoft.EntityFrameworkCore;
+using Volo.Abp.Identity;
+using Volo.Abp.ObjectExtending;
+using Volo.Abp.Threading;
+
+namespace Sample.EntityFrameworkCore;
+
+public static class SampleEfCoreEntityExtensionMappings
+{
+ private static readonly OneTimeRunner OneTimeRunner = new OneTimeRunner();
+
+ public static void Configure()
+ {
+ SampleGlobalFeatureConfigurator.Configure();
+ SampleModuleExtensionConfigurator.Configure();
+
+ OneTimeRunner.Run(() =>
+ {
+ /* You can configure extra properties for the
+ * entities defined in the modules used by your application.
+ *
+ * This class can be used to map these extra properties to table fields in the database.
+ *
+ * USE THIS CLASS ONLY TO CONFIGURE EF CORE RELATED MAPPING.
+ * USE SampleModuleExtensionConfigurator CLASS (in the Domain.Shared project)
+ * FOR A HIGH LEVEL API TO DEFINE EXTRA PROPERTIES TO ENTITIES OF THE USED MODULES
+ *
+ * Example: Map a property to a table field:
+
+ ObjectExtensionManager.Instance
+ .MapEfCoreProperty(
+ "MyProperty",
+ (entityBuilder, propertyBuilder) =>
+ {
+ propertyBuilder.HasMaxLength(128);
+ }
+ );
+
+ * See the documentation for more:
+ * https://docs.abp.io/en/abp/latest/Customizing-Application-Modules-Extending-Entities
+ */
+ });
+ }
+}
diff --git a/host/src/Sample.EntityFrameworkCore/EntityFrameworkCore/SampleEntityFrameworkCoreModule.cs b/host/src/Sample.EntityFrameworkCore/EntityFrameworkCore/SampleEntityFrameworkCoreModule.cs
new file mode 100644
index 0000000..9daee47
--- /dev/null
+++ b/host/src/Sample.EntityFrameworkCore/EntityFrameworkCore/SampleEntityFrameworkCoreModule.cs
@@ -0,0 +1,54 @@
+using System;
+using Microsoft.Extensions.DependencyInjection;
+using Volo.Abp.Uow;
+using Volo.Abp.AuditLogging.EntityFrameworkCore;
+using Volo.Abp.BackgroundJobs.EntityFrameworkCore;
+using Volo.Abp.EntityFrameworkCore;
+using Volo.Abp.EntityFrameworkCore.SqlServer;
+using Volo.Abp.FeatureManagement.EntityFrameworkCore;
+using Volo.Abp.Identity.EntityFrameworkCore;
+using Volo.Abp.Modularity;
+using Volo.Abp.OpenIddict.EntityFrameworkCore;
+using Volo.Abp.PermissionManagement.EntityFrameworkCore;
+using Volo.Abp.SettingManagement.EntityFrameworkCore;
+using Volo.Abp.TenantManagement.EntityFrameworkCore;
+
+namespace Sample.EntityFrameworkCore;
+
+[DependsOn(
+ typeof(SampleDomainModule),
+ typeof(AbpIdentityEntityFrameworkCoreModule),
+ typeof(AbpOpenIddictEntityFrameworkCoreModule),
+ typeof(AbpPermissionManagementEntityFrameworkCoreModule),
+ typeof(AbpSettingManagementEntityFrameworkCoreModule),
+ typeof(AbpEntityFrameworkCoreSqlServerModule),
+ typeof(AbpBackgroundJobsEntityFrameworkCoreModule),
+ typeof(AbpAuditLoggingEntityFrameworkCoreModule),
+ typeof(AbpTenantManagementEntityFrameworkCoreModule),
+ typeof(AbpFeatureManagementEntityFrameworkCoreModule)
+ )]
+public class SampleEntityFrameworkCoreModule : AbpModule
+{
+ public override void PreConfigureServices(ServiceConfigurationContext context)
+ {
+ SampleEfCoreEntityExtensionMappings.Configure();
+ }
+
+ public override void ConfigureServices(ServiceConfigurationContext context)
+ {
+ context.Services.AddAbpDbContext(options =>
+ {
+ /* Remove "includeAllEntities: true" to create
+ * default repositories only for aggregate roots */
+ options.AddDefaultRepositories(includeAllEntities: true);
+ });
+
+ Configure(options =>
+ {
+ /* The main point to change your DBMS.
+ * See also SampleMigrationsDbContextFactory for EF Core tooling. */
+ options.UseSqlServer();
+ });
+
+ }
+}
diff --git a/host/src/Sample.EntityFrameworkCore/Migrations/20230707030931_Initial.Designer.cs b/host/src/Sample.EntityFrameworkCore/Migrations/20230707030931_Initial.Designer.cs
new file mode 100644
index 0000000..8baae25
--- /dev/null
+++ b/host/src/Sample.EntityFrameworkCore/Migrations/20230707030931_Initial.Designer.cs
@@ -0,0 +1,1870 @@
+//
+using System;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Metadata;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+using Sample.EntityFrameworkCore;
+using Volo.Abp.EntityFrameworkCore;
+
+#nullable disable
+
+namespace Sample.Migrations
+{
+ [DbContext(typeof(SampleDbContext))]
+ [Migration("20230707030931_Initial")]
+ partial class Initial
+ {
+ ///
+ protected override void BuildTargetModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder
+ .HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.SqlServer)
+ .HasAnnotation("ProductVersion", "7.0.1")
+ .HasAnnotation("Relational:MaxIdentifierLength", 128);
+
+ SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
+
+ modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLog", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("ApplicationName")
+ .HasMaxLength(96)
+ .HasColumnType("nvarchar(96)")
+ .HasColumnName("ApplicationName");
+
+ b.Property("BrowserInfo")
+ .HasMaxLength(512)
+ .HasColumnType("nvarchar(512)")
+ .HasColumnName("BrowserInfo");
+
+ b.Property("ClientId")
+ .HasMaxLength(64)
+ .HasColumnType("nvarchar(64)")
+ .HasColumnName("ClientId");
+
+ b.Property("ClientIpAddress")
+ .HasMaxLength(64)
+ .HasColumnType("nvarchar(64)")
+ .HasColumnName("ClientIpAddress");
+
+ b.Property("ClientName")
+ .HasMaxLength(128)
+ .HasColumnType("nvarchar(128)")
+ .HasColumnName("ClientName");
+
+ b.Property("Comments")
+ .HasMaxLength(256)
+ .HasColumnType("nvarchar(256)")
+ .HasColumnName("Comments");
+
+ b.Property("ConcurrencyStamp")
+ .IsConcurrencyToken()
+ .HasMaxLength(40)
+ .HasColumnType("nvarchar(40)")
+ .HasColumnName("ConcurrencyStamp");
+
+ b.Property("CorrelationId")
+ .HasMaxLength(64)
+ .HasColumnType("nvarchar(64)")
+ .HasColumnName("CorrelationId");
+
+ b.Property("Exceptions")
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("ExecutionDuration")
+ .HasColumnType("int")
+ .HasColumnName("ExecutionDuration");
+
+ b.Property("ExecutionTime")
+ .HasColumnType("datetime2");
+
+ b.Property("ExtraProperties")
+ .HasColumnType("nvarchar(max)")
+ .HasColumnName("ExtraProperties");
+
+ b.Property("HttpMethod")
+ .HasMaxLength(16)
+ .HasColumnType("nvarchar(16)")
+ .HasColumnName("HttpMethod");
+
+ b.Property("HttpStatusCode")
+ .HasColumnType("int")
+ .HasColumnName("HttpStatusCode");
+
+ b.Property("ImpersonatorTenantId")
+ .HasColumnType("uniqueidentifier")
+ .HasColumnName("ImpersonatorTenantId");
+
+ b.Property("ImpersonatorTenantName")
+ .HasMaxLength(64)
+ .HasColumnType("nvarchar(64)")
+ .HasColumnName("ImpersonatorTenantName");
+
+ b.Property("ImpersonatorUserId")
+ .HasColumnType("uniqueidentifier")
+ .HasColumnName("ImpersonatorUserId");
+
+ b.Property("ImpersonatorUserName")
+ .HasMaxLength(256)
+ .HasColumnType("nvarchar(256)")
+ .HasColumnName("ImpersonatorUserName");
+
+ b.Property("TenantId")
+ .HasColumnType("uniqueidentifier")
+ .HasColumnName("TenantId");
+
+ b.Property("TenantName")
+ .HasMaxLength(64)
+ .HasColumnType("nvarchar(64)")
+ .HasColumnName("TenantName");
+
+ b.Property("Url")
+ .HasMaxLength(256)
+ .HasColumnType("nvarchar(256)")
+ .HasColumnName("Url");
+
+ b.Property("UserId")
+ .HasColumnType("uniqueidentifier")
+ .HasColumnName("UserId");
+
+ b.Property("UserName")
+ .HasMaxLength(256)
+ .HasColumnType("nvarchar(256)")
+ .HasColumnName("UserName");
+
+ b.HasKey("Id");
+
+ b.HasIndex("TenantId", "ExecutionTime");
+
+ b.HasIndex("TenantId", "UserId", "ExecutionTime");
+
+ b.ToTable("AbpAuditLogs", (string)null);
+ });
+
+ modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLogAction", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("AuditLogId")
+ .HasColumnType("uniqueidentifier")
+ .HasColumnName("AuditLogId");
+
+ b.Property("ExecutionDuration")
+ .HasColumnType("int")
+ .HasColumnName("ExecutionDuration");
+
+ b.Property("ExecutionTime")
+ .HasColumnType("datetime2")
+ .HasColumnName("ExecutionTime");
+
+ b.Property("ExtraProperties")
+ .HasColumnType("nvarchar(max)")
+ .HasColumnName("ExtraProperties");
+
+ b.Property("MethodName")
+ .HasMaxLength(128)
+ .HasColumnType("nvarchar(128)")
+ .HasColumnName("MethodName");
+
+ b.Property("Parameters")
+ .HasMaxLength(2000)
+ .HasColumnType("nvarchar(2000)")
+ .HasColumnName("Parameters");
+
+ b.Property("ServiceName")
+ .HasMaxLength(256)
+ .HasColumnType("nvarchar(256)")
+ .HasColumnName("ServiceName");
+
+ b.Property("TenantId")
+ .HasColumnType("uniqueidentifier")
+ .HasColumnName("TenantId");
+
+ b.HasKey("Id");
+
+ b.HasIndex("AuditLogId");
+
+ b.HasIndex("TenantId", "ServiceName", "MethodName", "ExecutionTime");
+
+ b.ToTable("AbpAuditLogActions", (string)null);
+ });
+
+ modelBuilder.Entity("Volo.Abp.AuditLogging.EntityChange", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("AuditLogId")
+ .HasColumnType("uniqueidentifier")
+ .HasColumnName("AuditLogId");
+
+ b.Property("ChangeTime")
+ .HasColumnType("datetime2")
+ .HasColumnName("ChangeTime");
+
+ b.Property("ChangeType")
+ .HasColumnType("tinyint")
+ .HasColumnName("ChangeType");
+
+ b.Property("EntityId")
+ .IsRequired()
+ .HasMaxLength(128)
+ .HasColumnType("nvarchar(128)")
+ .HasColumnName("EntityId");
+
+ b.Property("EntityTenantId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("EntityTypeFullName")
+ .IsRequired()
+ .HasMaxLength(128)
+ .HasColumnType("nvarchar(128)")
+ .HasColumnName("EntityTypeFullName");
+
+ b.Property("ExtraProperties")
+ .HasColumnType("nvarchar(max)")
+ .HasColumnName("ExtraProperties");
+
+ b.Property("TenantId")
+ .HasColumnType("uniqueidentifier")
+ .HasColumnName("TenantId");
+
+ b.HasKey("Id");
+
+ b.HasIndex("AuditLogId");
+
+ b.HasIndex("TenantId", "EntityTypeFullName", "EntityId");
+
+ b.ToTable("AbpEntityChanges", (string)null);
+ });
+
+ modelBuilder.Entity("Volo.Abp.AuditLogging.EntityPropertyChange", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("EntityChangeId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("NewValue")
+ .HasMaxLength(512)
+ .HasColumnType("nvarchar(512)")
+ .HasColumnName("NewValue");
+
+ b.Property("OriginalValue")
+ .HasMaxLength(512)
+ .HasColumnType("nvarchar(512)")
+ .HasColumnName("OriginalValue");
+
+ b.Property("PropertyName")
+ .IsRequired()
+ .HasMaxLength(128)
+ .HasColumnType("nvarchar(128)")
+ .HasColumnName("PropertyName");
+
+ b.Property("PropertyTypeFullName")
+ .IsRequired()
+ .HasMaxLength(64)
+ .HasColumnType("nvarchar(64)")
+ .HasColumnName("PropertyTypeFullName");
+
+ b.Property("TenantId")
+ .HasColumnType("uniqueidentifier")
+ .HasColumnName("TenantId");
+
+ b.HasKey("Id");
+
+ b.HasIndex("EntityChangeId");
+
+ b.ToTable("AbpEntityPropertyChanges", (string)null);
+ });
+
+ modelBuilder.Entity("Volo.Abp.BackgroundJobs.BackgroundJobRecord", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("ConcurrencyStamp")
+ .IsConcurrencyToken()
+ .HasMaxLength(40)
+ .HasColumnType("nvarchar(40)")
+ .HasColumnName("ConcurrencyStamp");
+
+ b.Property("CreationTime")
+ .HasColumnType("datetime2")
+ .HasColumnName("CreationTime");
+
+ b.Property("ExtraProperties")
+ .HasColumnType("nvarchar(max)")
+ .HasColumnName("ExtraProperties");
+
+ b.Property("IsAbandoned")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bit")
+ .HasDefaultValue(false);
+
+ b.Property("JobArgs")
+ .IsRequired()
+ .HasMaxLength(1048576)
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("JobName")
+ .IsRequired()
+ .HasMaxLength(128)
+ .HasColumnType("nvarchar(128)");
+
+ b.Property("LastTryTime")
+ .HasColumnType("datetime2");
+
+ b.Property("NextTryTime")
+ .HasColumnType("datetime2");
+
+ b.Property("Priority")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("tinyint")
+ .HasDefaultValue((byte)15);
+
+ b.Property("TryCount")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("smallint")
+ .HasDefaultValue((short)0);
+
+ b.HasKey("Id");
+
+ b.HasIndex("IsAbandoned", "NextTryTime");
+
+ b.ToTable("AbpBackgroundJobs", (string)null);
+ });
+
+ modelBuilder.Entity("Volo.Abp.FeatureManagement.FeatureDefinitionRecord", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("AllowedProviders")
+ .HasMaxLength(256)
+ .HasColumnType("nvarchar(256)");
+
+ b.Property("DefaultValue")
+ .HasMaxLength(256)
+ .HasColumnType("nvarchar(256)");
+
+ b.Property("Description")
+ .HasMaxLength(256)
+ .HasColumnType("nvarchar(256)");
+
+ b.Property("DisplayName")
+ .IsRequired()
+ .HasMaxLength(256)
+ .HasColumnType("nvarchar(256)");
+
+ b.Property("ExtraProperties")
+ .HasColumnType("nvarchar(max)")
+ .HasColumnName("ExtraProperties");
+
+ b.Property("GroupName")
+ .IsRequired()
+ .HasMaxLength(128)
+ .HasColumnType("nvarchar(128)");
+
+ b.Property("IsAvailableToHost")
+ .HasColumnType("bit");
+
+ b.Property("IsVisibleToClients")
+ .HasColumnType("bit");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasMaxLength(128)
+ .HasColumnType("nvarchar(128)");
+
+ b.Property("ParentName")
+ .HasMaxLength(128)
+ .HasColumnType("nvarchar(128)");
+
+ b.Property("ValueType")
+ .HasMaxLength(2048)
+ .HasColumnType("nvarchar(2048)");
+
+ b.HasKey("Id");
+
+ b.HasIndex("GroupName");
+
+ b.HasIndex("Name")
+ .IsUnique();
+
+ b.ToTable("AbpFeatures", (string)null);
+ });
+
+ modelBuilder.Entity("Volo.Abp.FeatureManagement.FeatureGroupDefinitionRecord", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("DisplayName")
+ .IsRequired()
+ .HasMaxLength(256)
+ .HasColumnType("nvarchar(256)");
+
+ b.Property("ExtraProperties")
+ .HasColumnType("nvarchar(max)")
+ .HasColumnName("ExtraProperties");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasMaxLength(128)
+ .HasColumnType("nvarchar(128)");
+
+ b.HasKey("Id");
+
+ b.HasIndex("Name")
+ .IsUnique();
+
+ b.ToTable("AbpFeatureGroups", (string)null);
+ });
+
+ modelBuilder.Entity("Volo.Abp.FeatureManagement.FeatureValue", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasMaxLength(128)
+ .HasColumnType("nvarchar(128)");
+
+ b.Property("ProviderKey")
+ .HasMaxLength(64)
+ .HasColumnType("nvarchar(64)");
+
+ b.Property("ProviderName")
+ .HasMaxLength(64)
+ .HasColumnType("nvarchar(64)");
+
+ b.Property("Value")
+ .IsRequired()
+ .HasMaxLength(128)
+ .HasColumnType("nvarchar(128)");
+
+ b.HasKey("Id");
+
+ b.HasIndex("Name", "ProviderName", "ProviderKey")
+ .IsUnique()
+ .HasFilter("[ProviderName] IS NOT NULL AND [ProviderKey] IS NOT NULL");
+
+ b.ToTable("AbpFeatureValues", (string)null);
+ });
+
+ modelBuilder.Entity("Volo.Abp.Identity.IdentityClaimType", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("ConcurrencyStamp")
+ .IsConcurrencyToken()
+ .HasMaxLength(40)
+ .HasColumnType("nvarchar(40)")
+ .HasColumnName("ConcurrencyStamp");
+
+ b.Property("Description")
+ .HasMaxLength(256)
+ .HasColumnType("nvarchar(256)");
+
+ b.Property("ExtraProperties")
+ .HasColumnType("nvarchar(max)")
+ .HasColumnName("ExtraProperties");
+
+ b.Property("IsStatic")
+ .HasColumnType("bit");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasMaxLength(256)
+ .HasColumnType("nvarchar(256)");
+
+ b.Property("Regex")
+ .HasMaxLength(512)
+ .HasColumnType("nvarchar(512)");
+
+ b.Property("RegexDescription")
+ .HasMaxLength(128)
+ .HasColumnType("nvarchar(128)");
+
+ b.Property("Required")
+ .HasColumnType("bit");
+
+ b.Property("ValueType")
+ .HasColumnType("int");
+
+ b.HasKey("Id");
+
+ b.ToTable("AbpClaimTypes", (string)null);
+ });
+
+ modelBuilder.Entity("Volo.Abp.Identity.IdentityLinkUser", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("SourceTenantId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("SourceUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("TargetTenantId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("TargetUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.HasKey("Id");
+
+ b.HasIndex("SourceUserId", "SourceTenantId", "TargetUserId", "TargetTenantId")
+ .IsUnique()
+ .HasFilter("[SourceTenantId] IS NOT NULL AND [TargetTenantId] IS NOT NULL");
+
+ b.ToTable("AbpLinkUsers", (string)null);
+ });
+
+ modelBuilder.Entity("Volo.Abp.Identity.IdentityRole", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("ConcurrencyStamp")
+ .IsConcurrencyToken()
+ .HasMaxLength(40)
+ .HasColumnType("nvarchar(40)")
+ .HasColumnName("ConcurrencyStamp");
+
+ b.Property("EntityVersion")
+ .HasColumnType("int");
+
+ b.Property("ExtraProperties")
+ .HasColumnType("nvarchar(max)")
+ .HasColumnName("ExtraProperties");
+
+ b.Property("IsDefault")
+ .HasColumnType("bit")
+ .HasColumnName("IsDefault");
+
+ b.Property("IsPublic")
+ .HasColumnType("bit")
+ .HasColumnName("IsPublic");
+
+ b.Property("IsStatic")
+ .HasColumnType("bit")
+ .HasColumnName("IsStatic");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasMaxLength(256)
+ .HasColumnType("nvarchar(256)");
+
+ b.Property("NormalizedName")
+ .IsRequired()
+ .HasMaxLength(256)
+ .HasColumnType("nvarchar(256)");
+
+ b.Property("TenantId")
+ .HasColumnType("uniqueidentifier")
+ .HasColumnName("TenantId");
+
+ b.HasKey("Id");
+
+ b.HasIndex("NormalizedName");
+
+ b.ToTable("AbpRoles", (string)null);
+ });
+
+ modelBuilder.Entity("Volo.Abp.Identity.IdentityRoleClaim", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("ClaimType")
+ .IsRequired()
+ .HasMaxLength(256)
+ .HasColumnType("nvarchar(256)");
+
+ b.Property("ClaimValue")
+ .HasMaxLength(1024)
+ .HasColumnType("nvarchar(1024)");
+
+ b.Property("RoleId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("TenantId")
+ .HasColumnType("uniqueidentifier")
+ .HasColumnName("TenantId");
+
+ b.HasKey("Id");
+
+ b.HasIndex("RoleId");
+
+ b.ToTable("AbpRoleClaims", (string)null);
+ });
+
+ modelBuilder.Entity("Volo.Abp.Identity.IdentitySecurityLog", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("Action")
+ .HasMaxLength(96)
+ .HasColumnType("nvarchar(96)");
+
+ b.Property("ApplicationName")
+ .HasMaxLength(96)
+ .HasColumnType("nvarchar(96)");
+
+ b.Property("BrowserInfo")
+ .HasMaxLength(512)
+ .HasColumnType("nvarchar(512)");
+
+ b.Property("ClientId")
+ .HasMaxLength(64)
+ .HasColumnType("nvarchar(64)");
+
+ b.Property("ClientIpAddress")
+ .HasMaxLength(64)
+ .HasColumnType("nvarchar(64)");
+
+ b.Property("ConcurrencyStamp")
+ .IsConcurrencyToken()
+ .HasMaxLength(40)
+ .HasColumnType("nvarchar(40)")
+ .HasColumnName("ConcurrencyStamp");
+
+ b.Property("CorrelationId")
+ .HasMaxLength(64)
+ .HasColumnType("nvarchar(64)");
+
+ b.Property("CreationTime")
+ .HasColumnType("datetime2");
+
+ b.Property("ExtraProperties")
+ .HasColumnType("nvarchar(max)")
+ .HasColumnName("ExtraProperties");
+
+ b.Property("Identity")
+ .HasMaxLength(96)
+ .HasColumnType("nvarchar(96)");
+
+ b.Property("TenantId")
+ .HasColumnType("uniqueidentifier")
+ .HasColumnName("TenantId");
+
+ b.Property("TenantName")
+ .HasMaxLength(64)
+ .HasColumnType("nvarchar(64)");
+
+ b.Property("UserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("UserName")
+ .HasMaxLength(256)
+ .HasColumnType("nvarchar(256)");
+
+ b.HasKey("Id");
+
+ b.HasIndex("TenantId", "Action");
+
+ b.HasIndex("TenantId", "ApplicationName");
+
+ b.HasIndex("TenantId", "Identity");
+
+ b.HasIndex("TenantId", "UserId");
+
+ b.ToTable("AbpSecurityLogs", (string)null);
+ });
+
+ modelBuilder.Entity("Volo.Abp.Identity.IdentityUser", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("AccessFailedCount")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int")
+ .HasDefaultValue(0)
+ .HasColumnName("AccessFailedCount");
+
+ b.Property("ConcurrencyStamp")
+ .IsConcurrencyToken()
+ .HasMaxLength(40)
+ .HasColumnType("nvarchar(40)")
+ .HasColumnName("ConcurrencyStamp");
+
+ b.Property("CreationTime")
+ .HasColumnType("datetime2")
+ .HasColumnName("CreationTime");
+
+ b.Property("CreatorId")
+ .HasColumnType("uniqueidentifier")
+ .HasColumnName("CreatorId");
+
+ b.Property("DeleterId")
+ .HasColumnType("uniqueidentifier")
+ .HasColumnName("DeleterId");
+
+ b.Property("DeletionTime")
+ .HasColumnType("datetime2")
+ .HasColumnName("DeletionTime");
+
+ b.Property("Email")
+ .IsRequired()
+ .HasMaxLength(256)
+ .HasColumnType("nvarchar(256)")
+ .HasColumnName("Email");
+
+ b.Property("EmailConfirmed")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bit")
+ .HasDefaultValue(false)
+ .HasColumnName("EmailConfirmed");
+
+ b.Property("EntityVersion")
+ .HasColumnType("int");
+
+ b.Property("ExtraProperties")
+ .HasColumnType("nvarchar(max)")
+ .HasColumnName("ExtraProperties");
+
+ b.Property("IsActive")
+ .HasColumnType("bit")
+ .HasColumnName("IsActive");
+
+ b.Property("IsDeleted")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bit")
+ .HasDefaultValue(false)
+ .HasColumnName("IsDeleted");
+
+ b.Property("IsExternal")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bit")
+ .HasDefaultValue(false)
+ .HasColumnName("IsExternal");
+
+ b.Property("LastModificationTime")
+ .HasColumnType("datetime2")
+ .HasColumnName("LastModificationTime");
+
+ b.Property("LastModifierId")
+ .HasColumnType("uniqueidentifier")
+ .HasColumnName("LastModifierId");
+
+ b.Property("LastPasswordChangeTime")
+ .HasColumnType("datetimeoffset");
+
+ b.Property("LockoutEnabled")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bit")
+ .HasDefaultValue(false)
+ .HasColumnName("LockoutEnabled");
+
+ b.Property("LockoutEnd")
+ .HasColumnType("datetimeoffset");
+
+ b.Property("Name")
+ .HasMaxLength(64)
+ .HasColumnType("nvarchar(64)")
+ .HasColumnName("Name");
+
+ b.Property("NormalizedEmail")
+ .IsRequired()
+ .HasMaxLength(256)
+ .HasColumnType("nvarchar(256)")
+ .HasColumnName("NormalizedEmail");
+
+ b.Property("NormalizedUserName")
+ .IsRequired()
+ .HasMaxLength(256)
+ .HasColumnType("nvarchar(256)")
+ .HasColumnName("NormalizedUserName");
+
+ b.Property("PasswordHash")
+ .HasMaxLength(256)
+ .HasColumnType("nvarchar(256)")
+ .HasColumnName("PasswordHash");
+
+ b.Property("PhoneNumber")
+ .HasMaxLength(16)
+ .HasColumnType("nvarchar(16)")
+ .HasColumnName("PhoneNumber");
+
+ b.Property("PhoneNumberConfirmed")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bit")
+ .HasDefaultValue(false)
+ .HasColumnName("PhoneNumberConfirmed");
+
+ b.Property("SecurityStamp")
+ .IsRequired()
+ .HasMaxLength(256)
+ .HasColumnType("nvarchar(256)")
+ .HasColumnName("SecurityStamp");
+
+ b.Property("ShouldChangePasswordOnNextLogin")
+ .HasColumnType("bit");
+
+ b.Property("Surname")
+ .HasMaxLength(64)
+ .HasColumnType("nvarchar(64)")
+ .HasColumnName("Surname");
+
+ b.Property("TenantId")
+ .HasColumnType("uniqueidentifier")
+ .HasColumnName("TenantId");
+
+ b.Property("TwoFactorEnabled")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bit")
+ .HasDefaultValue(false)
+ .HasColumnName("TwoFactorEnabled");
+
+ b.Property("UserName")
+ .IsRequired()
+ .HasMaxLength(256)
+ .HasColumnType("nvarchar(256)")
+ .HasColumnName("UserName");
+
+ b.HasKey("Id");
+
+ b.HasIndex("Email");
+
+ b.HasIndex("NormalizedEmail");
+
+ b.HasIndex("NormalizedUserName");
+
+ b.HasIndex("UserName");
+
+ b.ToTable("AbpUsers", (string)null);
+ });
+
+ modelBuilder.Entity("Volo.Abp.Identity.IdentityUserClaim", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("ClaimType")
+ .IsRequired()
+ .HasMaxLength(256)
+ .HasColumnType("nvarchar(256)");
+
+ b.Property("ClaimValue")
+ .HasMaxLength(1024)
+ .HasColumnType("nvarchar(1024)");
+
+ b.Property("TenantId")
+ .HasColumnType("uniqueidentifier")
+ .HasColumnName("TenantId");
+
+ b.Property("UserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.HasKey("Id");
+
+ b.HasIndex("UserId");
+
+ b.ToTable("AbpUserClaims", (string)null);
+ });
+
+ modelBuilder.Entity("Volo.Abp.Identity.IdentityUserDelegation", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("EndTime")
+ .HasColumnType("datetime2");
+
+ b.Property("SourceUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("StartTime")
+ .HasColumnType("datetime2");
+
+ b.Property("TargetUserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("TenantId")
+ .HasColumnType("uniqueidentifier")
+ .HasColumnName("TenantId");
+
+ b.HasKey("Id");
+
+ b.ToTable("AbpUserDelegations", (string)null);
+ });
+
+ modelBuilder.Entity("Volo.Abp.Identity.IdentityUserLogin", b =>
+ {
+ b.Property("UserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("LoginProvider")
+ .HasMaxLength(64)
+ .HasColumnType("nvarchar(64)");
+
+ b.Property("ProviderDisplayName")
+ .HasMaxLength(128)
+ .HasColumnType("nvarchar(128)");
+
+ b.Property("ProviderKey")
+ .IsRequired()
+ .HasMaxLength(196)
+ .HasColumnType("nvarchar(196)");
+
+ b.Property("TenantId")
+ .HasColumnType("uniqueidentifier")
+ .HasColumnName("TenantId");
+
+ b.HasKey("UserId", "LoginProvider");
+
+ b.HasIndex("LoginProvider", "ProviderKey");
+
+ b.ToTable("AbpUserLogins", (string)null);
+ });
+
+ modelBuilder.Entity("Volo.Abp.Identity.IdentityUserOrganizationUnit", b =>
+ {
+ b.Property("OrganizationUnitId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("UserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("CreationTime")
+ .HasColumnType("datetime2")
+ .HasColumnName("CreationTime");
+
+ b.Property("CreatorId")
+ .HasColumnType("uniqueidentifier")
+ .HasColumnName("CreatorId");
+
+ b.Property("TenantId")
+ .HasColumnType("uniqueidentifier")
+ .HasColumnName("TenantId");
+
+ b.HasKey("OrganizationUnitId", "UserId");
+
+ b.HasIndex("UserId", "OrganizationUnitId");
+
+ b.ToTable("AbpUserOrganizationUnits", (string)null);
+ });
+
+ modelBuilder.Entity("Volo.Abp.Identity.IdentityUserRole", b =>
+ {
+ b.Property("UserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("RoleId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("TenantId")
+ .HasColumnType("uniqueidentifier")
+ .HasColumnName("TenantId");
+
+ b.HasKey("UserId", "RoleId");
+
+ b.HasIndex("RoleId", "UserId");
+
+ b.ToTable("AbpUserRoles", (string)null);
+ });
+
+ modelBuilder.Entity("Volo.Abp.Identity.IdentityUserToken", b =>
+ {
+ b.Property("UserId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("LoginProvider")
+ .HasMaxLength(64)
+ .HasColumnType("nvarchar(64)");
+
+ b.Property("Name")
+ .HasMaxLength(128)
+ .HasColumnType("nvarchar(128)");
+
+ b.Property("TenantId")
+ .HasColumnType("uniqueidentifier")
+ .HasColumnName("TenantId");
+
+ b.Property("Value")
+ .HasColumnType("nvarchar(max)");
+
+ b.HasKey("UserId", "LoginProvider", "Name");
+
+ b.ToTable("AbpUserTokens", (string)null);
+ });
+
+ modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnit", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("Code")
+ .IsRequired()
+ .HasMaxLength(95)
+ .HasColumnType("nvarchar(95)")
+ .HasColumnName("Code");
+
+ b.Property("ConcurrencyStamp")
+ .IsConcurrencyToken()
+ .HasMaxLength(40)
+ .HasColumnType("nvarchar(40)")
+ .HasColumnName("ConcurrencyStamp");
+
+ b.Property("CreationTime")
+ .HasColumnType("datetime2")
+ .HasColumnName("CreationTime");
+
+ b.Property("CreatorId")
+ .HasColumnType("uniqueidentifier")
+ .HasColumnName("CreatorId");
+
+ b.Property("DeleterId")
+ .HasColumnType("uniqueidentifier")
+ .HasColumnName("DeleterId");
+
+ b.Property("DeletionTime")
+ .HasColumnType("datetime2")
+ .HasColumnName("DeletionTime");
+
+ b.Property("DisplayName")
+ .IsRequired()
+ .HasMaxLength(128)
+ .HasColumnType("nvarchar(128)")
+ .HasColumnName("DisplayName");
+
+ b.Property("EntityVersion")
+ .HasColumnType("int");
+
+ b.Property("ExtraProperties")
+ .HasColumnType("nvarchar(max)")
+ .HasColumnName("ExtraProperties");
+
+ b.Property("IsDeleted")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bit")
+ .HasDefaultValue(false)
+ .HasColumnName("IsDeleted");
+
+ b.Property("LastModificationTime")
+ .HasColumnType("datetime2")
+ .HasColumnName("LastModificationTime");
+
+ b.Property("LastModifierId")
+ .HasColumnType("uniqueidentifier")
+ .HasColumnName("LastModifierId");
+
+ b.Property("ParentId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("TenantId")
+ .HasColumnType("uniqueidentifier")
+ .HasColumnName("TenantId");
+
+ b.HasKey("Id");
+
+ b.HasIndex("Code");
+
+ b.HasIndex("ParentId");
+
+ b.ToTable("AbpOrganizationUnits", (string)null);
+ });
+
+ modelBuilder.Entity("Volo.Abp.Identity.OrganizationUnitRole", b =>
+ {
+ b.Property("OrganizationUnitId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("RoleId")
+ .HasColumnType("uniqueidentifier");
+
+ b.Property("CreationTime")
+ .HasColumnType("datetime2")
+ .HasColumnName("CreationTime");
+
+ b.Property