├── .gitattributes
├── .github
└── workflows
│ └── dotnet-core.yml
├── .gitignore
├── LICENSE
├── README.md
└── src
├── .dockerignore
├── .template.config
└── template.json
├── Libraries
├── Caching
│ ├── Caching.csproj
│ ├── ICacheManager.cs
│ ├── ILocker.cs
│ ├── IRedisConnectionWrapper.cs
│ ├── RedisCacheManager.cs
│ ├── RedisConnectionWrapper.cs
│ ├── RedisDatabaseNumber.cs
│ └── ServiceExtensions.cs
├── Core
│ ├── Core.csproj
│ ├── Exceptions
│ │ └── ApiException.cs
│ ├── Helpers
│ │ └── IpHelper.cs
│ ├── Interfaces
│ │ └── IEmailService.cs
│ ├── ServiceExtensions.cs
│ └── Services
│ │ └── EmailService.cs
├── Data.Mongo
│ ├── Attributes
│ │ └── BsonCollectionAttribute.cs
│ ├── Collections
│ │ ├── LoginLog.cs
│ │ └── MongoBaseDocument.cs
│ ├── Data.Mongo.csproj
│ ├── MongoDbOptions.cs
│ ├── Repo
│ │ ├── IMongoRepository.cs
│ │ └── MongoRepository.cs
│ └── ServiceExtensions.cs
├── Data
│ ├── Contexts
│ │ ├── ApplicationDbContext.cs
│ │ └── IDbContext.cs
│ ├── Data.csproj
│ ├── Mapping
│ │ ├── IMappingConfiguration.cs
│ │ ├── MappingEntityTypeConfiguration.cs
│ │ └── NoteMap.cs
│ ├── Migrations
│ │ ├── 20201008073308_first_appDb_migration.Designer.cs
│ │ ├── 20201008073308_first_appDb_migration.cs
│ │ ├── 20201008074018_new_appDb_migration.Designer.cs
│ │ ├── 20201008074018_new_appDb_migration.cs
│ │ └── ApplicationDbContextModelSnapshot.cs
│ ├── Repos
│ │ ├── GenericRepository.cs
│ │ └── IGenericRepository.cs
│ └── UnitOfWork
│ │ ├── IUnitOfWork.cs
│ │ └── UnitOfWork.cs
├── Identity
│ ├── Contexts
│ │ └── IdentityContext.cs
│ ├── Identity.csproj
│ ├── Migrations
│ │ ├── 20201005130141_my_new_identity_migration.Designer.cs
│ │ ├── 20201005130141_my_new_identity_migration.cs
│ │ ├── 20201027103615_update_identity_migration.Designer.cs
│ │ ├── 20201027103615_update_identity_migration.cs
│ │ └── IdentityContextModelSnapshot.cs
│ ├── Models
│ │ ├── ApplicationRole.cs
│ │ ├── ApplicationRoleClaim.cs
│ │ ├── ApplicationUser.cs
│ │ ├── ApplicationUserClaim.cs
│ │ ├── ApplicationUserLogin.cs
│ │ ├── ApplicationUserRole.cs
│ │ └── ApplicationUserToken.cs
│ ├── Seeds
│ │ ├── DefaultRoles.cs
│ │ └── DefaultSuperAdmin.cs
│ ├── ServiceExtensions.cs
│ └── Services
│ │ ├── Concrete
│ │ └── AccountService.cs
│ │ └── Interfaces
│ │ └── IAccountService.cs
├── Models
│ ├── DTOs
│ │ ├── Account
│ │ │ ├── AuthenticationRequest.cs
│ │ │ ├── ForgotPasswordRequest.cs
│ │ │ ├── RefreshToken.cs
│ │ │ ├── RefreshTokenRequest.cs
│ │ │ ├── RegisterRequest.cs
│ │ │ ├── ResetPasswordRequest.cs
│ │ │ └── UserDto.cs
│ │ ├── Email
│ │ │ └── EmailRequest.cs
│ │ └── Log
│ │ │ └── LogDto.cs
│ ├── DbEntities
│ │ ├── BaseEntity.cs
│ │ └── Note.cs
│ ├── Enums
│ │ └── Roles.cs
│ ├── Models.csproj
│ ├── ResponseModels
│ │ ├── AuthenticationResponse.cs
│ │ └── BaseResponse.cs
│ └── Settings
│ │ ├── JWTSettings.cs
│ │ ├── MailSettings.cs
│ │ └── RedisSettings.cs
└── Services
│ ├── Concrete
│ ├── LoginLogService.cs
│ └── NoteService.cs
│ ├── Interfaces
│ ├── IAuthenticatedUserService.cs
│ ├── ILoginLogService.cs
│ └── INoteService.cs
│ └── Services.csproj
├── Presentations
└── WebApi
│ ├── Attributes
│ └── CachedAttribute.cs
│ ├── Controllers
│ ├── AccountController.cs
│ ├── AdminController.cs
│ ├── GraphQLController.cs
│ ├── LogController.cs
│ └── NoteController.cs
│ ├── Dockerfile
│ ├── Extensions
│ └── AppExtensions.cs
│ ├── GraphQL
│ ├── GraphQLQuery.cs
│ ├── Mutations
│ │ └── MyNoteMutation.cs
│ ├── MyNoteSchema.cs
│ ├── Queries
│ │ └── MyNoteQuery.cs
│ ├── ServiceExtensions.cs
│ └── Types
│ │ └── Note
│ │ ├── NoteInputType.cs
│ │ └── NoteType.cs
│ ├── Helpers
│ ├── IApiAssemblyMarker.cs
│ └── MappingProfiles.cs
│ ├── Middlewares
│ └── ErrorHandlerMiddleware.cs
│ ├── Program.cs
│ ├── Properties
│ └── launchSettings.json
│ ├── Services
│ └── AuthenticatedUserService.cs
│ ├── Startup.cs
│ ├── WebApi.csproj
│ ├── appsettings.Development.json
│ └── appsettings.json
├── Template.WebApi.sln
├── Tests
└── UnitTests
│ ├── NoteTest.cs
│ ├── UnitTests.csproj
│ └── core
│ ├── ApiFactory.cs
│ └── Enums
│ └── TypeControllerTesting.cs
└── docker-compose.yml
/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Set default behavior to automatically normalize line endings.
3 | ###############################################################################
4 | * text=auto
5 |
6 | ###############################################################################
7 | # Set default behavior for command prompt diff.
8 | #
9 | # This is need for earlier builds of msysgit that does not have it on by
10 | # default for csharp files.
11 | # Note: This is only used by command line
12 | ###############################################################################
13 | #*.cs diff=csharp
14 |
15 | ###############################################################################
16 | # Set the merge driver for project and solution files
17 | #
18 | # Merging from the command prompt will add diff markers to the files if there
19 | # are conflicts (Merging from VS is not affected by the settings below, in VS
20 | # the diff markers are never inserted). Diff markers may cause the following
21 | # file extensions to fail to load in VS. An alternative would be to treat
22 | # these files as binary and thus will always conflict and require user
23 | # intervention with every merge. To do so, just uncomment the entries below
24 | ###############################################################################
25 | #*.sln merge=binary
26 | #*.csproj merge=binary
27 | #*.vbproj merge=binary
28 | #*.vcxproj merge=binary
29 | #*.vcproj merge=binary
30 | #*.dbproj merge=binary
31 | #*.fsproj merge=binary
32 | #*.lsproj merge=binary
33 | #*.wixproj merge=binary
34 | #*.modelproj merge=binary
35 | #*.sqlproj merge=binary
36 | #*.wwaproj merge=binary
37 |
38 | ###############################################################################
39 | # behavior for image files
40 | #
41 | # image files are treated as binary by default.
42 | ###############################################################################
43 | #*.jpg binary
44 | #*.png binary
45 | #*.gif binary
46 |
47 | ###############################################################################
48 | # diff behavior for common document formats
49 | #
50 | # Convert binary document formats to text before diffing them. This feature
51 | # is only available from the command line. Turn it on by uncommenting the
52 | # entries below.
53 | ###############################################################################
54 | #*.doc diff=astextplain
55 | #*.DOC diff=astextplain
56 | #*.docx diff=astextplain
57 | #*.DOCX diff=astextplain
58 | #*.dot diff=astextplain
59 | #*.DOT diff=astextplain
60 | #*.pdf diff=astextplain
61 | #*.PDF diff=astextplain
62 | #*.rtf diff=astextplain
63 | #*.RTF diff=astextplain
--------------------------------------------------------------------------------
/.github/workflows/dotnet-core.yml:
--------------------------------------------------------------------------------
1 | name: build
2 |
3 | on:
4 | push:
5 | branches: [ master ]
6 | pull_request:
7 | branches: [ master ]
8 | workflow_dispatch:
9 |
10 | concurrency:
11 | group: ${{ github.workflow }}-${{ github.ref }}
12 | cancel-in-progress: true
13 |
14 | jobs:
15 | build:
16 | name: Build
17 | runs-on: ubuntu-latest
18 |
19 | steps:
20 | - name: Checkout code
21 | uses: actions/checkout@v3
22 |
23 | - name: Setup .NET
24 | uses: actions/setup-dotnet@v3
25 | with:
26 | dotnet-version: '8.0.x'
27 |
28 | - name: Restore dependencies
29 | run: dotnet restore ./src/Presentations/WebApi/WebApi.csproj --verbosity minimal
30 |
31 | - name: Build solution
32 | run: dotnet build ./src/Presentations/WebApi/WebApi.csproj -c Release --verbosity minimal
33 |
34 | - name: Publish
35 | run: dotnet publish ./src/Presentations/WebApi/WebApi.csproj -c Release --no-build --no-restore
36 |
37 | - name: Upload Core artifacts
38 | uses: actions/upload-artifact@v3
39 | with:
40 | name: Core
41 | path: ./Publish/Core
42 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Created by https://www.gitignore.io/api/visualstudio
2 |
3 | ### VisualStudio ###
4 | ## Ignore Visual Studio temporary files, build results, and
5 | ## files generated by popular Visual Studio add-ons.
6 |
7 | # User-specific files
8 | *.suo
9 | *.user
10 | *.userosscache
11 | *.sln.docstates
12 |
13 | # User-specific files (MonoDevelop/Xamarin Studio)
14 | *.userprefs
15 |
16 | # Build results
17 | [Dd]ebug/
18 | [Dd]ebugPublic/
19 | [Rr]elease/
20 | [Rr]eleases/
21 | x64/
22 | x86/
23 | bld/
24 | [Bb]in/
25 | [Oo]bj/
26 | [Ll]og/
27 |
28 | # Visual Studio 2015 cache/options directory
29 | .vs/
30 | # Uncomment if you have tasks that create the project's static files in wwwroot
31 | #wwwroot/
32 |
33 | # MSTest test Results
34 | [Tt]est[Rr]esult*/
35 | [Bb]uild[Ll]og.*
36 |
37 | # NUNIT
38 | *.VisualState.xml
39 | TestResult.xml
40 |
41 | # Build Results of an ATL Project
42 | [Dd]ebugPS/
43 | [Rr]eleasePS/
44 | dlldata.c
45 |
46 | # DNX
47 | project.lock.json
48 | artifacts/
49 |
50 | *_i.c
51 | *_p.c
52 | *_i.h
53 | *.ilk
54 | *.meta
55 | *.obj
56 | *.pch
57 | *.pdb
58 | *.pgc
59 | *.pgd
60 | *.rsp
61 | *.sbr
62 | *.tlb
63 | *.tli
64 | *.tlh
65 | *.tmp
66 | *.tmp_proj
67 | *.log
68 | *.vspscc
69 | *.vssscc
70 | .builds
71 | *.pidb
72 | *.svclog
73 | *.scc
74 |
75 | # Chutzpah Test files
76 | _Chutzpah*
77 |
78 | # Visual C++ cache files
79 | ipch/
80 | *.aps
81 | *.ncb
82 | *.opendb
83 | *.opensdf
84 | *.sdf
85 | *.cachefile
86 |
87 | # Visual Studio profiler
88 | *.psess
89 | *.vsp
90 | *.vspx
91 | *.sap
92 |
93 | # TFS 2012 Local Workspace
94 | $tf/
95 |
96 | # Guidance Automation Toolkit
97 | *.gpState
98 |
99 | # ReSharper is a .NET coding add-in
100 | _ReSharper*/
101 | *.[Rr]e[Ss]harper
102 | *.DotSettings.user
103 |
104 | # JustCode is a .NET coding add-in
105 | .JustCode
106 |
107 | # TeamCity is a build add-in
108 | _TeamCity*
109 |
110 | # DotCover is a Code Coverage Tool
111 | *.dotCover
112 |
113 | # NCrunch
114 | _NCrunch_*
115 | .*crunch*.local.xml
116 | nCrunchTemp_*
117 |
118 | # MightyMoose
119 | *.mm.*
120 | AutoTest.Net/
121 |
122 | # Web workbench (sass)
123 | .sass-cache/
124 |
125 | # Installshield output folder
126 | [Ee]xpress/
127 |
128 | # DocProject is a documentation generator add-in
129 | DocProject/buildhelp/
130 | DocProject/Help/*.HxT
131 | DocProject/Help/*.HxC
132 | DocProject/Help/*.hhc
133 | DocProject/Help/*.hhk
134 | DocProject/Help/*.hhp
135 | DocProject/Help/Html2
136 | DocProject/Help/html
137 |
138 | # Click-Once directory
139 | publish/
140 |
141 | # Publish Web Output
142 | *.[Pp]ublish.xml
143 | *.azurePubxml
144 | # TODO: Comment the next line if you want to checkin your web deploy settings
145 | # but database connection strings (with potential passwords) will be unencrypted
146 | *.pubxml
147 | *.publishproj
148 |
149 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
150 | # checkin your Azure Web App publish settings, but sensitive information contained
151 | # in these scripts will be unencrypted
152 | PublishScripts/
153 |
154 | # NuGet Packages
155 | *.nupkg
156 | # The packages folder can be ignored because of Package Restore
157 | **/packages/*
158 | # except build/, which is used as an MSBuild target.
159 | !**/packages/build/
160 | # Uncomment if necessary however generally it will be regenerated when needed
161 | #!**/packages/repositories.config
162 | # NuGet v3's project.json files produces more ignoreable files
163 | *.nuget.props
164 | *.nuget.targets
165 |
166 | # Microsoft Azure Build Output
167 | csx/
168 | *.build.csdef
169 |
170 | # Microsoft Azure Emulator
171 | ecf/
172 | rcf/
173 |
174 | # Windows Store app package directories and files
175 | AppPackages/
176 | BundleArtifacts/
177 | Package.StoreAssociation.xml
178 | _pkginfo.txt
179 |
180 | # Visual Studio cache files
181 | # files ending in .cache can be ignored
182 | *.[Cc]ache
183 | # but keep track of directories ending in .cache
184 | !*.[Cc]ache/
185 |
186 | # Others
187 | ClientBin/
188 | ~$*
189 | *~
190 | *.dbmdl
191 | *.dbproj.schemaview
192 | *.pfx
193 | *.publishsettings
194 | node_modules/
195 | orleans.codegen.cs
196 |
197 | # Since there are multiple workflows, uncomment next line to ignore bower_components
198 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
199 | #bower_components/
200 |
201 | # RIA/Silverlight projects
202 | Generated_Code/
203 |
204 | # Backup & report files from converting an old project file
205 | # to a newer Visual Studio version. Backup files are not needed,
206 | # because we have git
207 | _UpgradeReport_Files/
208 | Backup*/
209 | UpgradeLog*.XML
210 | UpgradeLog*.htm
211 |
212 | # SQL Server files
213 | *.mdf
214 | *.ldf
215 |
216 | # Business Intelligence projects
217 | *.rdl.data
218 | *.bim.layout
219 | *.bim_*.settings
220 |
221 | # Microsoft Fakes
222 | FakesAssemblies/
223 |
224 | # GhostDoc plugin setting file
225 | *.GhostDoc.xml
226 |
227 | # Node.js Tools for Visual Studio
228 | .ntvs_analysis.dat
229 |
230 | # Visual Studio 6 build log
231 | *.plg
232 |
233 | # Visual Studio 6 workspace options file
234 | *.opt
235 |
236 | # Visual Studio LightSwitch build output
237 | **/*.HTMLClient/GeneratedArtifacts
238 | **/*.DesktopClient/GeneratedArtifacts
239 | **/*.DesktopClient/ModelManifest.xml
240 | **/*.Server/GeneratedArtifacts
241 | **/*.Server/ModelManifest.xml
242 | _Pvt_Extensions
243 |
244 | # Paket dependency manager
245 | .paket/paket.exe
246 | paket-files/
247 |
248 | # FAKE - F# Make
249 | .fake/
250 |
251 | # JetBrains Rider
252 | .idea/
253 | *.sln.iml
254 |
255 | db-data/
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 Sinan Tok
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | # ASP.NET Core Web Api Template
4 |
5 | This project is an Web API Open-Source Boilerplate Template that includes Net 8, Web API standards, clean n-tier architecture, GraphQL service, Redis, Mssql, Mongo databases and User Auditing (Identity) with a lot of best practices.
6 |
7 | ## Releases
8 | v1.0, v2.0, v3.0, v4.0
9 |
10 | ## v4.0
11 |
12 | Follow these steps to get started with this Boilerplate Template.
13 |
14 | ### Download the Extension
15 | Make sure Visual Studio 2019 is installed on your machine with the latest SDK.
16 | [Download from Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=SinanTok.ASPNETCoreWebAPI). Install it on your machine.
17 |
18 | Follow these Steps to get started.
19 |
20 | 
21 |
22 | You Solution Template is Ready!
23 |
24 | 
25 |
26 | ### Alternatively you can also clone the [Repository](https://github.com/sinantok/aspnetcore-webapi-template).
27 |
28 | 1. Clone this Repository and Extract it to a Folder.
29 | 3. Change the Connection Strings for the "DefaultConnection" and "IdentityConnection" in the appsettings.json
30 | 2. Run the following commands on Powershell in the Projecct's Directory.
31 | - dotnet restore
32 | - dotnet ef database update -Context IdentityContext
33 | - dotnet ef database update -Context ApplicationDbContext
34 | - dotnet run (OR) Run the Solution using Visual Studio
35 |
36 | ### Swagger
37 | You can view endpoints with swagger
38 | 
39 |
40 | ### HealthCheck
41 | You can check the status of the services with HealthCheck
42 |
43 | ### Default Roles & Credentials
44 | As soon you build and run your application, default users and roles get added to the database.
45 |
46 | Default Roles:
47 | - SuperAdmin
48 | - Admin
49 | - Moderator
50 | - Basic
51 |
52 | Here are the credentials for the default user.
53 | - Email - superadmin@gmail.com / Password - 123Pa$$word!
54 |
55 | You can use these default credentials to generate valid JWTokens at the ../api/account/authenticate endpoint.
56 |
57 | ## Technologies
58 | - .Net 8 WebApi
59 | - .NET 8
60 | - REST Standards
61 | - GraphQL
62 | - MSSQL
63 | - MongoDB
64 | - Microsoft Identity
65 | - Redis
66 | - SeriLog(seq)
67 | - AutoMapper
68 | - Smtp / Mailkit
69 | - Swagger Open Api
70 | - Health Checks
71 |
72 | ## Features
73 | - [x] Net 8
74 | - [x] N-Tier Architecture
75 | - [x] Restful
76 | - [x] GraphQl
77 | - [x] Entity Framework Core - Code First
78 | - [x] Repository Pattern - Generic
79 | - [x] UnitOfWork
80 | - [x] Redis Caching
81 | - [x] Response Wrappers
82 | - [x] Microsoft Identity with JWT Authentication
83 | - [x] Role based Authorization
84 | - [x] Identity Seeding
85 | - [x] Database Seeding
86 | - [x] Custom Exception Handling Middlewares
87 | - [x] Serilog
88 | - [x] Automapper
89 | - [x] Swagger UI
90 | - [x] Healthchecks
91 | - [x] SMTP / Mailkit / Sendgrid Email Service
92 | - [x] Complete User Management Module (Register / Generate Token / Forgot Password / Confirmation Mail)
93 | - [x] User Auditing
94 | - [ ] Pagination
95 | - [ ] Refit
96 | - [ ] Fluent Validation
97 | - [ ] Unit Test
98 | - [x] .Net 8 migration
99 | - [x] MongoDb Operations
100 | - [x] Docker Support `docker-compose.yml` and `Dockerfile`
101 |
102 | ## Purpose of this Project
103 |
104 | This template project has been developed to ensure that the necessary structures are not installed over and over again when creating each new WebAPI project. In addition, the structures that should be in a WepAPI are developed with a clean architecture and up-to-date technologies.
105 |
106 | ## Prerequisites
107 | - Visual Studio 2019 Community and above
108 | - .NET 8 SDK and above
109 | - Basic Understanding of Architectures and Clean Code Principles
110 |
111 | ## Give a Star ⭐️
112 | If you found this Implementation helpful or used it in your Projects, do give it a star. Thanks!
113 |
114 | ## Licensing
115 |
116 | sinantok/aspnetcore-webapi-template Project is licensed with the [MIT License](https://github.com/sinantok/aspnetcore-webapi-template/blob/master/LICENSE).
117 |
118 | ## About the Author
119 | ### Sinan Tok
120 | - Github [github.com/sinantok](https://github.com/sinantok)
121 | - Linkedin - [Sinan Tok](https://www.linkedin.com/in/sinantok/)
122 |
--------------------------------------------------------------------------------
/src/.dockerignore:
--------------------------------------------------------------------------------
1 | **/.classpath
2 | **/.dockerignore
3 | **/.env
4 | **/.git
5 | **/.gitignore
6 | **/.project
7 | **/.settings
8 | **/.toolstarget
9 | **/.vs
10 | **/.vscode
11 | **/*.*proj.user
12 | **/*.dbmdl
13 | **/*.jfm
14 | **/azds.yaml
15 | **/bin
16 | **/charts
17 | **/docker-compose*
18 | **/Dockerfile*
19 | **/node_modules
20 | **/npm-debug.log
21 | **/obj
22 | **/secrets.dev.yaml
23 | **/values.dev.yaml
24 | LICENSE
25 | README.md
26 | !**/.gitignore
27 | !.git/HEAD
28 | !.git/config
29 | !.git/packed-refs
30 | !.git/refs/heads/**
--------------------------------------------------------------------------------
/src/.template.config/template.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json.schemastore.org/template",
3 | "author": "Delta",
4 | "classifications": ["Web", "Api"],
5 | "name": "Web API",
6 | "sourceName": "WebApi",
7 | "shortName": "webapi",
8 | "identity": "WebApi",
9 | "tags": {
10 | "language": "C#",
11 | "type": "project"
12 | },
13 | "description": "Creates a Web API project with NET8",
14 | "preferNameDirectory": true
15 | }
16 |
--------------------------------------------------------------------------------
/src/Libraries/Caching/Caching.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | net8.0
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/src/Libraries/Caching/ICacheManager.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Threading.Tasks;
3 |
4 | namespace Caching
5 | {
6 | public interface ICacheManager : IDisposable
7 | {
8 | Task GetAsync(string cacheKey);
9 | Task GetAsync(string key, Func> acquire, int? cacheTime = null);
10 | T Get(string key, Func acquire, int? cacheTime = null);
11 | Task SetAsync(string key, object data, int cacheTime);
12 | void Set(string key, object data, int cacheTime);
13 | bool IsSet(string key);
14 | void Remove(string key);
15 | void RemoveByPrefix(string prefix);
16 | void Clear();
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/Libraries/Caching/ILocker.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace Caching
4 | {
5 | public interface ILocker
6 | {
7 | bool PerformActionWithLock(string resource, TimeSpan expirationTime, Action action);
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/src/Libraries/Caching/IRedisConnectionWrapper.cs:
--------------------------------------------------------------------------------
1 | using StackExchange.Redis;
2 | using System;
3 | using System.Net;
4 |
5 | namespace Caching
6 | {
7 | public interface IRedisConnectionWrapper : IDisposable
8 | {
9 | IDatabase GetDatabase(int db);
10 |
11 | IServer GetServer(EndPoint endPoint);
12 |
13 | EndPoint[] GetEndPoints();
14 |
15 | void FlushDatabase(RedisDatabaseNumber db);
16 |
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/Libraries/Caching/RedisCacheManager.cs:
--------------------------------------------------------------------------------
1 | using Models.Settings;
2 | using Newtonsoft.Json;
3 | using StackExchange.Redis;
4 | using System;
5 | using System.Collections.Generic;
6 | using System.Linq;
7 | using System.Net;
8 | using System.Threading.Tasks;
9 |
10 | namespace Caching
11 | {
12 | public partial class RedisCacheManager : ICacheManager
13 | {
14 | #region Fields
15 |
16 | private readonly IRedisConnectionWrapper _connectionWrapper;
17 | private readonly IDatabase _db;
18 | private readonly RedisSettings _config;
19 |
20 | #endregion
21 |
22 | #region Ctor
23 |
24 | public RedisCacheManager(IRedisConnectionWrapper connectionWrapper, RedisSettings config)
25 | {
26 |
27 | _config = config;
28 | if (string.IsNullOrEmpty(_config.RedisConnectionString))
29 | throw new Exception("Redis connection string is empty");
30 |
31 | _connectionWrapper = connectionWrapper;
32 |
33 | _db = _connectionWrapper.GetDatabase(_config.RedisDatabaseId ?? (int)RedisDatabaseNumber.Cache);
34 |
35 | }
36 |
37 | #endregion
38 |
39 | #region Utilities
40 |
41 | protected virtual IEnumerable GetKeys(EndPoint endPoint, string prefix = null)
42 | {
43 | var server = _connectionWrapper.GetServer(endPoint);
44 |
45 | var keys = server.Keys(_db.Database, string.IsNullOrEmpty(prefix) ? null : $"{prefix}*");
46 |
47 | keys = keys.Where(key => !key.ToString().Equals(_config.RedisDataProtectionKey, StringComparison.OrdinalIgnoreCase));
48 |
49 | return keys;
50 | }
51 |
52 | protected virtual async Task GetAsync(string key)
53 | {
54 | //get serialized item from cache
55 | var serializedItem = await _db.StringGetAsync(key);
56 | if (!serializedItem.HasValue)
57 | return default(T);
58 |
59 | //deserialize item
60 | var item = JsonConvert.DeserializeObject(serializedItem);
61 | if (item == null)
62 | return default(T);
63 |
64 | return item;
65 | }
66 |
67 | protected virtual async Task IsSetAsync(string key)
68 | {
69 | return await _db.KeyExistsAsync(key);
70 | }
71 |
72 | #endregion
73 |
74 | #region Methods
75 |
76 | public async Task GetAsync(string cacheKey)
77 | {
78 | var cachedResponse = await _db.StringGetAsync(cacheKey);
79 |
80 | if (cachedResponse.IsNullOrEmpty)
81 | {
82 | return null;
83 | }
84 |
85 | return cachedResponse;
86 | }
87 |
88 | public async Task GetAsync(string key, Func> acquire, int? cacheTime = null)
89 | {
90 | //item already is in cache, so return it
91 | if (await IsSetAsync(key))
92 | return await GetAsync(key);
93 |
94 | //or create it using passed function
95 | var result = await acquire();
96 |
97 | //and set in cache (if cache time is defined)
98 | if ((cacheTime ?? _config.CacheTime) > 0)
99 | await SetAsync(key, result, cacheTime ?? _config.CacheTime);
100 |
101 | return result;
102 | }
103 |
104 | public virtual T Get(string key)
105 | {
106 |
107 | //get serialized item from cache
108 | var serializedItem = _db.StringGet(key);
109 | if (!serializedItem.HasValue)
110 | return default(T);
111 |
112 | //deserialize item
113 | var item = JsonConvert.DeserializeObject(serializedItem);
114 | if (item == null)
115 | return default(T);
116 |
117 |
118 | return item;
119 | }
120 |
121 | public virtual T Get(string key, Func acquire, int? cacheTime = null)
122 | {
123 | //item already is in cache, so return it
124 | if (IsSet(key))
125 | return Get(key);
126 |
127 | //or create it using passed function
128 | var result = acquire();
129 |
130 | //and set in cache (if cache time is defined)
131 | if ((cacheTime ?? _config.CacheTime) > 0)
132 | Set(key, result, cacheTime ?? _config.CacheTime);
133 |
134 | return result;
135 | }
136 |
137 | public async Task SetAsync(string key, object data, int cacheTime)
138 | {
139 | if (data == null)
140 | return;
141 |
142 | //set cache time
143 | var expiresIn = TimeSpan.FromSeconds(cacheTime);
144 |
145 | //serialize item
146 | var serializedItem = JsonConvert.SerializeObject(data);
147 |
148 | //and set it to cache
149 | await _db.StringSetAsync(key, serializedItem, expiresIn);
150 | }
151 |
152 | public virtual void Set(string key, object data, int cacheTime)
153 | {
154 | if (data == null)
155 | return;
156 |
157 | //set cache time
158 | var expiresIn = TimeSpan.FromMinutes(cacheTime);
159 |
160 | //serialize item
161 | var serializedItem = JsonConvert.SerializeObject(data);
162 |
163 | //and set it to cache
164 | _db.StringSet(key, serializedItem, expiresIn);
165 | }
166 |
167 | public virtual bool IsSet(string key)
168 | {
169 |
170 | return _db.KeyExists(key);
171 | }
172 |
173 | public virtual void Remove(string key)
174 | {
175 | //we should always persist the data protection key list
176 | if (key.Equals(_config.RedisDataProtectionKey, StringComparison.OrdinalIgnoreCase))
177 | return;
178 |
179 | //remove item from caches
180 | _db.KeyDelete(key);
181 | }
182 |
183 | public virtual void RemoveByPrefix(string prefix)
184 | {
185 |
186 | foreach (var endPoint in _connectionWrapper.GetEndPoints())
187 | {
188 | var keys = GetKeys(endPoint, prefix);
189 |
190 | _db.KeyDelete(keys.ToArray());
191 | }
192 | }
193 |
194 | public virtual void Clear()
195 | {
196 | foreach (var endPoint in _connectionWrapper.GetEndPoints())
197 | {
198 | var keys = GetKeys(endPoint).ToArray();
199 |
200 | _db.KeyDelete(keys);
201 | }
202 | }
203 |
204 | public virtual void Dispose()
205 | {
206 | if (_connectionWrapper != null)
207 | {
208 | _connectionWrapper.Dispose();
209 | }
210 | // Dispose(true);
211 | }
212 |
213 | private void Dispose(bool clear)
214 | {
215 | GC.SuppressFinalize(this);
216 | }
217 |
218 |
219 | #endregion
220 | }
221 | }
222 |
--------------------------------------------------------------------------------
/src/Libraries/Caching/RedisConnectionWrapper.cs:
--------------------------------------------------------------------------------
1 | using Models.Settings;
2 | using RedLockNet.SERedis;
3 | using RedLockNet.SERedis.Configuration;
4 | using StackExchange.Redis;
5 | using System;
6 | using System.Linq;
7 | using System.Net;
8 |
9 | namespace Caching
10 | {
11 | public class RedisConnectionWrapper : IRedisConnectionWrapper, ILocker
12 | {
13 | #region Fields
14 |
15 | private readonly RedisSettings _config;
16 |
17 | private readonly object _lock = new object();
18 | private volatile ConnectionMultiplexer _connection;
19 | private readonly Lazy _connectionString;
20 | private volatile RedLockFactory _redisLockFactory;
21 |
22 | #endregion
23 |
24 | #region Ctor
25 |
26 | public RedisConnectionWrapper(RedisSettings config)
27 | {
28 | _config = config;
29 | _connectionString = new Lazy(GetConnectionString);
30 | _redisLockFactory = CreateRedisLockFactory();
31 | }
32 |
33 | #endregion
34 |
35 | #region Utilities
36 |
37 |
38 | protected string GetConnectionString()
39 | {
40 | return _config.RedisConnectionString;
41 | }
42 |
43 |
44 | protected ConnectionMultiplexer GetConnection()
45 | {
46 | if (_connection != null && _connection.IsConnected) return _connection;
47 |
48 | lock (_lock)
49 | {
50 | if (_connection != null && _connection.IsConnected) return _connection;
51 |
52 | //Connection disconnected. Disposing connection...
53 | _connection?.Dispose();
54 |
55 | //Creating new instance of Redis Connection
56 | _connection = ConnectionMultiplexer.Connect(_connectionString.Value);
57 | }
58 |
59 | return _connection;
60 | }
61 |
62 |
63 | protected RedLockFactory CreateRedisLockFactory()
64 | {
65 | //get RedLock endpoints
66 | var configurationOptions = ConfigurationOptions.Parse(_connectionString.Value);
67 | var redLockEndPoints = GetEndPoints().Select(endPoint => new RedLockEndPoint
68 | {
69 | EndPoint = endPoint,
70 | Password = configurationOptions.Password,
71 | Ssl = configurationOptions.Ssl,
72 | RedisDatabase = configurationOptions.DefaultDatabase,
73 | ConfigCheckSeconds = configurationOptions.ConfigCheckSeconds,
74 | ConnectionTimeout = configurationOptions.ConnectTimeout,
75 | SyncTimeout = configurationOptions.SyncTimeout
76 | }).ToList();
77 |
78 | //create RedLock factory to use RedLock distributed lock algorithm
79 | return RedLockFactory.Create(redLockEndPoints);
80 | }
81 |
82 | #endregion
83 |
84 | #region Methods
85 |
86 | public IDatabase GetDatabase(int db)
87 | {
88 | return GetConnection().GetDatabase(db);
89 | }
90 |
91 | public IServer GetServer(EndPoint endPoint)
92 | {
93 | return GetConnection().GetServer(endPoint);
94 | }
95 | public EndPoint[] GetEndPoints()
96 | {
97 | return GetConnection().GetEndPoints();
98 | }
99 |
100 | public void FlushDatabase(RedisDatabaseNumber db)
101 | {
102 | var endPoints = GetEndPoints();
103 |
104 | foreach (var endPoint in endPoints)
105 | {
106 | GetServer(endPoint).FlushDatabase((int)db);
107 | }
108 | }
109 |
110 | public bool PerformActionWithLock(string resource, TimeSpan expirationTime, Action action)
111 | {
112 | //use RedLock library
113 | using (var redisLock = _redisLockFactory.CreateLock(resource, expirationTime))
114 | {
115 | //ensure that lock is acquired
116 | if (!redisLock.IsAcquired)
117 | return false;
118 |
119 | //perform action
120 | action();
121 |
122 | return true;
123 | }
124 | }
125 |
126 | public void Dispose()
127 | {
128 | //dispose ConnectionMultiplexer
129 | _connection?.Dispose();
130 |
131 | //dispose RedLock factory
132 | _redisLockFactory?.Dispose();
133 | }
134 |
135 |
136 |
137 | #endregion
138 | }
139 | }
140 |
--------------------------------------------------------------------------------
/src/Libraries/Caching/RedisDatabaseNumber.cs:
--------------------------------------------------------------------------------
1 | namespace Caching
2 | {
3 | public enum RedisDatabaseNumber
4 | {
5 | ///
6 | /// Database for caching
7 | ///
8 | Cache = 1,
9 | ///
10 | /// Database for plugins
11 | ///
12 | Plugin = 2,
13 | ///
14 | /// Database for data protection keys
15 | ///
16 | DataProtectionKeys = 3
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/Libraries/Caching/ServiceExtensions.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.Configuration;
2 | using Microsoft.Extensions.DependencyInjection;
3 | using Microsoft.Extensions.Options;
4 | using Models.Settings;
5 |
6 | namespace Caching
7 | {
8 | public static class ServiceExtensions
9 | {
10 | public static IServiceCollection AddRedis(this IServiceCollection services, IConfiguration config)
11 | {
12 | #region Configure
13 | services.Configure(config.GetSection("RedisSettings"));
14 | #endregion
15 |
16 | #region Services
17 | services.AddScoped(sp => sp.GetService>().Value);
18 | services.AddTransient();
19 | services.AddTransient();
20 | #endregion
21 |
22 | return services;
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/Libraries/Core/Core.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | net8.0
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/src/Libraries/Core/Exceptions/ApiException.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Globalization;
4 | using System.Text;
5 |
6 | namespace Core.Exceptions
7 | {
8 | public class ApiException : Exception
9 | {
10 | public ApiException() : base() { }
11 |
12 | public ApiException(string message) : base(message) { }
13 |
14 | public ApiException(string message, params object[] args)
15 | : base(String.Format(CultureInfo.CurrentCulture, message, args))
16 | {
17 | }
18 | public int StatusCode { get; set; }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/Libraries/Core/Helpers/IpHelper.cs:
--------------------------------------------------------------------------------
1 | using System.Net;
2 | using System.Net.Sockets;
3 |
4 | namespace Core.Helpers
5 | {
6 | public class IpHelper
7 | {
8 | public static string GetIpAddress()
9 | {
10 | var host = Dns.GetHostEntry(Dns.GetHostName());
11 | foreach (var ip in host.AddressList)
12 | {
13 | if (ip.AddressFamily == AddressFamily.InterNetwork)
14 | {
15 | return ip.ToString();
16 | }
17 | }
18 | return string.Empty;
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/Libraries/Core/Interfaces/IEmailService.cs:
--------------------------------------------------------------------------------
1 | using Models.DTOs.Email;
2 | using System.Threading.Tasks;
3 |
4 | namespace Core.Interfaces
5 | {
6 | public interface IEmailService
7 | {
8 | Task SendAsync(EmailRequest request);
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/src/Libraries/Core/ServiceExtensions.cs:
--------------------------------------------------------------------------------
1 | using Core.Interfaces;
2 | using Core.Services;
3 | using Data.Contexts;
4 | using Data.Repos;
5 | using Data.UnitOfWork;
6 | using Microsoft.EntityFrameworkCore;
7 | using Microsoft.Extensions.Configuration;
8 | using Microsoft.Extensions.DependencyInjection;
9 | using Microsoft.OpenApi.Models;
10 | using Models.Settings;
11 | using Services.Concrete;
12 | using Services.Interfaces;
13 | using System.Collections.Generic;
14 |
15 | namespace Core
16 | {
17 | public static class ServiceExtensions
18 | {
19 | public static void AddSharedServices(this IServiceCollection services, IConfiguration config)
20 | {
21 | #region Configure
22 | services.Configure(config.GetSection("MailSettings"));
23 | #endregion
24 |
25 | #region Services
26 | services.AddTransient();
27 | #endregion
28 | }
29 | public static void AddApplicationSqlServer(this IServiceCollection services, IConfiguration config)
30 | {
31 | services.AddDbContext(options =>
32 | {
33 | options.UseSqlServer(config.GetConnectionString("DefaultConnection"),
34 | b => b.MigrationsAssembly(typeof(ApplicationDbContext).Assembly.FullName));
35 | });
36 | services.AddTransient();
37 |
38 | // Ensure the database is created.
39 | using var context = services.BuildServiceProvider().GetService();
40 | context.Database.EnsureCreated();
41 | }
42 | public static void AddRepoServices(this IServiceCollection services, IConfiguration config)
43 | {
44 | services.AddTransient(typeof(IGenericRepository<>), typeof(GenericRepository<>));
45 |
46 | services.AddScoped();
47 | }
48 | public static void AddAppServices(this IServiceCollection services, IConfiguration config)
49 | {
50 | services.AddTransient();
51 |
52 | services.AddTransient();
53 | }
54 | public static void AddCustomSwagger(this IServiceCollection services, IConfiguration config)
55 | {
56 | services.AddSwaggerGen(c =>
57 | {
58 | c.SwaggerDoc("v1", new OpenApiInfo { Title = "WebApi", Version = "v1" });
59 | c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
60 | {
61 | Description = @"JWT Authorization header using the Bearer scheme.
62 | Enter 'Bearer' [space] and then your token in the text input below.
63 |
Example: 'Bearer 12345abcdef'",
64 | Name = "Authorization",
65 | In = ParameterLocation.Header,
66 | Type = SecuritySchemeType.ApiKey,
67 | Scheme = "Bearer"
68 | });
69 | c.AddSecurityRequirement(new OpenApiSecurityRequirement()
70 | {
71 | {
72 | new OpenApiSecurityScheme
73 | {
74 | Reference = new OpenApiReference
75 | {
76 | Type = ReferenceType.SecurityScheme,
77 | Id = "Bearer"
78 | },
79 | Scheme = "oauth2",
80 | Name = "Bearer",
81 | In = ParameterLocation.Header,
82 |
83 | },
84 | new List()
85 | }
86 | });
87 |
88 | });
89 | }
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/src/Libraries/Core/Services/EmailService.cs:
--------------------------------------------------------------------------------
1 | using Core.Interfaces;
2 | using MailKit.Security;
3 | using Microsoft.Extensions.Logging;
4 | using MimeKit;
5 | using Models.DTOs.Email;
6 | using Models.Settings;
7 | using System;
8 | using System.Threading.Tasks;
9 | using MailKit.Net.Smtp;
10 | using Core.Exceptions;
11 | using Microsoft.Extensions.Options;
12 |
13 | namespace Core.Services
14 | {
15 | public class EmailService : IEmailService
16 | {
17 | private readonly MailSettings _mailSettings;
18 | private readonly ILogger _logger;
19 |
20 | public EmailService(IOptions mailSettings, ILogger logger)
21 | {
22 | _mailSettings = mailSettings.Value;
23 | _logger = logger;
24 | }
25 |
26 | public async Task SendAsync(EmailRequest request)
27 | {
28 | try
29 | {
30 | var email = new MimeMessage();
31 | email.Sender = MailboxAddress.Parse(request.From ?? _mailSettings.EmailFrom);
32 | email.To.Add(MailboxAddress.Parse(request.To));
33 | email.Subject = request.Subject;
34 | var builder = new BodyBuilder();
35 | builder.HtmlBody = request.Body;
36 | email.Body = builder.ToMessageBody();
37 | using var smtp = new SmtpClient();
38 | smtp.Connect(_mailSettings.SmtpHost, _mailSettings.SmtpPort, SecureSocketOptions.StartTls);
39 | smtp.Authenticate(_mailSettings.SmtpUser, _mailSettings.SmtpPass);
40 | await smtp.SendAsync(email);
41 | smtp.Disconnect(true);
42 | }
43 | catch (Exception ex)
44 | {
45 | _logger.LogError(ex.Message, ex);
46 | throw new ApiException(ex.Message);
47 | }
48 | }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/Libraries/Data.Mongo/Attributes/BsonCollectionAttribute.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace Data.Mongo.Attributes
4 | {
5 | [AttributeUsage(AttributeTargets.Class, Inherited = false)]
6 | public class BsonCollectionAttribute : Attribute
7 | {
8 | public string CollectionName { get; }
9 |
10 | public BsonCollectionAttribute(string collectionName)
11 | {
12 | CollectionName = collectionName;
13 | }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/Libraries/Data.Mongo/Collections/LoginLog.cs:
--------------------------------------------------------------------------------
1 | using Data.Mongo.Attributes;
2 | using MongoDB.Bson.Serialization.Attributes;
3 | using System;
4 |
5 | namespace Data.Mongo.Collections
6 | {
7 | [BsonCollection("loginlogs")]
8 | [BsonIgnoreExtraElements]
9 | public class LoginLog : MongoBaseDocument
10 | {
11 | public string UserEmail { get; set; }
12 | public DateTime LoginTime { get; set; }
13 | }
14 | }
--------------------------------------------------------------------------------
/src/Libraries/Data.Mongo/Collections/MongoBaseDocument.cs:
--------------------------------------------------------------------------------
1 | using MongoDB.Bson;
2 | using MongoDB.Bson.Serialization.Attributes;
3 | using Newtonsoft.Json;
4 | using System.Runtime.Serialization;
5 |
6 | namespace Data.Mongo.Collections
7 | {
8 | public abstract class MongoBaseDocument
9 | {
10 | ///
11 | /// Id > String
12 | ///
13 | [JsonProperty(Order = 1)]
14 | [BsonElement(Order = 0)]
15 | [BsonRepresentation(BsonType.ObjectId)]
16 | public string Id => _Id;
17 |
18 |
19 | [BsonId]
20 | [DataMember]
21 | [BsonIgnoreIfDefault]
22 | [BsonRepresentation(BsonType.ObjectId)]
23 | public virtual string _Id { get; set; }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/Libraries/Data.Mongo/Data.Mongo.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | net8.0
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/src/Libraries/Data.Mongo/MongoDbOptions.cs:
--------------------------------------------------------------------------------
1 | namespace Data.Mongo
2 | {
3 | public class MongoDbOptions
4 | {
5 | public string ConnectionString { get; set; }
6 | public string Database { get; set; }
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/src/Libraries/Data.Mongo/Repo/IMongoRepository.cs:
--------------------------------------------------------------------------------
1 | using Data.Mongo.Collections;
2 | using MongoDB.Driver;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Linq.Expressions;
6 | using System.Threading.Tasks;
7 |
8 | namespace Data.Mongo.Repo
9 | {
10 | public interface IMongoRepository where T : MongoBaseDocument
11 | {
12 | ///
13 | ///
14 | ///
15 | ///
16 | ///
17 | Task GetByIdAsync(string id);
18 |
19 | ///
20 | ///
21 | ///
22 | ///
23 | ///
24 | Task GetAsync(Expression> predicate);
25 |
26 | ///
27 | ///
28 | ///
29 | ///
30 | ///
31 | Task> FindAsync(Expression> predicate);
32 | ///
33 | ///
34 | ///
35 | ///
36 | ///
37 | IEnumerable Find(Expression> predicate);
38 |
39 | ///
40 | ///
41 | ///
42 | ///
43 | ///
44 | Task AddAsync(T entity);
45 |
46 | ///
47 | ///
48 | ///
49 | ///
50 | ///
51 | Task UpdateAsync(T entity);
52 |
53 | ///
54 | ///
55 | ///
56 | ///
57 | ///
58 | Task DeleteAsync(string id);
59 |
60 | ///
61 | ///
62 | ///
63 | ///
64 | ///
65 | Task ExistsAsync(Expression> predicate);
66 |
67 | ///
68 | ///
69 | ///
70 | ///
71 | ///
72 | ///
73 | Task> FindDistinctAsync(string field, FilterDefinition filter);
74 |
75 | ///
76 | ///
77 | ///
78 | ///
79 | List GetAll();
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/src/Libraries/Data.Mongo/Repo/MongoRepository.cs:
--------------------------------------------------------------------------------
1 | using Data.Mongo.Attributes;
2 | using Data.Mongo.Collections;
3 | using MongoDB.Driver;
4 | using System;
5 | using System.Collections.Generic;
6 | using System.Linq;
7 | using System.Linq.Expressions;
8 | using System.Text;
9 | using System.Threading.Tasks;
10 |
11 | namespace Data.Mongo.Repo
12 | {
13 | public class MongoRepository : IMongoRepository where T : MongoBaseDocument
14 | {
15 |
16 | protected IMongoCollection Collection { get; }
17 |
18 | public MongoRepository(IMongoDatabase database)
19 | {
20 | string collectionName;
21 |
22 | var att = Attribute.GetCustomAttribute(typeof(T), typeof(BsonCollectionAttribute));
23 |
24 | if (att != null)
25 | {
26 | collectionName = ((BsonCollectionAttribute)att).CollectionName;
27 | }
28 | else
29 | {
30 | collectionName = typeof(T).Name;
31 | }
32 |
33 | //var collectionName = typeof(TEntity).GetCustomAttribute(false).CollectionName;
34 | Collection = database.GetCollection(collectionName);
35 |
36 | }
37 |
38 | public async Task AddAsync(T entity)
39 | => await Collection.InsertOneAsync(entity);
40 |
41 | ///
42 | ///
43 | ///
44 | ///
45 | ///
46 | public async Task DeleteAsync(string id)
47 | => await Collection.DeleteOneAsync(e => e.Id == id);
48 |
49 | ///
50 | ///
51 | ///
52 | ///
53 | ///
54 | public async Task ExistsAsync(Expression> predicate)
55 | => await Collection.Find(predicate).AnyAsync();
56 |
57 | ///
58 | /// Not Async
59 | ///
60 | ///
61 | ///
62 | public IEnumerable Find(Expression> predicate)
63 | => Collection.Find(predicate).ToList();
64 |
65 | ///
66 | ///
67 | ///
68 | ///
69 | ///
70 | public async Task> FindAsync(Expression> predicate)
71 | => await Collection.Find(predicate).ToListAsync();
72 |
73 | public async Task> FindDistinctAsync(string field, FilterDefinition filter)
74 | => (ICollection)await Collection.DistinctAsync(field, filter);
75 |
76 | ///
77 | ///
78 | ///
79 | ///
80 | ///
81 | public async Task GetByIdAsync(string id)
82 | => await GetAsync(e => e.Id == id);
83 |
84 | ///
85 | ///
86 | ///
87 | ///
88 | ///
89 | public async Task GetAsync(Expression> predicate)
90 | => await Collection.Find(predicate).SingleOrDefaultAsync();
91 |
92 | ///
93 | ///
94 | ///
95 | ///
96 | ///
97 | public async Task UpdateAsync(T entity)
98 | => await Collection.ReplaceOneAsync(e => e.Id == entity.Id, entity);
99 |
100 | ///
101 | ///
102 | ///
103 | ///
104 | public List GetAll()
105 | => Collection.Find(Builders.Filter.Empty).ToList();
106 | }
107 | }
108 |
--------------------------------------------------------------------------------
/src/Libraries/Data.Mongo/ServiceExtensions.cs:
--------------------------------------------------------------------------------
1 | using Data.Mongo.Repo;
2 | using Microsoft.Extensions.Configuration;
3 | using Microsoft.Extensions.DependencyInjection;
4 | using MongoDB.Driver;
5 |
6 | namespace Data.Mongo
7 | {
8 | public static class ServiceExtensions
9 | {
10 | public static void AddMongo(this IServiceCollection services, IConfiguration configuration)
11 | {
12 | var options = new MongoDbOptions();
13 | configuration.GetSection("MongoDb").Bind(options);
14 |
15 | services.AddSingleton(sp =>
16 | {
17 | return new MongoClient(options.ConnectionString);
18 | });
19 |
20 | services.AddScoped(typeof(IMongoRepository<>), typeof(MongoRepository<>));
21 |
22 | services.AddScoped(sp =>
23 | {
24 | var client = sp.GetRequiredService();
25 | return client.GetDatabase(options.Database);
26 | });
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/Libraries/Data/Contexts/ApplicationDbContext.cs:
--------------------------------------------------------------------------------
1 | using Data.Mapping;
2 | using Microsoft.EntityFrameworkCore;
3 | using System;
4 | using System.Linq;
5 | using System.Reflection;
6 |
7 | namespace Data.Contexts
8 | {
9 | public class ApplicationDbContext : DbContext, IDbContext
10 | {
11 | public ApplicationDbContext(DbContextOptions options) : base(options)
12 | {
13 | }
14 |
15 | protected override void OnModelCreating(ModelBuilder modelBuilder)
16 | {
17 | RegisterEntityMapping(modelBuilder);
18 | base.OnModelCreating(modelBuilder);
19 | }
20 |
21 | public void RegisterEntityMapping(ModelBuilder modelBuilder)
22 | {
23 | var typeConfigurations = Assembly.GetExecutingAssembly().GetTypes().Where(type =>
24 | (type.BaseType?.IsGenericType ?? false) &&
25 | (type.BaseType.GetGenericTypeDefinition() == typeof(MappingEntityTypeConfiguration<>))
26 | );
27 | foreach (var item in typeConfigurations)
28 | {
29 | var configuration = (IMappingConfiguration)Activator.CreateInstance(item);
30 | configuration!.ApplyConfiguration(modelBuilder);
31 | }
32 | }
33 |
34 | public new virtual DbSet Set() where TEntity : class
35 | {
36 | return base.Set();
37 | }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/Libraries/Data/Contexts/IDbContext.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.EntityFrameworkCore;
2 |
3 | namespace Data.Contexts
4 | {
5 | public interface IDbContext
6 | {
7 | DbSet Set() where TEntity : class;
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/src/Libraries/Data/Data.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | net8.0
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/src/Libraries/Data/Mapping/IMappingConfiguration.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.EntityFrameworkCore;
2 |
3 | namespace Data.Mapping
4 | {
5 | public interface IMappingConfiguration
6 | {
7 | void ApplyConfiguration(ModelBuilder modelBuilder);
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/src/Libraries/Data/Mapping/MappingEntityTypeConfiguration.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.EntityFrameworkCore;
2 | using Microsoft.EntityFrameworkCore.Metadata.Builders;
3 | using Models.DbEntities;
4 |
5 | namespace Data.Mapping
6 | {
7 | public class MappingEntityTypeConfiguration : IMappingConfiguration, IEntityTypeConfiguration where TEntity : BaseEntity
8 | {
9 | public virtual void ApplyConfiguration(ModelBuilder modelBuilder)
10 | {
11 | modelBuilder.ApplyConfiguration(this);
12 | }
13 |
14 | public virtual void Configure(EntityTypeBuilder builder)
15 | {
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/Libraries/Data/Mapping/NoteMap.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.EntityFrameworkCore;
2 | using Microsoft.EntityFrameworkCore.Metadata.Builders;
3 | using Models.DbEntities;
4 |
5 | namespace Data.Mapping
6 | {
7 | public class NoteMap : MappingEntityTypeConfiguration
8 | {
9 | public override void Configure(EntityTypeBuilder builder)
10 | {
11 | builder.ToTable("Notes");
12 | builder.HasKey(p => p.Id);
13 | builder.Property(p => p.Title).HasMaxLength(255);
14 | builder.Property(p => p.Category).HasMaxLength(255);
15 | builder.Property(p => p.Description).HasMaxLength(255);
16 | builder.Property(p => p.OwnerEmail).HasMaxLength(255);
17 | builder.Property(p => p.CreateUTC).HasColumnType("DateTime").HasDefaultValueSql("GetUtcDate()");
18 | base.Configure(builder);
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/Libraries/Data/Migrations/20201008073308_first_appDb_migration.Designer.cs:
--------------------------------------------------------------------------------
1 | //
2 | using Data.Contexts;
3 | using Microsoft.EntityFrameworkCore;
4 | using Microsoft.EntityFrameworkCore.Infrastructure;
5 | using Microsoft.EntityFrameworkCore.Metadata;
6 | using Microsoft.EntityFrameworkCore.Migrations;
7 | using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
8 |
9 | namespace Data.Migrations
10 | {
11 | [DbContext(typeof(ApplicationDbContext))]
12 | [Migration("20201008073308_first_appDb_migration")]
13 | partial class first_appDb_migration
14 | {
15 | protected override void BuildTargetModel(ModelBuilder modelBuilder)
16 | {
17 | #pragma warning disable 612, 618
18 | modelBuilder
19 | .HasAnnotation("ProductVersion", "3.1.8")
20 | .HasAnnotation("Relational:MaxIdentifierLength", 128)
21 | .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
22 | #pragma warning restore 612, 618
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/Libraries/Data/Migrations/20201008073308_first_appDb_migration.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.EntityFrameworkCore.Migrations;
2 |
3 | namespace Data.Migrations
4 | {
5 | public partial class first_appDb_migration : Migration
6 | {
7 | protected override void Up(MigrationBuilder migrationBuilder)
8 | {
9 |
10 | }
11 |
12 | protected override void Down(MigrationBuilder migrationBuilder)
13 | {
14 |
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/Libraries/Data/Migrations/20201008074018_new_appDb_migration.Designer.cs:
--------------------------------------------------------------------------------
1 | //
2 | using System;
3 | using Data.Contexts;
4 | using Microsoft.EntityFrameworkCore;
5 | using Microsoft.EntityFrameworkCore.Infrastructure;
6 | using Microsoft.EntityFrameworkCore.Metadata;
7 | using Microsoft.EntityFrameworkCore.Migrations;
8 | using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
9 |
10 | namespace Data.Migrations
11 | {
12 | [DbContext(typeof(ApplicationDbContext))]
13 | [Migration("20201008074018_new_appDb_migration")]
14 | partial class new_appDb_migration
15 | {
16 | protected override void BuildTargetModel(ModelBuilder modelBuilder)
17 | {
18 | #pragma warning disable 612, 618
19 | modelBuilder
20 | .HasAnnotation("ProductVersion", "3.1.8")
21 | .HasAnnotation("Relational:MaxIdentifierLength", 128)
22 | .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
23 |
24 | modelBuilder.Entity("Models.DbEntities.Note", b =>
25 | {
26 | b.Property("Id")
27 | .ValueGeneratedOnAdd()
28 | .HasColumnType("int")
29 | .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
30 |
31 | b.Property("Category")
32 | .HasColumnType("nvarchar(255)")
33 | .HasMaxLength(255);
34 |
35 | b.Property("CreateUTC")
36 | .ValueGeneratedOnAdd()
37 | .HasColumnType("DateTime")
38 | .HasDefaultValueSql("GetUtcDate()");
39 |
40 | b.Property("Description")
41 | .HasColumnType("nvarchar(255)")
42 | .HasMaxLength(255);
43 |
44 | b.Property("OwnerEmail")
45 | .HasColumnType("nvarchar(255)")
46 | .HasMaxLength(255);
47 |
48 | b.Property("Title")
49 | .HasColumnType("nvarchar(255)")
50 | .HasMaxLength(255);
51 |
52 | b.HasKey("Id");
53 |
54 | b.ToTable("Notes");
55 | });
56 | #pragma warning restore 612, 618
57 | }
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/src/Libraries/Data/Migrations/20201008074018_new_appDb_migration.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Microsoft.EntityFrameworkCore.Migrations;
3 |
4 | namespace Data.Migrations
5 | {
6 | public partial class new_appDb_migration : Migration
7 | {
8 | protected override void Up(MigrationBuilder migrationBuilder)
9 | {
10 | migrationBuilder.CreateTable(
11 | name: "Notes",
12 | columns: table => new
13 | {
14 | Id = table.Column(nullable: false)
15 | .Annotation("SqlServer:Identity", "1, 1"),
16 | CreateUTC = table.Column(type: "DateTime", nullable: false, defaultValueSql: "GetUtcDate()"),
17 | Title = table.Column(maxLength: 255, nullable: true),
18 | Category = table.Column(maxLength: 255, nullable: true),
19 | Description = table.Column(maxLength: 255, nullable: true),
20 | OwnerEmail = table.Column(maxLength: 255, nullable: true)
21 | },
22 | constraints: table =>
23 | {
24 | table.PrimaryKey("PK_Notes", x => x.Id);
25 | });
26 | }
27 |
28 | protected override void Down(MigrationBuilder migrationBuilder)
29 | {
30 | migrationBuilder.DropTable(
31 | name: "Notes");
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/Libraries/Data/Migrations/ApplicationDbContextModelSnapshot.cs:
--------------------------------------------------------------------------------
1 | //
2 | using System;
3 | using Data.Contexts;
4 | using Microsoft.EntityFrameworkCore;
5 | using Microsoft.EntityFrameworkCore.Infrastructure;
6 | using Microsoft.EntityFrameworkCore.Metadata;
7 | using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
8 |
9 | namespace Data.Migrations
10 | {
11 | [DbContext(typeof(ApplicationDbContext))]
12 | partial class ApplicationDbContextModelSnapshot : ModelSnapshot
13 | {
14 | protected override void BuildModel(ModelBuilder modelBuilder)
15 | {
16 | #pragma warning disable 612, 618
17 | modelBuilder
18 | .HasAnnotation("ProductVersion", "3.1.8")
19 | .HasAnnotation("Relational:MaxIdentifierLength", 128)
20 | .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
21 |
22 | modelBuilder.Entity("Models.DbEntities.Note", b =>
23 | {
24 | b.Property("Id")
25 | .ValueGeneratedOnAdd()
26 | .HasColumnType("int")
27 | .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
28 |
29 | b.Property("Category")
30 | .HasColumnType("nvarchar(255)")
31 | .HasMaxLength(255);
32 |
33 | b.Property("CreateUTC")
34 | .ValueGeneratedOnAdd()
35 | .HasColumnType("DateTime")
36 | .HasDefaultValueSql("GetUtcDate()");
37 |
38 | b.Property("Description")
39 | .HasColumnType("nvarchar(255)")
40 | .HasMaxLength(255);
41 |
42 | b.Property("OwnerEmail")
43 | .HasColumnType("nvarchar(255)")
44 | .HasMaxLength(255);
45 |
46 | b.Property("Title")
47 | .HasColumnType("nvarchar(255)")
48 | .HasMaxLength(255);
49 |
50 | b.HasKey("Id");
51 |
52 | b.ToTable("Notes");
53 | });
54 | #pragma warning restore 612, 618
55 | }
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/src/Libraries/Data/Repos/GenericRepository.cs:
--------------------------------------------------------------------------------
1 | using Data.Contexts;
2 | using Microsoft.EntityFrameworkCore;
3 | using Models.DbEntities;
4 | using System;
5 | using System.Collections.Generic;
6 | using System.Linq;
7 | using System.Linq.Expressions;
8 | using System.Threading.Tasks;
9 |
10 | namespace Data.Repos
11 | {
12 | public class GenericRepository : IGenericRepository where T : BaseEntity
13 | {
14 | private readonly ApplicationDbContext _context;
15 | public GenericRepository(ApplicationDbContext context = null)
16 | {
17 | _context = context;
18 | }
19 |
20 | public bool BulkInsert(List entities)
21 | {
22 | _context.ChangeTracker.AutoDetectChangesEnabled = false;
23 | try
24 | {
25 | _context.Set().AddRange(entities);
26 | _context.SaveChanges();
27 | return true;
28 | }
29 | catch
30 | {
31 | return false;
32 | }
33 | }
34 |
35 | public int Delete(T entity)
36 | {
37 | _context.Set().Remove(entity);
38 | return _context.SaveChanges();
39 | }
40 |
41 | public T Find(Expression> match)
42 | {
43 | return _context.Set().FirstOrDefault(match);
44 | }
45 |
46 | public List FindAll(Expression> match)
47 | {
48 | return _context.Set().Where(match).ToList();
49 | }
50 |
51 | public async Task> FindAllAsync(Expression> match)
52 | {
53 | return await _context.Set().Where(match).ToListAsync();
54 | }
55 |
56 | public List GetAll()
57 | {
58 | return _context.Set().ToList();
59 | }
60 |
61 | public T GetById(int id)
62 | {
63 | return _context.Set().Find(id);
64 | }
65 |
66 | public T Insert(T entity)
67 | {
68 | _context.Set().Add(entity);
69 | _context.SaveChanges();
70 | return entity;
71 | }
72 |
73 | public T Update(T entity)
74 | {
75 | if (entity == null)
76 | return null;
77 | _context.Set().Attach(entity);
78 | _context.Entry(entity).State = EntityState.Modified;
79 | _context.SaveChanges();
80 | return entity;
81 | }
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/src/Libraries/Data/Repos/IGenericRepository.cs:
--------------------------------------------------------------------------------
1 | using Models.DbEntities;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Linq.Expressions;
5 | using System.Threading.Tasks;
6 |
7 | namespace Data.Repos
8 | {
9 | public interface IGenericRepository where T : BaseEntity
10 | {
11 | List GetAll();
12 | T GetById(int id);
13 | T Find(Expression> match);
14 | List FindAll(Expression> match);
15 | Task> FindAllAsync(Expression> match);
16 | T Insert(T entity);
17 | bool BulkInsert(List entities);
18 | T Update(T entity);
19 | int Delete(T entity);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/Libraries/Data/UnitOfWork/IUnitOfWork.cs:
--------------------------------------------------------------------------------
1 | using Data.Repos;
2 | using Models.DbEntities;
3 | using System;
4 | using System.Threading.Tasks;
5 |
6 | namespace Data.UnitOfWork
7 | {
8 | public interface IUnitOfWork : IDisposable
9 | {
10 | IGenericRepository Repository() where TEntity : BaseEntity;
11 | Task Complete();
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/Libraries/Data/UnitOfWork/UnitOfWork.cs:
--------------------------------------------------------------------------------
1 | using Data.Contexts;
2 | using Data.Repos;
3 | using Models.DbEntities;
4 | using System;
5 | using System.Collections;
6 | using System.Threading.Tasks;
7 |
8 | namespace Data.UnitOfWork
9 | {
10 | public class UnitOfWork : IUnitOfWork
11 | {
12 | private readonly ApplicationDbContext _context;
13 | private Hashtable _repositories;
14 | public UnitOfWork(ApplicationDbContext context)
15 | {
16 | _context = context;
17 | }
18 |
19 | public async Task Complete()
20 | {
21 | return await _context.SaveChangesAsync();
22 | }
23 |
24 | public void Dispose()
25 | {
26 | _context.Dispose();
27 | }
28 |
29 | public IGenericRepository Repository() where TEntity : BaseEntity
30 | {
31 | if (_repositories == null) _repositories = new Hashtable();
32 |
33 | var type = typeof(TEntity).Name;
34 |
35 | if (!_repositories.ContainsKey(type))
36 | {
37 | var repositoryType = typeof(GenericRepository<>);
38 | var repositoryInstance = Activator.CreateInstance(repositoryType.MakeGenericType(typeof(TEntity)), _context);
39 |
40 | _repositories.Add(type, repositoryInstance);
41 | }
42 |
43 | return (IGenericRepository)_repositories[type];
44 | }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/Libraries/Identity/Contexts/IdentityContext.cs:
--------------------------------------------------------------------------------
1 | using Identity.Models;
2 | using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
3 | using Microsoft.EntityFrameworkCore;
4 |
5 | namespace Identity.Contexts
6 | {
7 | public class IdentityContext
8 | : IdentityDbContext<
9 | ApplicationUser, ApplicationRole, int,
10 | ApplicationUserClaim, ApplicationUserRole, ApplicationUserLogin,
11 | ApplicationRoleClaim, ApplicationUserToken>
12 | {
13 | public IdentityContext(DbContextOptions options) : base(options)
14 | {
15 | }
16 | protected override void OnModelCreating(ModelBuilder builder)
17 | {
18 | base.OnModelCreating(builder);
19 |
20 | builder.HasDefaultSchema("Identity");
21 | builder.Entity(entity =>
22 | {
23 | entity.ToTable(name: "User");
24 | });
25 |
26 | builder.Entity(entity =>
27 | {
28 | entity.ToTable(name: "Role");
29 | });
30 |
31 | builder.Entity(entity =>
32 | {
33 | entity.HasKey(ur => new { ur.UserId, ur.RoleId });
34 |
35 | entity.HasOne(ur => ur.Role)
36 | .WithMany(r => r.UserRoles)
37 | .HasForeignKey(ur => ur.RoleId)
38 | .IsRequired();
39 |
40 | entity.HasOne(ur => ur.User)
41 | .WithMany(r => r.UserRoles)
42 | .HasForeignKey(ur => ur.UserId)
43 | .IsRequired();
44 | entity.ToTable("UserRoles");
45 | });
46 |
47 | builder.Entity(entity =>
48 | {
49 | entity.ToTable("UserClaims");
50 | });
51 |
52 | builder.Entity(entity =>
53 | {
54 | entity.ToTable("UserLogins");
55 | });
56 |
57 | builder.Entity(entity =>
58 | {
59 | entity.ToTable("RoleClaims");
60 |
61 | });
62 |
63 | builder.Entity(entity =>
64 | {
65 | entity.ToTable("UserTokens");
66 | });
67 | }
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/src/Libraries/Identity/Identity.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | net8.0
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/src/Libraries/Identity/Migrations/20201005130141_my_new_identity_migration.Designer.cs:
--------------------------------------------------------------------------------
1 | //
2 | using System;
3 | using Identity.Contexts;
4 | using Microsoft.EntityFrameworkCore;
5 | using Microsoft.EntityFrameworkCore.Infrastructure;
6 | using Microsoft.EntityFrameworkCore.Metadata;
7 | using Microsoft.EntityFrameworkCore.Migrations;
8 | using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
9 |
10 | namespace Identity.Migrations
11 | {
12 | [DbContext(typeof(IdentityContext))]
13 | [Migration("20201005130141_my_new_identity_migration")]
14 | partial class my_new_identity_migration
15 | {
16 | protected override void BuildTargetModel(ModelBuilder modelBuilder)
17 | {
18 | #pragma warning disable 612, 618
19 | modelBuilder
20 | .HasDefaultSchema("Identity")
21 | .HasAnnotation("ProductVersion", "3.1.8")
22 | .HasAnnotation("Relational:MaxIdentifierLength", 128)
23 | .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
24 |
25 | modelBuilder.Entity("Identity.Models.ApplicationRole", b =>
26 | {
27 | b.Property("Id")
28 | .ValueGeneratedOnAdd()
29 | .HasColumnType("int")
30 | .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
31 |
32 | b.Property("ConcurrencyStamp")
33 | .IsConcurrencyToken()
34 | .HasColumnType("nvarchar(max)");
35 |
36 | b.Property("CreatedDate")
37 | .HasColumnType("datetime2");
38 |
39 | b.Property("Name")
40 | .HasColumnType("nvarchar(256)")
41 | .HasMaxLength(256);
42 |
43 | b.Property("NormalizedName")
44 | .HasColumnType("nvarchar(256)")
45 | .HasMaxLength(256);
46 |
47 | b.HasKey("Id");
48 |
49 | b.HasIndex("NormalizedName")
50 | .IsUnique()
51 | .HasName("RoleNameIndex")
52 | .HasFilter("[NormalizedName] IS NOT NULL");
53 |
54 | b.ToTable("Role");
55 | });
56 |
57 | modelBuilder.Entity("Identity.Models.ApplicationRoleClaim", b =>
58 | {
59 | b.Property("Id")
60 | .ValueGeneratedOnAdd()
61 | .HasColumnType("int")
62 | .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
63 |
64 | b.Property("ClaimType")
65 | .HasColumnType("nvarchar(max)");
66 |
67 | b.Property("ClaimValue")
68 | .HasColumnType("nvarchar(max)");
69 |
70 | b.Property("RoleId")
71 | .HasColumnType("int");
72 |
73 | b.HasKey("Id");
74 |
75 | b.HasIndex("RoleId");
76 |
77 | b.ToTable("RoleClaims");
78 | });
79 |
80 | modelBuilder.Entity("Identity.Models.ApplicationUser", b =>
81 | {
82 | b.Property("Id")
83 | .ValueGeneratedOnAdd()
84 | .HasColumnType("int")
85 | .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
86 |
87 | b.Property("AccessFailedCount")
88 | .HasColumnType("int");
89 |
90 | b.Property("ConcurrencyStamp")
91 | .IsConcurrencyToken()
92 | .HasColumnType("nvarchar(max)");
93 |
94 | b.Property("Email")
95 | .HasColumnType("nvarchar(256)")
96 | .HasMaxLength(256);
97 |
98 | b.Property("EmailConfirmed")
99 | .HasColumnType("bit");
100 |
101 | b.Property("FirstName")
102 | .HasColumnType("nvarchar(max)");
103 |
104 | b.Property("LastName")
105 | .HasColumnType("nvarchar(max)");
106 |
107 | b.Property("LockoutEnabled")
108 | .HasColumnType("bit");
109 |
110 | b.Property("LockoutEnd")
111 | .HasColumnType("datetimeoffset");
112 |
113 | b.Property("NormalizedEmail")
114 | .HasColumnType("nvarchar(256)")
115 | .HasMaxLength(256);
116 |
117 | b.Property("NormalizedUserName")
118 | .HasColumnType("nvarchar(256)")
119 | .HasMaxLength(256);
120 |
121 | b.Property("PasswordHash")
122 | .HasColumnType("nvarchar(max)");
123 |
124 | b.Property("PhoneNumber")
125 | .HasColumnType("nvarchar(max)");
126 |
127 | b.Property("PhoneNumberConfirmed")
128 | .HasColumnType("bit");
129 |
130 | b.Property("SecurityStamp")
131 | .HasColumnType("nvarchar(max)");
132 |
133 | b.Property("TwoFactorEnabled")
134 | .HasColumnType("bit");
135 |
136 | b.Property("UserName")
137 | .HasColumnType("nvarchar(256)")
138 | .HasMaxLength(256);
139 |
140 | b.HasKey("Id");
141 |
142 | b.HasIndex("NormalizedEmail")
143 | .HasName("EmailIndex");
144 |
145 | b.HasIndex("NormalizedUserName")
146 | .IsUnique()
147 | .HasName("UserNameIndex")
148 | .HasFilter("[NormalizedUserName] IS NOT NULL");
149 |
150 | b.ToTable("User");
151 | });
152 |
153 | modelBuilder.Entity("Identity.Models.ApplicationUserClaim", b =>
154 | {
155 | b.Property("Id")
156 | .ValueGeneratedOnAdd()
157 | .HasColumnType("int")
158 | .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
159 |
160 | b.Property("ClaimType")
161 | .HasColumnType("nvarchar(max)");
162 |
163 | b.Property("ClaimValue")
164 | .HasColumnType("nvarchar(max)");
165 |
166 | b.Property("UserId")
167 | .HasColumnType("int");
168 |
169 | b.HasKey("Id");
170 |
171 | b.HasIndex("UserId");
172 |
173 | b.ToTable("UserClaims");
174 | });
175 |
176 | modelBuilder.Entity("Identity.Models.ApplicationUserLogin", b =>
177 | {
178 | b.Property("LoginProvider")
179 | .HasColumnType("nvarchar(450)");
180 |
181 | b.Property("ProviderKey")
182 | .HasColumnType("nvarchar(450)");
183 |
184 | b.Property("ProviderDisplayName")
185 | .HasColumnType("nvarchar(max)");
186 |
187 | b.Property("UserId")
188 | .HasColumnType("int");
189 |
190 | b.HasKey("LoginProvider", "ProviderKey");
191 |
192 | b.HasIndex("UserId");
193 |
194 | b.ToTable("UserLogins");
195 | });
196 |
197 | modelBuilder.Entity("Identity.Models.ApplicationUserRole", b =>
198 | {
199 | b.Property("UserId")
200 | .HasColumnType("int");
201 |
202 | b.Property("RoleId")
203 | .HasColumnType("int");
204 |
205 | b.HasKey("UserId", "RoleId");
206 |
207 | b.HasIndex("RoleId");
208 |
209 | b.ToTable("UserRoles");
210 | });
211 |
212 | modelBuilder.Entity("Identity.Models.ApplicationUserToken", b =>
213 | {
214 | b.Property("UserId")
215 | .HasColumnType("int");
216 |
217 | b.Property("LoginProvider")
218 | .HasColumnType("nvarchar(450)");
219 |
220 | b.Property("Name")
221 | .HasColumnType("nvarchar(450)");
222 |
223 | b.Property("Value")
224 | .HasColumnType("nvarchar(max)");
225 |
226 | b.HasKey("UserId", "LoginProvider", "Name");
227 |
228 | b.ToTable("UserTokens");
229 | });
230 |
231 | modelBuilder.Entity("Identity.Models.ApplicationRoleClaim", b =>
232 | {
233 | b.HasOne("Identity.Models.ApplicationRole", null)
234 | .WithMany()
235 | .HasForeignKey("RoleId")
236 | .OnDelete(DeleteBehavior.Cascade)
237 | .IsRequired();
238 | });
239 |
240 | modelBuilder.Entity("Identity.Models.ApplicationUserClaim", b =>
241 | {
242 | b.HasOne("Identity.Models.ApplicationUser", null)
243 | .WithMany()
244 | .HasForeignKey("UserId")
245 | .OnDelete(DeleteBehavior.Cascade)
246 | .IsRequired();
247 | });
248 |
249 | modelBuilder.Entity("Identity.Models.ApplicationUserLogin", b =>
250 | {
251 | b.HasOne("Identity.Models.ApplicationUser", null)
252 | .WithMany()
253 | .HasForeignKey("UserId")
254 | .OnDelete(DeleteBehavior.Cascade)
255 | .IsRequired();
256 | });
257 |
258 | modelBuilder.Entity("Identity.Models.ApplicationUserRole", b =>
259 | {
260 | b.HasOne("Identity.Models.ApplicationRole", null)
261 | .WithMany()
262 | .HasForeignKey("RoleId")
263 | .OnDelete(DeleteBehavior.Cascade)
264 | .IsRequired();
265 |
266 | b.HasOne("Identity.Models.ApplicationUser", null)
267 | .WithMany()
268 | .HasForeignKey("UserId")
269 | .OnDelete(DeleteBehavior.Cascade)
270 | .IsRequired();
271 | });
272 |
273 | modelBuilder.Entity("Identity.Models.ApplicationUserToken", b =>
274 | {
275 | b.HasOne("Identity.Models.ApplicationUser", null)
276 | .WithMany()
277 | .HasForeignKey("UserId")
278 | .OnDelete(DeleteBehavior.Cascade)
279 | .IsRequired();
280 | });
281 | #pragma warning restore 612, 618
282 | }
283 | }
284 | }
285 |
--------------------------------------------------------------------------------
/src/Libraries/Identity/Migrations/20201005130141_my_new_identity_migration.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Microsoft.EntityFrameworkCore.Migrations;
3 |
4 | namespace Identity.Migrations
5 | {
6 | public partial class my_new_identity_migration : Migration
7 | {
8 | protected override void Up(MigrationBuilder migrationBuilder)
9 | {
10 | migrationBuilder.EnsureSchema(
11 | name: "Identity");
12 |
13 | migrationBuilder.CreateTable(
14 | name: "Role",
15 | schema: "Identity",
16 | columns: table => new
17 | {
18 | Id = table.Column(nullable: false)
19 | .Annotation("SqlServer:Identity", "1, 1"),
20 | Name = table.Column(maxLength: 256, nullable: true),
21 | NormalizedName = table.Column(maxLength: 256, nullable: true),
22 | ConcurrencyStamp = table.Column(nullable: true),
23 | CreatedDate = table.Column(nullable: true)
24 | },
25 | constraints: table =>
26 | {
27 | table.PrimaryKey("PK_Role", x => x.Id);
28 | });
29 |
30 | migrationBuilder.CreateTable(
31 | name: "User",
32 | schema: "Identity",
33 | columns: table => new
34 | {
35 | Id = table.Column(nullable: false)
36 | .Annotation("SqlServer:Identity", "1, 1"),
37 | UserName = table.Column(maxLength: 256, nullable: true),
38 | NormalizedUserName = table.Column(maxLength: 256, nullable: true),
39 | Email = table.Column(maxLength: 256, nullable: true),
40 | NormalizedEmail = table.Column(maxLength: 256, nullable: true),
41 | EmailConfirmed = table.Column(nullable: false),
42 | PasswordHash = table.Column(nullable: true),
43 | SecurityStamp = table.Column(nullable: true),
44 | ConcurrencyStamp = table.Column(nullable: true),
45 | PhoneNumber = table.Column(nullable: true),
46 | PhoneNumberConfirmed = table.Column(nullable: false),
47 | TwoFactorEnabled = table.Column(nullable: false),
48 | LockoutEnd = table.Column(nullable: true),
49 | LockoutEnabled = table.Column(nullable: false),
50 | AccessFailedCount = table.Column(nullable: false),
51 | FirstName = table.Column(nullable: true),
52 | LastName = table.Column(nullable: true)
53 | },
54 | constraints: table =>
55 | {
56 | table.PrimaryKey("PK_User", x => x.Id);
57 | });
58 |
59 | migrationBuilder.CreateTable(
60 | name: "RoleClaims",
61 | schema: "Identity",
62 | columns: table => new
63 | {
64 | Id = table.Column(nullable: false)
65 | .Annotation("SqlServer:Identity", "1, 1"),
66 | RoleId = table.Column(nullable: false),
67 | ClaimType = table.Column(nullable: true),
68 | ClaimValue = table.Column(nullable: true)
69 | },
70 | constraints: table =>
71 | {
72 | table.PrimaryKey("PK_RoleClaims", x => x.Id);
73 | table.ForeignKey(
74 | name: "FK_RoleClaims_Role_RoleId",
75 | column: x => x.RoleId,
76 | principalSchema: "Identity",
77 | principalTable: "Role",
78 | principalColumn: "Id",
79 | onDelete: ReferentialAction.Cascade);
80 | });
81 |
82 | migrationBuilder.CreateTable(
83 | name: "UserClaims",
84 | schema: "Identity",
85 | columns: table => new
86 | {
87 | Id = table.Column(nullable: false)
88 | .Annotation("SqlServer:Identity", "1, 1"),
89 | UserId = table.Column(nullable: false),
90 | ClaimType = table.Column(nullable: true),
91 | ClaimValue = table.Column(nullable: true)
92 | },
93 | constraints: table =>
94 | {
95 | table.PrimaryKey("PK_UserClaims", x => x.Id);
96 | table.ForeignKey(
97 | name: "FK_UserClaims_User_UserId",
98 | column: x => x.UserId,
99 | principalSchema: "Identity",
100 | principalTable: "User",
101 | principalColumn: "Id",
102 | onDelete: ReferentialAction.Cascade);
103 | });
104 |
105 | migrationBuilder.CreateTable(
106 | name: "UserLogins",
107 | schema: "Identity",
108 | columns: table => new
109 | {
110 | LoginProvider = table.Column(nullable: false),
111 | ProviderKey = table.Column(nullable: false),
112 | ProviderDisplayName = table.Column(nullable: true),
113 | UserId = table.Column(nullable: false)
114 | },
115 | constraints: table =>
116 | {
117 | table.PrimaryKey("PK_UserLogins", x => new { x.LoginProvider, x.ProviderKey });
118 | table.ForeignKey(
119 | name: "FK_UserLogins_User_UserId",
120 | column: x => x.UserId,
121 | principalSchema: "Identity",
122 | principalTable: "User",
123 | principalColumn: "Id",
124 | onDelete: ReferentialAction.Cascade);
125 | });
126 |
127 | migrationBuilder.CreateTable(
128 | name: "UserRoles",
129 | schema: "Identity",
130 | columns: table => new
131 | {
132 | UserId = table.Column(nullable: false),
133 | RoleId = table.Column(nullable: false)
134 | },
135 | constraints: table =>
136 | {
137 | table.PrimaryKey("PK_UserRoles", x => new { x.UserId, x.RoleId });
138 | table.ForeignKey(
139 | name: "FK_UserRoles_Role_RoleId",
140 | column: x => x.RoleId,
141 | principalSchema: "Identity",
142 | principalTable: "Role",
143 | principalColumn: "Id",
144 | onDelete: ReferentialAction.Cascade);
145 | table.ForeignKey(
146 | name: "FK_UserRoles_User_UserId",
147 | column: x => x.UserId,
148 | principalSchema: "Identity",
149 | principalTable: "User",
150 | principalColumn: "Id",
151 | onDelete: ReferentialAction.Cascade);
152 | });
153 |
154 | migrationBuilder.CreateTable(
155 | name: "UserTokens",
156 | schema: "Identity",
157 | columns: table => new
158 | {
159 | UserId = table.Column(nullable: false),
160 | LoginProvider = table.Column(nullable: false),
161 | Name = table.Column(nullable: false),
162 | Value = table.Column(nullable: true)
163 | },
164 | constraints: table =>
165 | {
166 | table.PrimaryKey("PK_UserTokens", x => new { x.UserId, x.LoginProvider, x.Name });
167 | table.ForeignKey(
168 | name: "FK_UserTokens_User_UserId",
169 | column: x => x.UserId,
170 | principalSchema: "Identity",
171 | principalTable: "User",
172 | principalColumn: "Id",
173 | onDelete: ReferentialAction.Cascade);
174 | });
175 |
176 | migrationBuilder.CreateIndex(
177 | name: "RoleNameIndex",
178 | schema: "Identity",
179 | table: "Role",
180 | column: "NormalizedName",
181 | unique: true,
182 | filter: "[NormalizedName] IS NOT NULL");
183 |
184 | migrationBuilder.CreateIndex(
185 | name: "IX_RoleClaims_RoleId",
186 | schema: "Identity",
187 | table: "RoleClaims",
188 | column: "RoleId");
189 |
190 | migrationBuilder.CreateIndex(
191 | name: "EmailIndex",
192 | schema: "Identity",
193 | table: "User",
194 | column: "NormalizedEmail");
195 |
196 | migrationBuilder.CreateIndex(
197 | name: "UserNameIndex",
198 | schema: "Identity",
199 | table: "User",
200 | column: "NormalizedUserName",
201 | unique: true,
202 | filter: "[NormalizedUserName] IS NOT NULL");
203 |
204 | migrationBuilder.CreateIndex(
205 | name: "IX_UserClaims_UserId",
206 | schema: "Identity",
207 | table: "UserClaims",
208 | column: "UserId");
209 |
210 | migrationBuilder.CreateIndex(
211 | name: "IX_UserLogins_UserId",
212 | schema: "Identity",
213 | table: "UserLogins",
214 | column: "UserId");
215 |
216 | migrationBuilder.CreateIndex(
217 | name: "IX_UserRoles_RoleId",
218 | schema: "Identity",
219 | table: "UserRoles",
220 | column: "RoleId");
221 | }
222 |
223 | protected override void Down(MigrationBuilder migrationBuilder)
224 | {
225 | migrationBuilder.DropTable(
226 | name: "RoleClaims",
227 | schema: "Identity");
228 |
229 | migrationBuilder.DropTable(
230 | name: "UserClaims",
231 | schema: "Identity");
232 |
233 | migrationBuilder.DropTable(
234 | name: "UserLogins",
235 | schema: "Identity");
236 |
237 | migrationBuilder.DropTable(
238 | name: "UserRoles",
239 | schema: "Identity");
240 |
241 | migrationBuilder.DropTable(
242 | name: "UserTokens",
243 | schema: "Identity");
244 |
245 | migrationBuilder.DropTable(
246 | name: "Role",
247 | schema: "Identity");
248 |
249 | migrationBuilder.DropTable(
250 | name: "User",
251 | schema: "Identity");
252 | }
253 | }
254 | }
255 |
--------------------------------------------------------------------------------
/src/Libraries/Identity/Migrations/20201027103615_update_identity_migration.Designer.cs:
--------------------------------------------------------------------------------
1 | //
2 | using System;
3 | using Identity.Contexts;
4 | using Microsoft.EntityFrameworkCore;
5 | using Microsoft.EntityFrameworkCore.Infrastructure;
6 | using Microsoft.EntityFrameworkCore.Metadata;
7 | using Microsoft.EntityFrameworkCore.Migrations;
8 | using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
9 |
10 | namespace Identity.Migrations
11 | {
12 | [DbContext(typeof(IdentityContext))]
13 | [Migration("20201027103615_update_identity_migration")]
14 | partial class update_identity_migration
15 | {
16 | protected override void BuildTargetModel(ModelBuilder modelBuilder)
17 | {
18 | #pragma warning disable 612, 618
19 | modelBuilder
20 | .HasDefaultSchema("Identity")
21 | .HasAnnotation("ProductVersion", "3.1.8")
22 | .HasAnnotation("Relational:MaxIdentifierLength", 128)
23 | .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
24 |
25 | modelBuilder.Entity("Identity.Models.ApplicationRole", b =>
26 | {
27 | b.Property("Id")
28 | .ValueGeneratedOnAdd()
29 | .HasColumnType("int")
30 | .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
31 |
32 | b.Property("ConcurrencyStamp")
33 | .IsConcurrencyToken()
34 | .HasColumnType("nvarchar(max)");
35 |
36 | b.Property("CreatedDate")
37 | .HasColumnType("datetime2");
38 |
39 | b.Property("Name")
40 | .HasColumnType("nvarchar(256)")
41 | .HasMaxLength(256);
42 |
43 | b.Property("NormalizedName")
44 | .HasColumnType("nvarchar(256)")
45 | .HasMaxLength(256);
46 |
47 | b.HasKey("Id");
48 |
49 | b.HasIndex("NormalizedName")
50 | .IsUnique()
51 | .HasName("RoleNameIndex")
52 | .HasFilter("[NormalizedName] IS NOT NULL");
53 |
54 | b.ToTable("Role");
55 | });
56 |
57 | modelBuilder.Entity("Identity.Models.ApplicationRoleClaim", b =>
58 | {
59 | b.Property("Id")
60 | .ValueGeneratedOnAdd()
61 | .HasColumnType("int")
62 | .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
63 |
64 | b.Property("ClaimType")
65 | .HasColumnType("nvarchar(max)");
66 |
67 | b.Property("ClaimValue")
68 | .HasColumnType("nvarchar(max)");
69 |
70 | b.Property("RoleId")
71 | .HasColumnType("int");
72 |
73 | b.HasKey("Id");
74 |
75 | b.HasIndex("RoleId");
76 |
77 | b.ToTable("RoleClaims");
78 | });
79 |
80 | modelBuilder.Entity("Identity.Models.ApplicationUser", b =>
81 | {
82 | b.Property("Id")
83 | .ValueGeneratedOnAdd()
84 | .HasColumnType("int")
85 | .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
86 |
87 | b.Property("AccessFailedCount")
88 | .HasColumnType("int");
89 |
90 | b.Property("ConcurrencyStamp")
91 | .IsConcurrencyToken()
92 | .HasColumnType("nvarchar(max)");
93 |
94 | b.Property("Email")
95 | .HasColumnType("nvarchar(256)")
96 | .HasMaxLength(256);
97 |
98 | b.Property("EmailConfirmed")
99 | .HasColumnType("bit");
100 |
101 | b.Property("FirstName")
102 | .HasColumnType("nvarchar(max)");
103 |
104 | b.Property("LastName")
105 | .HasColumnType("nvarchar(max)");
106 |
107 | b.Property("LockoutEnabled")
108 | .HasColumnType("bit");
109 |
110 | b.Property("LockoutEnd")
111 | .HasColumnType("datetimeoffset");
112 |
113 | b.Property("NormalizedEmail")
114 | .HasColumnType("nvarchar(256)")
115 | .HasMaxLength(256);
116 |
117 | b.Property("NormalizedUserName")
118 | .HasColumnType("nvarchar(256)")
119 | .HasMaxLength(256);
120 |
121 | b.Property("PasswordHash")
122 | .HasColumnType("nvarchar(max)");
123 |
124 | b.Property("PhoneNumber")
125 | .HasColumnType("nvarchar(max)");
126 |
127 | b.Property("PhoneNumberConfirmed")
128 | .HasColumnType("bit");
129 |
130 | b.Property("SecurityStamp")
131 | .HasColumnType("nvarchar(max)");
132 |
133 | b.Property("TwoFactorEnabled")
134 | .HasColumnType("bit");
135 |
136 | b.Property("UserName")
137 | .HasColumnType("nvarchar(256)")
138 | .HasMaxLength(256);
139 |
140 | b.HasKey("Id");
141 |
142 | b.HasIndex("NormalizedEmail")
143 | .HasName("EmailIndex");
144 |
145 | b.HasIndex("NormalizedUserName")
146 | .IsUnique()
147 | .HasName("UserNameIndex")
148 | .HasFilter("[NormalizedUserName] IS NOT NULL");
149 |
150 | b.ToTable("User");
151 | });
152 |
153 | modelBuilder.Entity("Identity.Models.ApplicationUserClaim", b =>
154 | {
155 | b.Property("Id")
156 | .ValueGeneratedOnAdd()
157 | .HasColumnType("int")
158 | .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
159 |
160 | b.Property("ClaimType")
161 | .HasColumnType("nvarchar(max)");
162 |
163 | b.Property("ClaimValue")
164 | .HasColumnType("nvarchar(max)");
165 |
166 | b.Property