145 Commits
test ... main

Author SHA1 Message Date
c4ef564d71 Fixing sonarcloud issues 2025-06-22 22:55:19 +02:00
9e95ad1cc8 Fixing sonarcloud issues 2025-06-22 22:00:12 +02:00
4c3aa30cbb Fixing sonarcloud issues 2025-06-21 17:42:04 +02:00
Caterina Simona Pastore
54a5106314 Sprint 8 (#43) 2025-06-21 01:11:02 +02:00
87adaffa3e Minor fixes for sonarcloud 2025-06-21 01:00:21 +02:00
fa4f1c0791 Added new tests 2025-06-21 00:51:58 +02:00
a6193c3c94 Adding tests for CRUD operations on users 2025-06-20 20:37:40 +02:00
12b4a4d0c8 Removed obsolete tests 2025-06-19 23:37:25 +02:00
63fab9d827 Removing duplicated lines 2025-06-19 23:28:28 +02:00
e1d1381a5c Adding tests for ValidationActionFilter 2025-06-19 23:14:43 +02:00
2d7db3d919 Minor fixes for model validation 2025-06-19 20:48:17 +02:00
73043970a8 Fixing sonarcloud issues 2025-06-19 20:08:34 +02:00
5c1eacd85e Fixing sonarcloud issues 2025-06-19 19:45:02 +02:00
e03db76496 Fixing sonarcloud issues 2025-06-19 19:29:05 +02:00
1fc8e6cc1c Fixing sonarcloud issues 2025-06-19 00:53:52 +02:00
8bc50f8135 Removing duplicated lines - wip 2025-06-19 00:30:16 +02:00
e1a249c07a Adding crud operations for users 2025-06-17 23:08:21 +02:00
8986e3d77e Minor fixes 2025-06-17 21:11:35 +02:00
56a7e76785 Fixed password generation 2025-06-17 21:01:57 +02:00
061ce4cb3d Fixed issues "Do not negate boolean assertions, instead use the opposite assertion" 2025-06-17 19:58:02 +02:00
11a9696bdd Fixing security hotspots + issues 2025-06-17 19:47:56 +02:00
ad1909ef57 Minor fixes 2025-06-17 00:11:14 +02:00
1877c29e68 Fixing user password generation/validation - wip 2025-06-17 00:01:29 +02:00
14d9b45413 Added strong password validation 2025-06-16 22:43:02 +02:00
a4b8458542 Changed target branch for dependabot 2025-05-28 00:58:17 +02:00
Caterina Simona Pastore
c950556104 Sprint 7 - Dependabot (#42) 2025-05-28 00:57:28 +02:00
118a9bb6e4 Removed versioning-strategy to avoid error
The property '#/updates/0/' contains additional properties ["versioning-strategy"] outside of the schema when none are allowed
2025-05-28 00:50:57 +02:00
a3938fa5f0 Moved dependabot.yml to correct folder 2025-05-28 00:42:52 +02:00
ca8fd67428 Changed target branch 2025-05-28 00:41:08 +02:00
fbd09b56c8 Adding dependabot.yml to enable version updates 2025-05-28 00:37:12 +02:00
Caterina Simona Pastore
79549bea05 Sprint 5 (#28) 2025-05-28 00:10:38 +02:00
Caterina Simona Pastore
ac20664446 Merged roles branch 2025-03-26 23:52:19 +01:00
c9390479bb Adding tests 2025-03-26 23:43:44 +01:00
9f595779ee Fixed build failed 2025-03-26 22:45:18 +01:00
fa1ee76d35 Added in-memory database for tests 2025-03-26 22:37:50 +01:00
82d5ede421 Fixing coverage - user 2025-03-23 23:43:45 +01:00
b7398fd910 tests 2025-03-23 23:34:54 +01:00
030882f3e1 Fixing test coverage for CreateUserAsync 2025-03-23 22:37:10 +01:00
9d2b2405d5 Changed CreateUserAsync to avoid silent transaction failure - 2 2025-03-23 22:05:32 +01:00
39e856f522 Changed await 2025-03-23 20:56:48 +01:00
64f4cdc85e Changed CreateUserAsync to avoid silent transaction failure 2025-03-23 20:46:11 +01:00
5d104d5dc8 Revert "Fixing coverage"
This reverts commit 61f7504e66.
2025-03-23 20:34:45 +01:00
8b5b3a198f Revert "Fixing coverage"
This reverts commit e5a3e6fdcf.
2025-03-23 20:19:31 +01:00
e5a3e6fdcf Fixing coverage 2025-03-23 19:50:32 +01:00
61f7504e66 Fixing coverage 2025-03-23 19:34:32 +01:00
de2c914a0c Fixing coverage 2025-03-23 19:17:01 +01:00
0e50393455 Revert "Tests with mock service"
This reverts commit b1ad6c942b.
2025-03-23 19:09:53 +01:00
d92d1c7de9 Revert "Finxing coverage"
This reverts commit ad9633ca8b.
2025-03-23 19:09:46 +01:00
ad9633ca8b Finxing coverage 2025-03-23 19:02:05 +01:00
b1ad6c942b Tests with mock service 2025-03-23 18:46:21 +01:00
fe010e2baa Revert "Fixing coverage"
This reverts commit a8e51fa6b5.
2025-03-20 23:43:27 +01:00
a8e51fa6b5 Fixing coverage 2025-03-20 23:34:56 +01:00
764f0a1511 Restored role deletion in UserService_Tests 2025-03-20 23:10:50 +01:00
86cf6f2a27 Fixing coverage 2025-03-20 23:01:37 +01:00
8f98ee5954 Fixing coverage 2025-03-20 22:54:20 +01:00
cfe877a066 Fixing coverage 2025-03-20 22:42:19 +01:00
422bbf24fb Fixing coverage 2025-03-20 22:32:10 +01:00
aefaefd64f Fixing coverage 2025-03-20 22:18:31 +01:00
caa2cf2035 Fixing coverage 2025-03-20 22:14:09 +01:00
a4e3b0666b Fixing coverage 2025-03-20 22:02:47 +01:00
ae6cb2b2a4 Fixing user service tests 2025-03-20 21:45:34 +01:00
fdf97c7c42 Fixing tests 2025-03-18 00:11:18 +01:00
f27f7733f8 Fixing issues 2025-03-17 23:52:02 +01:00
db37ebbdce Adding tests for users and roles 2025-03-17 23:34:52 +01:00
e7b3acb91e Fixing tests for UserController 2025-03-17 20:30:11 +01:00
5bc75de87c Adding tests for UserController 2025-03-17 00:33:19 +01:00
f6cd629fe2 Minor fixes for CreateUser 2025-03-16 23:26:15 +01:00
18e713153b Adding role creation during startup + minor fixes in tests 2025-03-16 22:41:44 +01:00
7f5178883d Fixing issues 2025-03-15 17:44:39 +01:00
bd175da738 Fixed JwtAuthorizationAttribute + tests 2025-03-15 17:31:13 +01:00
962de4df9e Adding index and max length to user tabel + minor fixes 2025-03-13 00:53:08 +01:00
61b9c732bc Adding user CRUD methods and controller + automapper 2025-03-13 00:19:29 +01:00
0b354988fd Adding SHA256 password encryption and password verify 2025-03-11 23:36:49 +01:00
78911eb877 Minor fixes 2025-03-04 00:55:30 +01:00
f73fe748ed Code refactoring + tests 2025-03-04 00:42:20 +01:00
a0c93ea587 Adding JwtService tests + fixed issues 2025-03-03 21:54:03 +01:00
433e97938d Added UserService tests 2025-03-03 21:45:22 +01:00
67affa8b82 Added tests for AuthService 2025-03-03 20:27:17 +01:00
b2619f6acc Adding tests on models 2025-03-02 23:36:21 +01:00
e105e4731d Testing exception 2025-03-02 22:51:50 +01:00
98dbf0fdde Testing invalid model 2025-03-02 22:34:10 +01:00
08182dc9ef Added NotFound test 2025-03-02 20:54:32 +01:00
505a2cb6cc Fixes + restored ModelState.IsValid 2025-03-02 20:19:15 +01:00
114e7c7c50 Improving code coverage - wip 2025-03-02 17:59:12 +01:00
1969852a2c Minor fix 2025-03-01 21:29:05 +01:00
3858ec20c4 Fixing issues 2025-03-01 21:21:19 +01:00
a83c9c104a Restored exclusions from coverage 2025-03-01 20:52:27 +01:00
0bf3e081fb Removed unused Moq package from MainProject 2025-03-01 20:48:05 +01:00
c9382e9cde removed double quote 2025-03-01 20:43:52 +01:00
c2df8a545d Removed exclusions from coverage 2025-03-01 20:34:37 +01:00
c194a49170 Fixed failing test 2025-03-01 20:05:56 +01:00
70bc34b117 Removed space 2025-03-01 20:01:17 +01:00
5591f6516b Adding AuthController tests - wip 2025-03-01 19:53:09 +01:00
d0cb4666d4 Fixing issues 2025-03-01 17:46:05 +01:00
7321ab2901 Fixing issues 2025-02-27 00:28:33 +01:00
fbf5ef8c16 Adding authentication and authorization flow 2025-02-27 00:12:41 +01:00
7926cf2f65 Minor fixes to remove issues 2025-02-26 22:52:27 +01:00
76779afd2e Adding authentication and authorization flow 2025-02-26 22:23:15 +01:00
176f149be3 Merge branch 'connections' 2025-02-21 18:43:23 +01:00
aaea2c30a5 Excluding dbcontext models files from analysis 2025-02-21 18:20:59 +01:00
3ed9a15d09 Excluding database models files from analysis 2025-02-21 18:06:53 +01:00
5ef25d601f Excluding migrations files from analysis 2025-02-21 13:55:34 +01:00
810f23f814 Adding new tests 2025-02-21 13:21:06 +01:00
8d8a7a4c77 Updated README 2024-11-30 01:01:06 +01:00
b26c553d12 Fixed multiple db contexts 2024-11-30 00:26:05 +01:00
0ab8d7f7d1 Fixing connection strings - wip 2024-11-29 22:23:40 +01:00
998a4d5ab9 Adding database configuration - wip 2024-09-05 01:52:07 +02:00
b638c48104 Fixed launch.json 2024-09-04 17:17:16 +02:00
ada6967234 Minor fixes + changed debug launch.json file 2024-09-04 15:51:56 +02:00
286a9eff72 Updated gitignore 2024-05-14 21:56:09 +02:00
ebf8237be6 Fixing dotnet coverage + minor fixes 2024-05-14 19:47:25 +02:00
6c34f3e380 Fixing coverage - 11 2024-05-14 00:27:25 +02:00
fb578026eb Fixing coverage - 10 2024-05-13 21:43:49 +02:00
57391d3e51 Fixing coverage - 9 2024-05-13 01:13:09 +02:00
277d6b99fd Fixing coverage - 8 2024-05-13 00:58:40 +02:00
bbfac5eb07 Changed method name 2024-05-13 00:27:36 +02:00
4663e10f96 Revert "Fixing coverage - 7"
This reverts commit b393abe948.
2024-05-13 00:26:17 +02:00
b393abe948 Fixing coverage - 7 2024-05-13 00:21:21 +02:00
3e4372c1b7 Removed unuseful configuration from RootController 2024-05-12 23:53:15 +02:00
6b53139fd4 Fixing coverage - 6 2024-05-12 23:47:10 +02:00
e941649d75 Fixing coverage - 5 2024-05-12 23:19:54 +02:00
3808adb6db Fixing coverage - 4 2024-05-12 22:56:15 +02:00
8ee14255ce Fixing coverage - 3 2024-05-12 21:50:23 +02:00
7c324e9647 Fixing coverage - 2 2024-05-12 19:54:27 +02:00
5d4e351982 Fixing coverage 2024-05-12 19:36:23 +02:00
1739961bc2 Added basic README + minor fixes 2024-05-12 17:57:27 +02:00
567e5abf07 Fixing SonarCloud integration - 10 2024-05-05 15:49:25 +02:00
c27971609a Fixing SonarCloud integration - 9 2024-05-05 03:40:20 +02:00
41251bb110 Fixing SonarCloud integration - 8 2024-05-05 02:56:44 +02:00
f53e289f51 Fixing pipeline 2024-05-05 02:48:10 +02:00
23ca30f084 Fixing SonarCloud integration - 7 2024-05-05 02:44:46 +02:00
a1a1a667b3 Fixing SonarCloud integration - 6 2024-05-05 02:39:56 +02:00
12d56ebcc1 Fixing SonarCloud integration - 5 2024-05-05 02:37:59 +02:00
54be2c8732 Fixing SonarCloud integration - 4 2024-05-05 02:13:08 +02:00
af470ea869 Fixing SonarCloud integration - 3 2024-05-04 20:12:21 +02:00
1446803fb8 Fixing SonarCloud integration - 2 2024-05-04 20:05:53 +02:00
0929ca2d94 Fixing SonarCloud integration 2024-05-04 19:52:45 +02:00
39b7f4f3b3 Fixing SonarCloud integration + fixing CodeSmells - 2 2024-05-04 19:29:44 +02:00
79b66cb8b4 Fixing SonarCloud integration + fixing CodeSmells 2024-05-04 18:47:58 +02:00
708966fcf8 Various changes (Controller and test)
- Added RootController
- Added new methods in BaseController
- Added BaseResponse
- Changed Program structure
- Added first basic test for Program
2024-05-04 17:51:11 +02:00
d3ba42e57a Adding base controller 2024-04-07 20:04:41 +02:00
716d75a072 Added base NLog configuration 2024-04-07 17:50:11 +02:00
61f0dab8df Removed unnecessary check for null 2024-04-07 17:03:33 +02:00
e78e5b205f Merge branch 'test' 2024-04-07 16:55:28 +02:00
ddb5223572 Adding test configuration 2024-03-10 20:36:07 +01:00
146 changed files with 14270 additions and 173 deletions

15
.editorconfig Normal file
View File

@@ -0,0 +1,15 @@
# top-most EditorConfig file
root = true
# Core EditorConfig properties
[*]
indent_style = space
indent_size = 4
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
csharp_prefer_braced_block = true:suggestion
csharp_preserve_single_line_blocks = true
csharp_style_expression_bodied_methods = when_on_single_line:suggestion

15
.github/dependabot.yml vendored Normal file
View File

@@ -0,0 +1,15 @@
version: 2
updates:
- package-ecosystem: "nuget"
directory: "/MainProject"
schedule:
interval: "daily"
open-pull-requests-limit: 5
target-branch: "main"
- package-ecosystem: "nuget"
directory: "/MainProject.Tests"
schedule:
interval: "daily"
open-pull-requests-limit: 5
target-branch: "main"

View File

@@ -37,12 +37,22 @@ jobs:
run: |
New-Item -Path .\.sonar\scanner -ItemType Directory
dotnet tool update dotnet-sonarscanner --tool-path .\.sonar\scanner
- name: Install dotnet-coverage tool
run: dotnet tool install --global dotnet-coverage
- name: Build and analyze
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
SQLSERVER_DB_SERVER: ${{ secrets.SQLSERVER_DB_SERVER }}
MONGO_DB_SERVER: ${{ secrets.MONGO_DB_SERVER }}
shell: powershell
run: |
.\.sonar\scanner\dotnet-sonarscanner begin /k:"csimonapastore_BasicDotnetTemplate" /o:"csimonapastore-github" /d:sonar.token="${{ secrets.SONAR_TOKEN }}" /d:sonar.host.url="https://sonarcloud.io"
dotnet build
.\.sonar\scanner\dotnet-sonarscanner begin /k:"csimonapastore_BasicDotnetTemplate" /o:"csimonapastore-github" /d:sonar.token="${{ secrets.SONAR_TOKEN }}" /d:sonar.host.url="https://sonarcloud.io" /d:sonar.cs.vscoveragexml.reportsPaths=coverage.xml /d:sonar.exclusions="**/Migrations/**.cs, **/Models/Database/**.cs, **/Core/Database/**.cs"
dotnet clean
dotnet restore
dotnet build --no-incremental
dotnet-coverage collect "dotnet test" -f xml -o "coverage.xml"
dotnet test ./MainProject.Tests/MainProject.Tests.csproj --collect "Code Coverage" --results-directory "./TestResults"
Get-Content -Path "coverage.xml"
.\.sonar\scanner\dotnet-sonarscanner end /d:sonar.token="${{ secrets.SONAR_TOKEN }}"

4
.gitignore vendored
View File

@@ -1,3 +1,5 @@
**/obj
**/bin
appsettings.*.json
**/appsettings.*.json
**/coverage*.xml
.fake

31
.vscode/launch.json vendored
View File

@@ -2,18 +2,13 @@
"version": "0.2.0",
"configurations": [
{
// Use IntelliSense to find out which attributes exist for C# debugging
// Use hover for the description of the existing attributes
// For further information visit https://github.com/dotnet/vscode-csharp/blob/main/debugger-launchjson.md
"name": ".NET Core Launch (console)",
"name": ".NET Rest Api - Watch",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build",
// If you have changed target frameworks, make sure to update the program path.
"program": "${workspaceFolder}/bin/Debug/net8.0/BasicDotnetTemplate.dll",
"program": "${workspaceFolder}/MainProject/bin/Debug/net8.0/MainProject.dll",
"args": [],
"cwd": "${workspaceFolder}",
// For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console
"console": "internalConsole",
"stopAtEntry": false,
"env": {
@@ -22,17 +17,31 @@
"ASPNETCORE_DETAILEDERRORS": "1",
"ASPNETCORE_SHUTDOWNTIMEOUTSECONDS": "3"
},
// Enable launching a web browser when ASP.NET Core starts. For more information: https://aka.ms/VSCode-CS-LaunchJson-WebBrowser
"serverReadyAction": {
"action": "openExternally",
"pattern": "\\bNow listening on:\\s+(https?://\\S+)",
"uriFormat": "%s/swagger"
},
},
"postDebugTask": "watch"
},
{
"name": ".NET Core Attach",
"type": "coreclr",
"request": "attach"
}
]
}
],
"tasks": {
"label": "watch",
"type": "shell",
"command": "dotnet",
"args": [
"watch",
"run"
],
"problemMatcher": "$msCompile",
"group": {
"kind": "build",
"isDefault": true
}
}
}

6
.vscode/tasks.json vendored
View File

@@ -7,7 +7,7 @@
"type": "process",
"args": [
"build",
"${workspaceFolder}/BasicDotnetTemplate.csproj",
"${workspaceFolder}/BasicDotnetTemplate.sln",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary;ForceNoAlign"
],
@@ -19,7 +19,7 @@
"type": "process",
"args": [
"publish",
"${workspaceFolder}/BasicDotnetTemplate.csproj",
"${workspaceFolder}/BasicDotnetTemplate.sln",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary;ForceNoAlign"
],
@@ -33,7 +33,7 @@
"watch",
"run",
"--project",
"${workspaceFolder}/BasicDotnetTemplate.csproj"
"${workspaceFolder}/BasicDotnetTemplate.sln"
],
"problemMatcher": "$msCompile"
}

View File

@@ -1,24 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" />
<PackageReference Include="NLog" Version="5.2.8" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
<PackageReference Include="Swashbuckle.AspNetCore.Annotations" Version="6.5.0" />
<PackageReference Include="Swashbuckle.AspNetCore.Filters" Version="8.0.0" />
<PackageReference Include="Swashbuckle.AspNetCore.Filters.Abstractions" Version="8.0.0" />
<PackageReference Include="Swashbuckle.AspNetCore.Newtonsoft" Version="6.5.0" />
<PackageReference Include="Swashbuckle.AspNetCore.Swagger" Version="6.5.0" />
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerGen" Version="6.5.0" />
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerUI" Version="6.5.0" />
</ItemGroup>
</Project>

28
BasicDotnetTemplate.sln Normal file
View File

@@ -0,0 +1,28 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.0.31903.59
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MainProject", "MainProject\MainProject.csproj", "{5BC4F94C-35BC-4436-A107-9D85E53A9E84}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MainProject.Tests", "MainProject.Tests\MainProject.Tests.csproj", "{A672CB00-DC99-4847-A384-B857C5E69301}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{5BC4F94C-35BC-4436-A107-9D85E53A9E84}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5BC4F94C-35BC-4436-A107-9D85E53A9E84}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5BC4F94C-35BC-4436-A107-9D85E53A9E84}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5BC4F94C-35BC-4436-A107-9D85E53A9E84}.Release|Any CPU.Build.0 = Release|Any CPU
{A672CB00-DC99-4847-A384-B857C5E69301}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A672CB00-DC99-4847-A384-B857C5E69301}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A672CB00-DC99-4847-A384-B857C5E69301}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A672CB00-DC99-4847-A384-B857C5E69301}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal

View File

@@ -0,0 +1,31 @@
{
"PermissionInfos": [
{
"System": "base",
"RolePermissionModuleOperations": [
{
"Module": "roles",
"Operations": [
{ "Operation": "create", "Roles": [] },
{ "Operation": "read", "Roles": [] },
{ "Operation": "update", "Roles": [] },
{ "Operation": "delete", "Roles": [] },
{ "Operation": "list", "Roles": [] },
{ "Operation": "use", "Roles": [] }
]
},
{
"Module": "users",
"Operations": [
{ "Operation": "create", "Roles": [] },
{ "Operation": "read", "Roles": [] },
{ "Operation": "update", "Roles": [] },
{ "Operation": "delete", "Roles": [] },
{ "Operation": "list", "Roles": [] },
{ "Operation": "use", "Roles": [] }
]
}
]
]
}

View File

@@ -0,0 +1,31 @@
{
"PermissionInfos": [
{
"System": "base",
"RolePermissionModuleOperations": [
{
"Module": "roles",
"Operations": [
{ "Operation": "create", "Roles": ["Admin"] },
{ "Operation": "read", "Roles": [] },
{ "Operation": "update", "Roles": ["Admin"] },
{ "Operation": "delete", "Roles": ["Admin"] },
{ "Operation": "list", "Roles": [] },
{ "Operation": "use", "Roles": [] }
]
},
{
"Module": "users",
"Operations": [
{ "Operation": "create", "Roles": [] },
{ "Operation": "read", "Roles": [] },
{ "Operation": "update", "Roles": [] },
{ "Operation": "delete", "Roles": [] },
{ "Operation": "list", "Roles": [] }
]
}
]
}
]
}

View File

@@ -0,0 +1,154 @@
using System;
using System.Reflection;
using System.Net;
using System.Net.Http;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Infrastructure;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Microsoft.Extensions.Configuration;
using Moq;
using Newtonsoft.Json;
using BasicDotnetTemplate.MainProject;
using BasicDotnetTemplate.MainProject.Controllers;
using BasicDotnetTemplate.MainProject.Services;
using BasicDotnetTemplate.MainProject.Models.Api.Response;
using BasicDotnetTemplate.MainProject.Models.Settings;
using BasicDotnetTemplate.MainProject.Models.Api.Request.Auth;
using BasicDotnetTemplate.MainProject.Models.Api.Data.Auth;
using BasicDotnetTemplate.MainProject.Models.Api.Common.User;
using BasicDotnetTemplate.MainProject.Models.Api.Common.Role;
using DatabaseSqlServer = BasicDotnetTemplate.MainProject.Models.Database.SqlServer;
using BasicDotnetTemplate.MainProject.Models.Api.Response.Auth;
using Microsoft.AspNetCore.Http;
namespace BasicDotnetTemplate.MainProject.Tests;
[TestClass]
public class AuthController_Tests
{
[TestMethod]
public void AuthController_NullConfiguration()
{
Environment.SetEnvironmentVariable("ASPNETCORE_ENVIRONMENT", "Development");
var exception = true;
try
{
var authServiceMock = new Mock<IAuthService>();
_ = new AuthController(null, authServiceMock.Object);
exception = false;
Assert.Fail($"This test should not pass as configuration is null");
}
catch (Exception)
{
Assert.IsTrue(exception);
}
}
[TestMethod]
public async Task AuthenticateAsync_Should_Return_200_When_Successful()
{
IConfiguration configuration = TestUtils.CreateConfiguration();
var authServiceMock = new Mock<IAuthService>();
var controller = new AuthController(configuration, authServiceMock.Object);
DatabaseSqlServer.User user = ModelsInit.CreateUser();
AuthenticatedUser authenticatedUser = new AuthenticatedUser(user);
var request = new AuthenticateRequest { Data = new AuthenticateRequestData { Email = "user", Password = "pass" } };
authServiceMock.Setup(s => s.AuthenticateAsync(It.IsAny<AuthenticateRequestData>())).ReturnsAsync(authenticatedUser);
ObjectResult response = (ObjectResult)(await controller.AuthenticateAsync(request));
if (response != null && response.Value != null)
{
Assert.AreEqual(StatusCodes.Status200OK, response.StatusCode);
var result = (BaseResponse<object>)response.Value;
if (result != null)
{
Assert.AreEqual(StatusCodes.Status200OK, result.Status);
Assert.IsInstanceOfType(result.Data, typeof(AuthenticatedUser));
}
else
{
Assert.Fail($"Result value is null");
}
}
else
{
Assert.Fail($"Response value is null");
}
}
[TestMethod]
public async Task AuthenticateAsync_NotFound()
{
IConfiguration configuration = TestUtils.CreateConfiguration();
var authServiceMock = new Mock<IAuthService>();
var controller = new AuthController(configuration, authServiceMock.Object);
var request = new AuthenticateRequest
{
Data = new AuthenticateRequestData()
{
Email = "d2ejdI1f4GYpq2kTB1nmeQkZXqR3QSxH8Yqkl7iv7zgfQ13qG/0dUUsreG/WGHWRBE5mVWaV43A=",
Password = "d2ejdI1f4GYpq2kTB1nmeQkZXqR3QSxH8Yqkl7iv7zgfQ13qG/0dUUsreG/WGHWRBE5mVWaV43A="
}
};
AuthenticatedUser? authenticatedUser = null;
authServiceMock.Setup(s => s.AuthenticateAsync(It.IsAny<AuthenticateRequestData>())).ReturnsAsync(authenticatedUser);
NotFoundResult response = (NotFoundResult)(await controller.AuthenticateAsync(request));
Assert.IsInstanceOfType(response, typeof(NotFoundResult));
if (response != null)
{
Assert.AreEqual(StatusCodes.Status404NotFound, response.StatusCode);
}
else
{
Assert.Fail($"Response is null");
}
}
[TestMethod]
public async Task AuthenticateAsync_Exception()
{
IConfiguration configuration = TestUtils.CreateConfiguration();
var authServiceMock = new Mock<IAuthService>();
var controller = new AuthController(configuration, authServiceMock.Object);
var request = new AuthenticateRequest
{
Data = new AuthenticateRequestData { Email = "user", Password = "pass" }
};
authServiceMock.Setup(s => s.AuthenticateAsync(It.IsAny<AuthenticateRequestData>())).ThrowsAsync(new Exception("Unexpected error"));
ObjectResult response = (ObjectResult)(await controller.AuthenticateAsync(request));
Assert.IsInstanceOfType(response, typeof(ObjectResult));
if (response != null && response.Value != null)
{
Assert.AreEqual(StatusCodes.Status500InternalServerError, response.StatusCode);
var result = (BaseResponse<object>)response.Value;
if (result != null)
{
Assert.AreEqual(StatusCodes.Status500InternalServerError, result.Status);
Assert.AreEqual("Something went wrong. Unexpected error", result.Message);
}
else
{
Assert.Fail($"Result value is null");
}
}
else
{
Assert.Fail($"Response is null");
}
}
}

View File

@@ -0,0 +1,670 @@
using System;
using System.Reflection;
using System.Net;
using System.Net.Http;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Infrastructure;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Microsoft.Extensions.Configuration;
using Moq;
using BasicDotnetTemplate.MainProject.Controllers;
using BasicDotnetTemplate.MainProject.Services;
using BasicDotnetTemplate.MainProject.Models.Api.Response;
using BasicDotnetTemplate.MainProject.Models.Api.Common.Role;
using DatabaseSqlServer = BasicDotnetTemplate.MainProject.Models.Database.SqlServer;
using Microsoft.AspNetCore.Http;
using BasicDotnetTemplate.MainProject.Models.Api.Request.Role;
using BasicDotnetTemplate.MainProject.Models.Api.Data.Role;
using BasicDotnetTemplate.MainProject.Models.Database.SqlServer;
using Newtonsoft.Json;
namespace BasicDotnetTemplate.MainProject.Tests;
[TestClass]
public class RoleController_Tests
{
private Mock<IRoleService>? _roleServiceMock;
private RoleController? _roleController;
[TestInitialize]
public void Setup()
{
IConfiguration configuration = TestUtils.CreateConfiguration();
_roleServiceMock = new Mock<IRoleService>();
_roleController = new RoleController(configuration, _roleServiceMock.Object);
}
[TestMethod]
public void RoleController_NullConfiguration()
{
Environment.SetEnvironmentVariable("ASPNETCORE_ENVIRONMENT", "Development");
var exception = true;
try
{
var roleServiceMock = new Mock<IRoleService>();
_ = new RoleController(null, roleServiceMock.Object);
exception = false;
Assert.Fail($"This test should not pass as configuration is null");
}
catch (Exception)
{
Assert.IsTrue(exception);
}
}
#region "GET"
[TestMethod]
public async Task GetRoleByGuidAsync_Should_Return_200_When_Successful()
{
if (_roleController == null)
{
Assert.Fail($"_roleController is null");
}
var guid = Guid.NewGuid().ToString();
DatabaseSqlServer.Role role = ModelsInit.CreateRole();
_roleServiceMock?.Setup(s => s.GetRoleByGuidAsync(It.IsAny<string>())).ReturnsAsync(role);
ObjectResult response = (ObjectResult)(await _roleController.GetRoleByGuidAsync(guid));
if (response != null && response.Value != null)
{
Assert.AreEqual(StatusCodes.Status200OK, response.StatusCode);
var result = (BaseResponse<object>)response.Value;
if (result != null)
{
Assert.AreEqual(StatusCodes.Status200OK, result.Status);
Assert.IsInstanceOfType(result.Data, typeof(RoleDto));
}
else
{
Assert.Fail($"Result value is null");
}
}
else
{
Assert.Fail($"Response value is null");
}
}
[TestMethod]
public async Task GetRoleByGuidAsync_NotFound()
{
if (_roleController == null)
{
Assert.Fail($"_roleController is null");
}
var guid = Guid.NewGuid().ToString();
DatabaseSqlServer.Role? role = null;
_roleServiceMock?.Setup(s => s.GetRoleByGuidAsync(It.IsAny<string>())).ReturnsAsync(role);
NotFoundResult response = (NotFoundResult)(await _roleController.GetRoleByGuidAsync(guid));
Assert.IsInstanceOfType(response, typeof(NotFoundResult));
if (response != null)
{
Assert.AreEqual(StatusCodes.Status404NotFound, response.StatusCode);
}
else
{
Assert.Fail($"Response is null");
}
}
[TestMethod]
public async Task GetRoleByGuidAsync_Exception()
{
if (_roleController == null)
{
Assert.Fail($"_roleController is null");
}
var guid = Guid.NewGuid().ToString();
_roleServiceMock?.Setup(s => s.GetRoleByGuidAsync(It.IsAny<string>())).ThrowsAsync(new Exception("Unexpected error"));
ObjectResult response = (ObjectResult)(await _roleController.GetRoleByGuidAsync(guid));
Assert.IsInstanceOfType(response, typeof(ObjectResult));
if (response != null && response.Value != null)
{
Assert.AreEqual(StatusCodes.Status500InternalServerError, response.StatusCode);
var result = (BaseResponse<object>)response.Value;
if (result != null)
{
Assert.AreEqual(StatusCodes.Status500InternalServerError, result.Status);
Assert.AreEqual("Something went wrong. Unexpected error", result.Message);
}
else
{
Assert.Fail($"Result value is null");
}
}
else
{
Assert.Fail($"Response is null");
}
}
#endregion
#region "CREATE"
[TestMethod]
public async Task CreateRoleAsync_Should_Return_200_When_Successful()
{
if (_roleController == null)
{
Assert.Fail($"_roleController is null");
}
if (_roleServiceMock == null)
{
Assert.Fail($"_roleServiceMock is null");
}
DatabaseSqlServer.Role role = ModelsInit.CreateRole();
CreateRoleRequest request = new CreateRoleRequest()
{
Data = new CreateRoleRequestData()
{
Name = "RoleTest",
IsNotEditable = true
}
};
_roleServiceMock?.Setup(s => s.CheckIfNameIsValid(It.IsAny<string>(), It.IsAny<string>())).ReturnsAsync(true);
_roleServiceMock?.Setup(s => s.CreateRoleAsync(request.Data)).ReturnsAsync(role);
ObjectResult response = (ObjectResult)(await _roleController.CreateRoleAsync(request));
if (response != null && response.Value != null)
{
Assert.AreEqual(StatusCodes.Status200OK, response.StatusCode);
var result = (BaseResponse<object>)response.Value;
if (result != null)
{
Assert.AreEqual(StatusCodes.Status200OK, result.Status);
Assert.IsInstanceOfType(result.Data, typeof(RoleDto));
}
else
{
Assert.Fail($"Result value is null");
}
}
else
{
Assert.Fail($"Response value is null");
}
}
[TestMethod]
public async Task CreateRoleAsync_InvalidName()
{
if (_roleController == null)
{
Assert.Fail($"_roleController is null");
}
CreateRoleRequest request = new CreateRoleRequest()
{
Data = new CreateRoleRequestData()
{
Name = "RoleTest",
IsNotEditable = true
}
};
_roleServiceMock?.Setup(s => s.CheckIfNameIsValid(It.IsAny<string>(), It.IsAny<string>())).ReturnsAsync(false);
ObjectResult response = (ObjectResult)(await _roleController.CreateRoleAsync(request));
if (response != null && response.Value != null)
{
Assert.AreEqual(StatusCodes.Status400BadRequest, response.StatusCode);
var result = (BaseResponse<object>)response.Value;
if (result != null)
{
Assert.AreEqual(StatusCodes.Status400BadRequest, result.Status);
Assert.AreEqual("Invalid name", result.Message);
}
else
{
Assert.Fail($"Result value is null");
}
}
else
{
Assert.Fail($"Response value is null");
}
}
[TestMethod]
public async Task CreateRoleAsync_NotCreated()
{
if (_roleController == null)
{
Assert.Fail($"_roleController is null");
}
if (_roleServiceMock == null)
{
Assert.Fail($"_roleServiceMock is null");
}
DatabaseSqlServer.Role role = ModelsInit.CreateRole();
DatabaseSqlServer.Role? expectedRole = null;
CreateRoleRequest request = new CreateRoleRequest()
{
Data = new CreateRoleRequestData()
{
Name = "RoleTest",
IsNotEditable = true
}
};
_roleServiceMock?.Setup(s => s.CheckIfNameIsValid(It.IsAny<string>(), It.IsAny<string>())).ReturnsAsync(true);
_roleServiceMock?.Setup(s => s.CreateRoleAsync(request.Data)).ReturnsAsync(expectedRole);
ObjectResult response = (ObjectResult)(await _roleController.CreateRoleAsync(request));
if (response != null && response.Value != null)
{
Assert.AreEqual(StatusCodes.Status400BadRequest, response.StatusCode);
var result = (BaseResponse<object>)response.Value;
if (result != null)
{
Assert.AreEqual(StatusCodes.Status400BadRequest, result.Status);
Assert.AreEqual("Not created", result.Message);
}
else
{
Assert.Fail($"Result value is null");
}
}
else
{
Assert.Fail($"Response value is null");
}
}
[TestMethod]
public async Task CreateRoleAsync_Exception()
{
if (_roleController == null)
{
Assert.Fail($"_roleController is null");
}
if (_roleServiceMock == null)
{
Assert.Fail($"_roleServiceMock is null");
}
DatabaseSqlServer.Role role = ModelsInit.CreateRole();
CreateRoleRequest request = new CreateRoleRequest()
{
Data = new CreateRoleRequestData()
{
Name = "RoleTest",
IsNotEditable = true
}
};
_roleServiceMock?.Setup(s => s.CheckIfNameIsValid(It.IsAny<string>(), It.IsAny<string>())).ReturnsAsync(true);
_roleServiceMock?.Setup(s => s.CreateRoleAsync(
It.IsAny<CreateRoleRequestData>()
)).ThrowsAsync(new Exception("Unexpected error"));
ObjectResult response = (ObjectResult)(await _roleController.CreateRoleAsync(request));
Assert.IsInstanceOfType(response, typeof(ObjectResult));
if (response != null && response.Value != null)
{
Assert.AreEqual(StatusCodes.Status500InternalServerError, response.StatusCode);
var result = (BaseResponse<object>)response.Value;
if (result != null)
{
Assert.AreEqual(StatusCodes.Status500InternalServerError, result.Status);
Assert.AreEqual("Something went wrong. Unexpected error", result.Message);
}
else
{
Assert.Fail($"Result value is null");
}
}
else
{
Assert.Fail($"Response is null");
}
}
#endregion
#region "DELETE"
[TestMethod]
public async Task DeleteRoleByGuidAsync_Success()
{
if (_roleController == null)
{
Assert.Fail($"_roleController is null");
}
var guid = Guid.NewGuid().ToString();
DatabaseSqlServer.Role role = ModelsInit.CreateRole();
_roleServiceMock?.Setup(s => s.GetRoleByGuidAsync(It.IsAny<string>())).ReturnsAsync(role);
ObjectResult response = (ObjectResult)(await _roleController.DeleteRoleByGuidAsync(guid));
if (response != null && response.Value != null)
{
Assert.AreEqual(StatusCodes.Status200OK, response.StatusCode);
}
else
{
Assert.Fail($"Response value is null");
}
}
[TestMethod]
public async Task DeleteRoleByGuidAsync_NotFound()
{
if (_roleController == null)
{
Assert.Fail($"_roleController is null");
}
var guid = Guid.NewGuid().ToString();
DatabaseSqlServer.Role? role = null;
_roleServiceMock?.Setup(s => s.GetRoleByGuidAsync(It.IsAny<string>())).ReturnsAsync(role);
NotFoundResult response = (NotFoundResult)(await _roleController.DeleteRoleByGuidAsync(guid));
Assert.IsInstanceOfType(response, typeof(NotFoundResult));
if (response != null)
{
Assert.AreEqual(StatusCodes.Status404NotFound, response.StatusCode);
}
else
{
Assert.Fail($"Response is null");
}
}
[TestMethod]
public async Task DeleteRoleByGuidAsync_Exception()
{
if (_roleController == null)
{
Assert.Fail($"_roleController is null");
}
var guid = Guid.NewGuid().ToString();
_roleServiceMock?.Setup(s => s.GetRoleByGuidAsync(It.IsAny<string>())).ThrowsAsync(new Exception("Unexpected error"));
ObjectResult response = (ObjectResult)(await _roleController.DeleteRoleByGuidAsync(guid));
Assert.IsInstanceOfType(response, typeof(ObjectResult));
if (response != null && response.Value != null)
{
Assert.AreEqual(StatusCodes.Status500InternalServerError, response.StatusCode);
var result = (BaseResponse<object>)response.Value;
if (result != null)
{
Assert.AreEqual(StatusCodes.Status500InternalServerError, result.Status);
Assert.AreEqual("Something went wrong. Unexpected error", result.Message);
}
else
{
Assert.Fail($"Result value is null");
}
}
else
{
Assert.Fail($"Response is null");
}
}
#endregion
#region "UPDATE"
[TestMethod]
public async Task UpdateRoleAsync_Should_Return_200_When_Successful()
{
if (_roleController == null)
{
Assert.Fail($"_roleController is null");
}
if (_roleServiceMock == null)
{
Assert.Fail($"_roleServiceMock is null");
}
DatabaseSqlServer.Role role = ModelsInit.CreateRole();
CreateRoleRequest request = new CreateRoleRequest()
{
Data = new CreateRoleRequestData()
{
Name = "RoleTest",
IsNotEditable = true
}
};
_roleServiceMock?.Setup(s => s.GetRoleByGuidAsync(It.IsAny<string>())).ReturnsAsync(role);
_roleServiceMock?.Setup(s => s.CheckIfNameIsValid(It.IsAny<string>(), It.IsAny<string>())).ReturnsAsync(true);
_roleServiceMock?.Setup(s => s.UpdateRoleAsync(It.IsAny<CreateRoleRequestData>(), It.IsAny<Role>())).ReturnsAsync(role);
ObjectResult response = (ObjectResult)(await _roleController.UpdateRoleAsync(request, role.Guid));
if (response != null && response.Value != null)
{
Assert.AreEqual(StatusCodes.Status200OK, response.StatusCode);
var result = (BaseResponse<object>)response.Value;
if (result != null)
{
Assert.AreEqual(StatusCodes.Status200OK, result.Status);
Assert.IsInstanceOfType(result.Data, typeof(RoleDto));
}
else
{
Assert.Fail($"Result value is null");
}
}
else
{
Assert.Fail($"Response value is null");
}
}
[TestMethod]
public async Task UpdateRoleAsync_RoleNotFound()
{
if (_roleController == null)
{
Assert.Fail($"_roleController is null");
}
DatabaseSqlServer.Role? role = null;
CreateRoleRequest request = new CreateRoleRequest()
{
Data = new CreateRoleRequestData()
{
Name = "RoleTest",
IsNotEditable = true
}
};
_roleServiceMock?.Setup(s => s.GetRoleByGuidAsync(It.IsAny<string>())).ReturnsAsync(role);
NotFoundResult response = (NotFoundResult)(await _roleController.UpdateRoleAsync(request, Guid.NewGuid().ToString()));
if (response != null)
{
Assert.AreEqual(StatusCodes.Status404NotFound, response.StatusCode);
}
else
{
Assert.Fail($"Response is null");
}
}
[TestMethod]
public async Task UpdateRoleAsync_InvalidName()
{
if (_roleController == null)
{
Assert.Fail($"_roleController is null");
}
DatabaseSqlServer.Role role = ModelsInit.CreateRole();
CreateRoleRequest request = new CreateRoleRequest()
{
Data = new CreateRoleRequestData()
{
Name = "RoleTest",
IsNotEditable = true
}
};
_roleServiceMock?.Setup(s => s.GetRoleByGuidAsync(It.IsAny<string>())).ReturnsAsync(role);
_roleServiceMock?.Setup(s => s.CheckIfNameIsValid(It.IsAny<string>(), It.IsAny<string>())).ReturnsAsync(false);
ObjectResult response = (ObjectResult)(await _roleController.UpdateRoleAsync(request, role.Guid));
if (response != null && response.Value != null)
{
Assert.AreEqual(StatusCodes.Status400BadRequest, response.StatusCode);
var result = (BaseResponse<object>)response.Value;
if (result != null)
{
Assert.AreEqual(StatusCodes.Status400BadRequest, result.Status);
Assert.AreEqual("Invalid name", result.Message);
}
else
{
Assert.Fail($"Result value is null");
}
}
else
{
Assert.Fail($"Response value is null");
}
}
[TestMethod]
public async Task UpdateRoleAsync_NotEditable()
{
if (_roleController == null)
{
Assert.Fail($"_roleController is null");
}
DatabaseSqlServer.Role role = ModelsInit.CreateRole();
role.IsNotEditable = true;
CreateRoleRequest request = new CreateRoleRequest()
{
Data = new CreateRoleRequestData()
{
Name = "RoleTest",
IsNotEditable = true
}
};
_roleServiceMock?.Setup(s => s.GetRoleByGuidAsync(It.IsAny<string>())).ReturnsAsync(role);
_roleServiceMock?.Setup(s => s.CheckIfNameIsValid(It.IsAny<string>(), It.IsAny<string>())).ReturnsAsync(false);
ObjectResult response = (ObjectResult)(await _roleController.UpdateRoleAsync(request, role.Guid));
if (response != null && response.Value != null)
{
Assert.AreEqual(StatusCodes.Status400BadRequest, response.StatusCode);
var result = (BaseResponse<object>)response.Value;
if (result != null)
{
Assert.AreEqual(StatusCodes.Status400BadRequest, result.Status);
Assert.AreEqual("This role is not editable", result.Message);
}
else
{
Assert.Fail($"Result value is null");
}
}
else
{
Assert.Fail($"Response value is null");
}
}
[TestMethod]
public async Task UpdateRoleAsync_Exception()
{
if (_roleController == null)
{
Assert.Fail($"_roleController is null");
}
if (_roleServiceMock == null)
{
Assert.Fail($"_roleServiceMock is null");
}
DatabaseSqlServer.Role role = ModelsInit.CreateRole();
CreateRoleRequest request = new CreateRoleRequest()
{
Data = new CreateRoleRequestData()
{
Name = "RoleTest",
IsNotEditable = true
}
};
_roleServiceMock?.Setup(s => s.GetRoleByGuidAsync(It.IsAny<string>())).ReturnsAsync(role);
_roleServiceMock?.Setup(s => s.CheckIfNameIsValid(It.IsAny<string>(), It.IsAny<string>())).ReturnsAsync(true);
_roleServiceMock?.Setup(s => s.UpdateRoleAsync(
It.IsAny<CreateRoleRequestData>(), It.IsAny<Role>()
)).ThrowsAsync(new Exception("Unexpected error"));
ObjectResult response = (ObjectResult)await _roleController.UpdateRoleAsync(request, role.Guid);
Assert.IsInstanceOfType(response, typeof(ObjectResult));
if (response != null && response.Value != null)
{
Assert.AreEqual(StatusCodes.Status500InternalServerError, response.StatusCode);
var result = (BaseResponse<object>)response.Value;
if (result != null)
{
Assert.AreEqual(StatusCodes.Status500InternalServerError, result.Status);
Assert.AreEqual("Something went wrong. Unexpected error", result.Message);
}
else
{
Assert.Fail($"Result value is null");
}
}
else
{
Assert.Fail($"Response is null");
}
}
#endregion
}

View File

@@ -0,0 +1,45 @@
using System;
using System.Reflection;
using System.Net;
using System.Net.Http;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using BasicDotnetTemplate.MainProject;
using BasicDotnetTemplate.MainProject.Controllers;
using Microsoft.Extensions.Configuration;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Infrastructure;
using BasicDotnetTemplate.MainProject.Models.Api.Response;
using BasicDotnetTemplate.MainProject.Models.Settings;
using Microsoft.AspNetCore.Http;
namespace BasicDotnetTemplate.MainProject.Tests;
[TestClass]
public class RootController_Test
{
[TestMethod]
public void GetRoot_Valid()
{
Environment.SetEnvironmentVariable("ASPNETCORE_ENVIRONMENT", "Development");
try
{
RootController rootController = new RootController();
var result = rootController.GetRoot();
if (result != null)
{
var data = (OkResult)result;
Assert.AreEqual(StatusCodes.Status200OK, data.StatusCode);
}
else
{
Assert.Fail($"Data is null");
}
}
catch (Exception ex)
{
Assert.Fail($"An exception was thrown: {ex}");
}
}
}

View File

@@ -0,0 +1,907 @@
using System;
using System.Reflection;
using System.Net;
using System.Net.Http;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Infrastructure;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Microsoft.Extensions.Configuration;
using Moq;
using Newtonsoft.Json;
using BasicDotnetTemplate.MainProject;
using BasicDotnetTemplate.MainProject.Controllers;
using BasicDotnetTemplate.MainProject.Services;
using BasicDotnetTemplate.MainProject.Models.Api.Response;
using BasicDotnetTemplate.MainProject.Models.Settings;
using BasicDotnetTemplate.MainProject.Models.Api.Request.Auth;
using BasicDotnetTemplate.MainProject.Models.Api.Data.Auth;
using BasicDotnetTemplate.MainProject.Models.Api.Common.User;
using BasicDotnetTemplate.MainProject.Models.Api.Common.Role;
using DatabaseSqlServer = BasicDotnetTemplate.MainProject.Models.Database.SqlServer;
using BasicDotnetTemplate.MainProject.Models.Api.Response.Auth;
using AutoMapper;
using BasicDotnetTemplate.MainProject.Core.Middlewares;
using Microsoft.AspNetCore.Http;
using BasicDotnetTemplate.MainProject.Models.Api.Request.User;
using BasicDotnetTemplate.MainProject.Models.Api.Data.User;
using BasicDotnetTemplate.MainProject.Models.Database.SqlServer;
namespace BasicDotnetTemplate.MainProject.Tests;
[TestClass]
public class UserController_Tests
{
private Mock<IUserService>? _userServiceMock;
private Mock<IRoleService>? _roleServiceMock;
private UserController? _userController;
[TestInitialize]
public void Setup()
{
IConfiguration configuration = TestUtils.CreateConfiguration();
_userServiceMock = new Mock<IUserService>();
_roleServiceMock = new Mock<IRoleService>();
_userController = new UserController(configuration, _userServiceMock.Object, _roleServiceMock.Object);
}
[TestMethod]
public void UserController_NullConfiguration()
{
Environment.SetEnvironmentVariable("ASPNETCORE_ENVIRONMENT", "Development");
var exception = true;
try
{
var userServiceMock = new Mock<IUserService>();
var roleServiceMock = new Mock<IRoleService>();
_ = new UserController(null, userServiceMock.Object, roleServiceMock.Object);
exception = false;
Assert.Fail($"This test should not pass as configuration is null");
}
catch (Exception)
{
Assert.IsTrue(exception);
}
}
#region "GET"
[TestMethod]
public async Task GetUserByGuidAsync_Should_Return_200_When_Successful()
{
if (_userController == null)
{
Assert.Fail($"_userController is null");
}
var guid = Guid.NewGuid().ToString();
DatabaseSqlServer.User user = ModelsInit.CreateUser();
_userServiceMock?.Setup(s => s.GetUserByGuidAsync(It.IsAny<string>())).ReturnsAsync(user);
ObjectResult response = (ObjectResult)(await _userController.GetUserByGuidAsync(guid));
if (response != null && response.Value != null)
{
Assert.AreEqual(StatusCodes.Status200OK, response.StatusCode);
var result = (BaseResponse<object>)response.Value;
if (result != null)
{
Assert.AreEqual(StatusCodes.Status200OK, result.Status);
Assert.IsInstanceOfType(result.Data, typeof(UserDto));
}
else
{
Assert.Fail($"Result value is null");
}
}
else
{
Assert.Fail($"Response value is null");
}
}
[TestMethod]
public async Task GetUserByGuidAsync_NotFound()
{
if (_userController == null)
{
Assert.Fail($"_userController is null");
}
var guid = Guid.NewGuid().ToString();
DatabaseSqlServer.User? user = null;
_userServiceMock?.Setup(s => s.GetUserByGuidAsync(It.IsAny<string>())).ReturnsAsync(user);
NotFoundResult response = (NotFoundResult)(await _userController.GetUserByGuidAsync(guid));
Assert.IsInstanceOfType(response, typeof(NotFoundResult));
if (response != null)
{
Assert.AreEqual(StatusCodes.Status404NotFound, response.StatusCode);
}
else
{
Assert.Fail($"Response is null");
}
}
[TestMethod]
public async Task GetUserByGuidAsync_Exception()
{
if (_userController == null)
{
Assert.Fail($"_userController is null");
}
var guid = Guid.NewGuid().ToString();
_userServiceMock?.Setup(s => s.GetUserByGuidAsync(It.IsAny<string>())).ThrowsAsync(new Exception("Unexpected error"));
ObjectResult response = (ObjectResult)(await _userController.GetUserByGuidAsync(guid));
Assert.IsInstanceOfType(response, typeof(ObjectResult));
if (response != null && response.Value != null)
{
Assert.AreEqual(StatusCodes.Status500InternalServerError, response.StatusCode);
var result = (BaseResponse<object>)response.Value;
if (result != null)
{
Assert.AreEqual(StatusCodes.Status500InternalServerError, result.Status);
Assert.AreEqual("Something went wrong. Unexpected error", result.Message);
}
else
{
Assert.Fail($"Result value is null");
}
}
else
{
Assert.Fail($"Response is null");
}
}
#endregion
#region "CREATE"
[TestMethod]
public async Task CreateUserAsync_Success()
{
if (_userController == null)
{
Assert.Fail($"_userController is null");
}
if (_roleServiceMock == null)
{
Assert.Fail($"_roleServiceMock is null");
}
DatabaseSqlServer.User user = ModelsInit.CreateUser();
DatabaseSqlServer.Role role = ModelsInit.CreateRole();
CreateUserRequest request = new CreateUserRequest()
{
Data = new CreateUserRequestData()
{
FirstName = user.FirstName,
LastName = user.LastName,
Email = user.Email,
Password = user.Password
}
};
_userServiceMock?.Setup(s => s.CheckIfEmailIsValid(It.IsAny<string>(), It.IsAny<string>())).ReturnsAsync(true);
_roleServiceMock.Setup(s => s.GetRoleForUser(null)).ReturnsAsync(role);
_userServiceMock?.Setup(s => s.CreateUserAsync(request.Data, role)).ReturnsAsync(user);
ObjectResult response = (ObjectResult)(await _userController.CreateUserAsync(request));
if (response != null && response.Value != null)
{
Assert.AreEqual(StatusCodes.Status200OK, response.StatusCode);
var result = (BaseResponse<object>)response.Value;
if (result != null)
{
Assert.AreEqual(StatusCodes.Status200OK, result.Status);
Assert.IsInstanceOfType(result.Data, typeof(UserDto));
}
else
{
Assert.Fail($"Result value is null");
}
}
else
{
Assert.Fail($"Response value is null");
}
}
[TestMethod]
public async Task CreateUserAsync_InvalidEmail()
{
if (_userController == null)
{
Assert.Fail($"_userController is null");
}
DatabaseSqlServer.User user = ModelsInit.CreateUser();
CreateUserRequest request = new CreateUserRequest()
{
Data = new CreateUserRequestData()
{
FirstName = user.FirstName,
LastName = user.LastName,
Email = user.Email,
Password = user.Password
}
};
_userServiceMock?.Setup(s => s.CheckIfEmailIsValid(It.IsAny<string>(), It.IsAny<string>())).ReturnsAsync(false);
ObjectResult response = (ObjectResult)(await _userController.CreateUserAsync(request));
if (response != null && response.Value != null)
{
Assert.AreEqual(StatusCodes.Status400BadRequest, response.StatusCode);
var result = (BaseResponse<object>)response.Value;
if (result != null)
{
Assert.AreEqual(StatusCodes.Status400BadRequest, result.Status);
Assert.AreEqual("Invalid email", result.Message);
}
else
{
Assert.Fail($"Result value is null");
}
}
else
{
Assert.Fail($"Response value is null");
}
}
[TestMethod]
public async Task CreateUserAsync_RoleNull()
{
if (_userController == null)
{
Assert.Fail($"_userController is null");
}
DatabaseSqlServer.User user = ModelsInit.CreateUser();
CreateUserRequest request = new CreateUserRequest()
{
Data = new CreateUserRequestData()
{
FirstName = user.FirstName,
LastName = user.LastName,
Email = user.Email,
Password = user.Password
}
};
_userServiceMock?.Setup(s => s.CheckIfEmailIsValid(It.IsAny<string>(), It.IsAny<string>())).ReturnsAsync(true);
_userServiceMock?.Setup(s => s.CreateUserAsync(
It.IsAny<CreateUserRequestData>(),
It.IsAny<Role>()
)).ReturnsAsync(user);
ObjectResult response = (ObjectResult)(await _userController.CreateUserAsync(request));
if (response != null && response.Value != null)
{
Assert.AreEqual(StatusCodes.Status400BadRequest, response.StatusCode);
var result = (BaseResponse<object>)response.Value;
if (result != null)
{
Assert.AreEqual(StatusCodes.Status400BadRequest, result.Status);
Assert.AreEqual("Role not found", result.Message);
}
else
{
Assert.Fail($"Result value is null");
}
}
else
{
Assert.Fail($"Response value is null");
}
}
[TestMethod]
public async Task CreateUserAsync_NotCreated()
{
if (_userController == null)
{
Assert.Fail($"_userController is null");
}
if (_roleServiceMock == null)
{
Assert.Fail($"_roleServiceMock is null");
}
DatabaseSqlServer.User user = ModelsInit.CreateUser();
DatabaseSqlServer.Role role = ModelsInit.CreateRole();
DatabaseSqlServer.User? expectedUser = null;
CreateUserRequest request = new CreateUserRequest()
{
Data = new CreateUserRequestData()
{
FirstName = user.FirstName,
LastName = user.LastName,
Email = user.Email,
Password = user.Password
}
};
_userServiceMock?.Setup(s => s.CheckIfEmailIsValid(It.IsAny<string>(), It.IsAny<string>())).ReturnsAsync(true);
_roleServiceMock.Setup(s => s.GetRoleForUser(null)).ReturnsAsync(role);
_userServiceMock?.Setup(s => s.CreateUserAsync(request.Data, role)).ReturnsAsync(expectedUser);
ObjectResult response = (ObjectResult)(await _userController.CreateUserAsync(request));
if (response != null && response.Value != null)
{
Assert.AreEqual(StatusCodes.Status400BadRequest, response.StatusCode);
var result = (BaseResponse<object>)response.Value;
if (result != null)
{
Assert.AreEqual(StatusCodes.Status400BadRequest, result.Status);
Assert.AreEqual("Not created", result.Message);
}
else
{
Assert.Fail($"Result value is null");
}
}
else
{
Assert.Fail($"Response value is null");
}
}
[TestMethod]
public async Task CreateUserAsync_Exception()
{
if (_userController == null)
{
Assert.Fail($"_userController is null");
}
if (_roleServiceMock == null)
{
Assert.Fail($"_roleServiceMock is null");
}
DatabaseSqlServer.User user = ModelsInit.CreateUser();
DatabaseSqlServer.Role role = ModelsInit.CreateRole();
CreateUserRequest request = new CreateUserRequest()
{
Data = new CreateUserRequestData()
{
FirstName = user.FirstName,
LastName = user.LastName,
Email = user.Email,
Password = user.Password
}
};
_userServiceMock?.Setup(s => s.CheckIfEmailIsValid(It.IsAny<string>(), It.IsAny<string>())).ReturnsAsync(true);
_roleServiceMock.Setup(s => s.GetRoleForUser(null)).ReturnsAsync(role);
_userServiceMock?.Setup(s => s.CreateUserAsync(request.Data, role)).ReturnsAsync(user);
_userServiceMock?.Setup(s => s.CreateUserAsync(
It.IsAny<CreateUserRequestData>(),
It.IsAny<Role>()
)).ThrowsAsync(new Exception("Unexpected error"));
ObjectResult response = (ObjectResult)(await _userController.CreateUserAsync(request));
Assert.IsInstanceOfType(response, typeof(ObjectResult));
if (response != null && response.Value != null)
{
Assert.AreEqual(StatusCodes.Status500InternalServerError, response.StatusCode);
var result = (BaseResponse<object>)response.Value;
if (result != null)
{
Assert.AreEqual(StatusCodes.Status500InternalServerError, result.Status);
Assert.AreEqual("Something went wrong. Unexpected error", result.Message);
}
else
{
Assert.Fail($"Result value is null");
}
}
else
{
Assert.Fail($"Response is null");
}
}
#endregion
#region "DELETE"
[TestMethod]
public async Task DeleteRoleByGuidAsync_Success()
{
if (_userController == null)
{
Assert.Fail($"_userController is null");
}
var guid = Guid.NewGuid().ToString();
DatabaseSqlServer.User user = ModelsInit.CreateUser();
_userServiceMock?.Setup(s => s.GetUserByGuidAsync(It.IsAny<string>())).ReturnsAsync(user);
ObjectResult response = (ObjectResult)await _userController.DeleteUserByGuidAsync(guid);
if (response != null && response.Value != null)
{
Assert.AreEqual(StatusCodes.Status200OK, response.StatusCode);
}
else
{
Assert.Fail($"Response value is null");
}
}
[TestMethod]
public async Task DeleteRoleByGuidAsync_NotFound()
{
if (_userController == null)
{
Assert.Fail($"_userController is null");
}
var guid = Guid.NewGuid().ToString();
DatabaseSqlServer.User? user = null;
_userServiceMock?.Setup(s => s.GetUserByGuidAsync(It.IsAny<string>())).ReturnsAsync(user);
NotFoundResult response = (NotFoundResult)await _userController.DeleteUserByGuidAsync(guid);
Assert.IsInstanceOfType(response, typeof(NotFoundResult));
if (response != null)
{
Assert.AreEqual(StatusCodes.Status404NotFound, response.StatusCode);
}
else
{
Assert.Fail($"Response is null");
}
}
[TestMethod]
public async Task DeleteRoleByGuidAsync_Exception()
{
if (_userController == null)
{
Assert.Fail($"_userController is null");
}
var guid = Guid.NewGuid().ToString();
_userServiceMock?.Setup(s => s.GetUserByGuidAsync(It.IsAny<string>())).ThrowsAsync(new Exception("Unexpected error"));
ObjectResult response = (ObjectResult)await _userController.DeleteUserByGuidAsync(guid);
Assert.IsInstanceOfType(response, typeof(ObjectResult));
if (response != null && response.Value != null)
{
Assert.AreEqual(StatusCodes.Status500InternalServerError, response.StatusCode);
var result = (BaseResponse<object>)response.Value;
if (result != null)
{
Assert.AreEqual(StatusCodes.Status500InternalServerError, result.Status);
Assert.AreEqual("Something went wrong. Unexpected error", result.Message);
}
else
{
Assert.Fail($"Result value is null");
}
}
else
{
Assert.Fail($"Response is null");
}
}
#endregion
#region "UPDATE"
[TestMethod]
public async Task UpdateUserAsync_Should_Return_200_When_Successful()
{
if (_userController == null)
{
Assert.Fail($"_userController is null");
}
DatabaseSqlServer.User user = ModelsInit.CreateUser();
UpdateUserRequest request = new UpdateUserRequest()
{
Data = new UpdateUserRequestData()
{
FirstName = "NewFirstName",
LastName = "NewLastName"
}
};
_userServiceMock?.Setup(s => s.GetUserByGuidAsync(It.IsAny<string>())).ReturnsAsync(user);
_userServiceMock?.Setup(s => s.UpdateUserAsync(It.IsAny<UpdateUserRequestData>(), It.IsAny<User>())).ReturnsAsync(user);
ObjectResult response = (ObjectResult)await _userController.UpdateUserAsync(request, user.Guid);
if (response != null && response.Value != null)
{
Assert.AreEqual(StatusCodes.Status200OK, response.StatusCode);
var result = (BaseResponse<object>)response.Value;
if (result != null)
{
Assert.AreEqual(StatusCodes.Status200OK, result.Status);
Assert.IsInstanceOfType(result.Data, typeof(UserDto));
}
else
{
Assert.Fail($"Result value is null");
}
}
else
{
Assert.Fail($"Response value is null");
}
}
[TestMethod]
public async Task UpdateUserAsync_UserNotFound()
{
if (_userController == null)
{
Assert.Fail($"_userController is null");
}
DatabaseSqlServer.User? user = null;
UpdateUserRequest request = new UpdateUserRequest()
{
Data = new UpdateUserRequestData()
{
FirstName = "NewFirstName",
LastName = "NewLastName"
}
};
_userServiceMock?.Setup(s => s.GetUserByGuidAsync(It.IsAny<string>())).ReturnsAsync(user);
NotFoundResult response = (NotFoundResult)await _userController.UpdateUserAsync(request, Guid.NewGuid().ToString());
if (response != null)
{
Assert.AreEqual(StatusCodes.Status404NotFound, response.StatusCode);
}
else
{
Assert.Fail($"Response is null");
}
}
[TestMethod]
public async Task UpdateUserAsync_Exception()
{
if (_userController == null)
{
Assert.Fail($"_userController is null");
}
DatabaseSqlServer.User user = ModelsInit.CreateUser();
UpdateUserRequest request = new UpdateUserRequest()
{
Data = new UpdateUserRequestData()
{
FirstName = "NewFirstName",
LastName = "NewLastName"
}
};
_userServiceMock?.Setup(s => s.GetUserByGuidAsync(It.IsAny<string>())).ReturnsAsync(user);
_userServiceMock?.Setup(s => s.UpdateUserAsync(
It.IsAny<UpdateUserRequestData>(), It.IsAny<User>()
)).ThrowsAsync(new Exception("Unexpected error"));
ObjectResult response = (ObjectResult)await _userController.UpdateUserAsync(request, user.Guid);
Assert.IsInstanceOfType(response, typeof(ObjectResult));
if (response != null && response.Value != null)
{
Assert.AreEqual(StatusCodes.Status500InternalServerError, response.StatusCode);
var result = (BaseResponse<object>)response.Value;
if (result != null)
{
Assert.AreEqual(StatusCodes.Status500InternalServerError, result.Status);
Assert.AreEqual("Something went wrong. Unexpected error", result.Message);
}
else
{
Assert.Fail($"Result value is null");
}
}
else
{
Assert.Fail($"Response is null");
}
}
[TestMethod]
public async Task UpdateUserPasswordAsync_Should_Return_200_When_Successful()
{
if (_userController == null)
{
Assert.Fail($"_userController is null");
}
DatabaseSqlServer.User user = ModelsInit.CreateUser();
string newPassword = "This!s4T3stP4ssw0rd#";
_userServiceMock?.Setup(s => s.GetUserByGuidAsync(It.IsAny<string>())).ReturnsAsync(user);
_userServiceMock?.Setup(s => s.UpdateUserPasswordAsync(It.IsAny<User>(), newPassword)).ReturnsAsync(user);
ObjectResult response = (ObjectResult)await _userController.UpdateUserPasswordAsync(user.Guid, newPassword);
if (response != null && response.Value != null)
{
Assert.AreEqual(StatusCodes.Status200OK, response.StatusCode);
var result = (BaseResponse<object>)response.Value;
if (result != null)
{
Assert.AreEqual(StatusCodes.Status200OK, result.Status);
Assert.IsInstanceOfType(result.Data, typeof(UserDto));
}
else
{
Assert.Fail($"Result value is null");
}
}
else
{
Assert.Fail($"Response value is null");
}
}
[TestMethod]
public async Task UpdateUserPasswordAsync_UserNotFound()
{
if (_userController == null)
{
Assert.Fail($"_userController is null");
}
DatabaseSqlServer.User? user = null;
string newPassword = "This!s4T3stP4ssw0rd#";
_userServiceMock?.Setup(s => s.GetUserByGuidAsync(It.IsAny<string>())).ReturnsAsync(user);
NotFoundResult response = (NotFoundResult)await _userController.UpdateUserPasswordAsync(Guid.NewGuid().ToString(), newPassword);
if (response != null)
{
Assert.AreEqual(StatusCodes.Status404NotFound, response.StatusCode);
}
else
{
Assert.Fail($"Response is null");
}
}
[TestMethod]
public async Task UpdateUserPasswordAsync_Exception()
{
if (_userController == null)
{
Assert.Fail($"_userController is null");
}
DatabaseSqlServer.User user = ModelsInit.CreateUser();
string newPassword = "This!s4T3stP4ssw0rd#";
_userServiceMock?.Setup(s => s.GetUserByGuidAsync(It.IsAny<string>())).ReturnsAsync(user);
_userServiceMock?.Setup(s => s.UpdateUserPasswordAsync(
It.IsAny<User>(), It.IsAny<string>()
)).ThrowsAsync(new Exception("Unexpected error"));
ObjectResult response = (ObjectResult)await _userController.UpdateUserPasswordAsync(user.Guid, newPassword);
Assert.IsInstanceOfType(response, typeof(ObjectResult));
if (response != null && response.Value != null)
{
Assert.AreEqual(StatusCodes.Status500InternalServerError, response.StatusCode);
var result = (BaseResponse<object>)response.Value;
if (result != null)
{
Assert.AreEqual(StatusCodes.Status500InternalServerError, result.Status);
Assert.AreEqual("Something went wrong. Unexpected error", result.Message);
}
else
{
Assert.Fail($"Result value is null");
}
}
else
{
Assert.Fail($"Response is null");
}
}
[TestMethod]
public async Task UpdateUserRoleAsync_Should_Return_200_When_Successful()
{
if (_userController == null)
{
Assert.Fail($"_userController is null");
}
if(_roleServiceMock == null)
{
Assert.Fail($"_roleServiceMock is null");
}
DatabaseSqlServer.User user = ModelsInit.CreateUser();
DatabaseSqlServer.Role role = ModelsInit.CreateRole();
_roleServiceMock?.Setup(s => s.GetRoleByGuidAsync(It.IsAny<string>())).ReturnsAsync(role);
_userServiceMock?.Setup(s => s.GetUserByGuidAsync(It.IsAny<string>())).ReturnsAsync(user);
_userServiceMock?.Setup(s => s.UpdateUserRoleAsync(It.IsAny<User>(), It.IsAny<Role>())).ReturnsAsync(user);
ObjectResult response = (ObjectResult)await _userController.UpdateUserRoleAsync(user.Guid, role.Guid);
if (response != null && response.Value != null)
{
Assert.AreEqual(StatusCodes.Status200OK, response.StatusCode);
var result = (BaseResponse<object>)response.Value;
if (result != null)
{
Assert.AreEqual(StatusCodes.Status200OK, result.Status);
Assert.IsInstanceOfType(result.Data, typeof(UserDto));
}
else
{
Assert.Fail($"Result value is null");
}
}
else
{
Assert.Fail($"Response value is null");
}
}
[TestMethod]
public async Task UpdateUserPasswordAsync_RoleNotFound()
{
if (_userController == null)
{
Assert.Fail($"_userController is null");
}
DatabaseSqlServer.User user = ModelsInit.CreateUser();
DatabaseSqlServer.Role? role = null;
_roleServiceMock?.Setup(s => s.GetRoleByGuidAsync(It.IsAny<string>())).ReturnsAsync(role);
_userServiceMock?.Setup(s => s.GetUserByGuidAsync(It.IsAny<string>())).ReturnsAsync(user);
ObjectResult response = (ObjectResult)await _userController.UpdateUserRoleAsync(user.Guid, Guid.NewGuid().ToString());
if (response != null)
{
Assert.AreEqual(StatusCodes.Status400BadRequest, response.StatusCode);
Assert.IsNotNull(response.Value);
var result = (BaseResponse<object>)response.Value;
if (result != null)
{
Assert.AreEqual(StatusCodes.Status400BadRequest, result.Status);
Assert.AreEqual("Role not found", result.Message);
}
else
{
Assert.Fail($"Result value is null");
}
}
else
{
Assert.Fail($"Response is null");
}
}
[TestMethod]
public async Task UpdateUserRoleAsync_UserNotFound()
{
if (_userController == null)
{
Assert.Fail($"_userController is null");
}
DatabaseSqlServer.User? user = null;
DatabaseSqlServer.Role role = ModelsInit.CreateRole();
_roleServiceMock?.Setup(s => s.GetRoleByGuidAsync(It.IsAny<string>())).ReturnsAsync(role);
_userServiceMock?.Setup(s => s.GetUserByGuidAsync(It.IsAny<string>())).ReturnsAsync(user);
_userServiceMock?.Setup(s => s.UpdateUserRoleAsync(It.IsAny<User>(), It.IsAny<Role>())).ReturnsAsync(user);
NotFoundResult response = (NotFoundResult)await _userController.UpdateUserRoleAsync(Guid.NewGuid().ToString(), role.Guid);
if (response != null)
{
Assert.AreEqual(StatusCodes.Status404NotFound, response.StatusCode);
}
else
{
Assert.Fail($"Response is null");
}
}
[TestMethod]
public async Task UpdateUserRoleAsync_Exception()
{
if (_userController == null)
{
Assert.Fail($"_userController is null");
}
DatabaseSqlServer.User user = ModelsInit.CreateUser();
DatabaseSqlServer.Role role = ModelsInit.CreateRole();
_roleServiceMock?.Setup(s => s.GetRoleByGuidAsync(It.IsAny<string>())).ReturnsAsync(role);
_userServiceMock?.Setup(s => s.GetUserByGuidAsync(It.IsAny<string>())).ReturnsAsync(user);
_userServiceMock?.Setup(s => s.UpdateUserRoleAsync(
It.IsAny<User>(), It.IsAny<Role>()
)).ThrowsAsync(new Exception("Unexpected error"));
ObjectResult response = (ObjectResult)await _userController.UpdateUserRoleAsync(user.Guid, role.Guid);
Assert.IsInstanceOfType(response, typeof(ObjectResult));
if (response != null && response.Value != null)
{
Assert.AreEqual(StatusCodes.Status500InternalServerError, response.StatusCode);
var result = (BaseResponse<object>)response.Value;
if (result != null)
{
Assert.AreEqual(StatusCodes.Status500InternalServerError, result.Status);
Assert.AreEqual("Something went wrong. Unexpected error", result.Message);
}
else
{
Assert.Fail($"Result value is null");
}
}
else
{
Assert.Fail($"Response is null");
}
}
#endregion
}

View File

@@ -0,0 +1,101 @@
using System;
using System.Reflection;
using System.Net;
using System.Net.Http;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using BasicDotnetTemplate.MainProject;
using BasicDotnetTemplate.MainProject.Controllers;
using Microsoft.Extensions.Configuration;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Infrastructure;
using BasicDotnetTemplate.MainProject.Models.Api.Response;
using BasicDotnetTemplate.MainProject.Models.Settings;
using Microsoft.AspNetCore.Http;
namespace BasicDotnetTemplate.MainProject.Tests;
[TestClass]
public class VersionController_Tests
{
[TestMethod]
public void VersionController_NullConfiguration()
{
Environment.SetEnvironmentVariable("ASPNETCORE_ENVIRONMENT", "Development");
var exception = true;
try
{
_ = new VersionController(null);
exception = false;
Assert.Fail($"This test should not pass as configuration is null");
}
catch (Exception)
{
Assert.IsTrue(exception);
}
}
[TestMethod]
public void VersionController_GetVersion_Valid()
{
Environment.SetEnvironmentVariable("ASPNETCORE_ENVIRONMENT", "Development");
try
{
IConfiguration configuration = TestUtils.CreateConfiguration();
VersionController versionController = new VersionController(configuration);
var result = versionController.GetVersion();
var objectResult = ((ObjectResult)result).Value;
if (objectResult != null)
{
var data = (BaseResponse<object>)objectResult;
if (data.Data != null)
{
AppSettings appSettings = new AppSettings();
configuration.GetSection("AppSettings").Bind(appSettings);
string version = data.Data != null ? (string)data.Data : "";
Assert.IsTrue((((IStatusCodeActionResult)result).StatusCode == StatusCodes.Status200OK) && (version == appSettings.Settings?.Version));
}
else
{
Assert.Fail($"Unable to convert response value to BaseResponse because Data is null");
}
}
else
{
Assert.Fail($"Data is null");
}
}
catch (Exception ex)
{
Assert.Fail($"An exception was thrown: {ex}");
}
}
[TestMethod]
public void VersionController_GetVersion_NoVersion()
{
Environment.SetEnvironmentVariable("ASPNETCORE_ENVIRONMENT", "Development");
try
{
var configuration = TestUtils.CreateEmptyConfiguration(System.AppDomain.CurrentDomain.BaseDirectory + "/JsonData", "emptyAppsettings.json");
VersionController versionController = new VersionController(configuration);
var result = versionController.GetVersion();
var objectResult = ((ObjectResult)result).Value;
if (objectResult != null)
{
var data = (BaseResponse<object>)objectResult;
Assert.IsTrue((((IStatusCodeActionResult)result).StatusCode == StatusCodes.Status200OK) && String.IsNullOrEmpty(data.Data));
}
else
{
Assert.Fail($"Response value is null");
}
}
catch (Exception ex)
{
Assert.Fail($"An exception was thrown: {ex}");
}
}
}

View File

@@ -0,0 +1,146 @@
using BasicDotnetTemplate.MainProject.Models.Api.Common.User;
using DatabaseSqlServer = BasicDotnetTemplate.MainProject.Models.Database.SqlServer;
using Microsoft.AspNetCore.Builder;
using BasicDotnetTemplate.MainProject.Models.Settings;
using BasicDotnetTemplate.MainProject.Utils;
using Microsoft.AspNetCore.Mvc.Filters;
using BasicDotnetTemplate.MainProject.Core.Attributes;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.DependencyInjection;
using Moq;
using Microsoft.Extensions.Configuration;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Routing;
namespace BasicDotnetTemplate.MainProject.Tests;
[TestClass]
public class JwtAuthorizationAttribute_Tests
{
private static AuthenticatedUser? _authenticatedUser = null;
private static string? _token = null;
private static JwtAuthorizationAttribute? _attribute;
private static JwtTokenUtils? _jwtTokenUtils;
[TestInitialize]
public void Setup()
{
_attribute = new JwtAuthorizationAttribute();
DatabaseSqlServer.User user = ModelsInit.CreateUser();
_authenticatedUser = new AuthenticatedUser(user);
WebApplicationBuilder builder = WebApplication.CreateBuilder(Array.Empty<string>());
AppSettings appSettings = ProgramUtils.AddConfiguration(ref builder, System.AppDomain.CurrentDomain.BaseDirectory + "/JsonData");
_jwtTokenUtils = new JwtTokenUtils(appSettings);
_token = _jwtTokenUtils.GenerateToken(user.Guid);
}
private static AuthorizationFilterContext CreateAuthorizationContextWithAllowAnonymous()
{
var httpContext = new DefaultHttpContext();
var routeData = new RouteData();
var actionDescriptor = new ControllerActionDescriptor
{
EndpointMetadata = new List<object> { new AllowAnonymousAttribute() }
};
var actionContext = new ActionContext(httpContext, routeData, actionDescriptor);
actionContext.ActionDescriptor.EndpointMetadata.Add(new AllowAnonymousAttribute());
return new AuthorizationFilterContext(actionContext, []);
}
[TestMethod]
public void OnAuthorization_AllowAnonymous_SkipsAuthorization()
{
try
{
var context = CreateAuthorizationContextWithAllowAnonymous();
_attribute?.OnAuthorization(context);
Assert.IsNull(context.Result);
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException);
Assert.Fail($"An exception was thrown: {ex}");
}
}
[TestMethod]
public void OnAuthorization_NoAuthenticatedUser_ReturnsUnauthorized()
{
var context = TestUtils.CreateAuthorizationContext();
IConfiguration configuration = TestUtils.CreateConfiguration();
context.HttpContext.RequestServices = new ServiceCollection()
.AddSingleton(configuration)
.BuildServiceProvider();
context.HttpContext.Items["User"] = null;
_attribute?.OnAuthorization(context);
Assert.IsInstanceOfType(context.Result, typeof(UnauthorizedResult));
}
[TestMethod]
public void OnAuthorization_EmptyAuthorizationHeader_ReturnsUnauthorized()
{
var context = TestUtils.CreateAuthorizationContext();
IConfiguration configuration = TestUtils.CreateConfiguration();
context.HttpContext.RequestServices = new ServiceCollection()
.AddSingleton(configuration)
.BuildServiceProvider();
context.HttpContext.Items["User"] = _authenticatedUser;
context.HttpContext.Request.Headers.Authorization = string.Empty;
_attribute?.OnAuthorization(context);
Assert.IsInstanceOfType(context.Result, typeof(UnauthorizedResult));
}
[TestMethod]
public void OnAuthorization_InvalidToken_ReturnsUnauthorized()
{
var context = TestUtils.CreateAuthorizationContext();
IConfiguration configuration = TestUtils.CreateConfiguration();
context.HttpContext.RequestServices = new ServiceCollection()
.AddSingleton(configuration)
.BuildServiceProvider();
var invalidToken = _jwtTokenUtils?.GenerateToken(Guid.NewGuid().ToString());
context.HttpContext.Request.Headers.Authorization = $"Bearer {invalidToken}";
context.HttpContext.Items["User"] = _authenticatedUser;
_attribute?.OnAuthorization(context);
Assert.IsInstanceOfType(context.Result, typeof(UnauthorizedResult));
}
[TestMethod]
public void OnAuthorization_ValidToken()
{
var context = TestUtils.CreateAuthorizationContext();
IConfiguration configuration = TestUtils.CreateConfiguration();
context.HttpContext.RequestServices = new ServiceCollection()
.AddSingleton(configuration)
.BuildServiceProvider();
context.HttpContext.Request.Headers.Authorization = $"Bearer {_token}";
context.HttpContext.Items["User"] = _authenticatedUser;
_attribute?.OnAuthorization(context);
Assert.IsNotInstanceOfType(context.Result, typeof(UnauthorizedResult));
}
}

View File

@@ -0,0 +1,135 @@
using BasicDotnetTemplate.MainProject.Models.Api.Common.User;
using DatabaseSqlServer = BasicDotnetTemplate.MainProject.Models.Database.SqlServer;
using Microsoft.AspNetCore.Builder;
using BasicDotnetTemplate.MainProject.Models.Settings;
using BasicDotnetTemplate.MainProject.Utils;
using Microsoft.AspNetCore.Mvc.Filters;
using BasicDotnetTemplate.MainProject.Core.Attributes;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.DependencyInjection;
using Moq;
using Microsoft.Extensions.Configuration;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using BasicDotnetTemplate.MainProject.Core.Filters;
using Newtonsoft.Json;
using BasicDotnetTemplate.MainProject.Models.Api.Base;
namespace BasicDotnetTemplate.MainProject.Tests;
[TestClass]
public class ValidationActionFilter_Tests
{
private readonly string _requestNotWellFormedMessage = "Request is not well formed";
private static ActionExecutingContext CreateContext(ModelStateDictionary modelState, object? requestBody = null)
{
var actionContext = new ActionContext(
new DefaultHttpContext(),
new Microsoft.AspNetCore.Routing.RouteData(),
new Microsoft.AspNetCore.Mvc.Controllers.ControllerActionDescriptor(),
modelState
);
var actionArguments = new Dictionary<string, object?>();
if (requestBody != null)
{
actionArguments.Add("request", requestBody);
}
return new ActionExecutingContext(
actionContext,
[],
actionArguments,
new Mock<Controller>().Object
);
}
[TestMethod]
public void OnActionExecutionAsync_ModelStateInvalid_ReturnsBadRequestAndDoesNotCallNext()
{
// Arrange
var modelState = new ModelStateDictionary();
modelState.AddModelError("MissingProperty", "MissingProperty is required");
var context = CreateContext(modelState, new { SomeProp = "Value" });
var nextCalled = false;
ActionExecutionDelegate next = () => {
nextCalled = true;
return Task.FromResult(new ActionExecutedContext(context, [], new Mock<Controller>().Object));
};
var filter = new ValidationActionFilter();
// Act
filter.OnActionExecutionAsync(context, next).GetAwaiter().GetResult();
// Assert
Assert.IsNotNull(context.Result);
var badRequestResult = context.Result as BadRequestObjectResult;
Assert.IsNotNull(badRequestResult);
Assert.IsNotNull(badRequestResult!.Value);
ValidationError validationError = (ValidationError)badRequestResult.Value;
Assert.AreEqual(_requestNotWellFormedMessage, validationError?.Message);
Assert.IsNotNull(validationError?.Errors);
Assert.IsFalse(modelState.IsValid);
Assert.IsFalse(nextCalled);
}
[TestMethod]
public void OnActionExecutionAsync_ModelStateValid_RequestBodyNull_ReturnsBadRequestAndDoesNotCallNext()
{
var modelState = new ModelStateDictionary();
var context = CreateContext(modelState, null);
var nextCalled = false;
ActionExecutionDelegate next = () => {
nextCalled = true;
return Task.FromResult(new ActionExecutedContext(context, [], new Mock<Controller>().Object));
};
var filter = new ValidationActionFilter();
// Act
filter.OnActionExecutionAsync(context, next).GetAwaiter().GetResult();
// Assert
Assert.IsNotNull(context.Result);
var badRequestResult = context.Result as BadRequestObjectResult;
Assert.IsNotNull(badRequestResult);
Assert.IsNotNull(badRequestResult!.Value);
ValidationError validationError = (ValidationError)badRequestResult.Value;
Assert.AreEqual(_requestNotWellFormedMessage, validationError?.Message);
Assert.IsNull(validationError?.Errors);
Assert.IsTrue(modelState.IsValid);
Assert.IsFalse(nextCalled);
}
[TestMethod]
public void OnActionExecutionAsync_ModelStateValid_RequestBodyValid_CallsNextAndDoesNotSetResult()
{
// Arrange
var modelState = new ModelStateDictionary();
var requestBody = new TestRequestBody { Value = "Test" };
var context = CreateContext(modelState, requestBody);
var nextCalled = false;
ActionExecutionDelegate next = () => {
nextCalled = true;
return Task.FromResult(new ActionExecutedContext(context, [], new Mock<Controller>().Object));
};
var filter = new ValidationActionFilter();
// Act
filter.OnActionExecutionAsync(context, next).GetAwaiter().GetResult();
// Assert
Assert.IsNull(context.Result);
Assert.IsTrue(nextCalled);
}
private class TestRequestBody
{
public string? Value { get; set; }
}
}

View File

@@ -0,0 +1,59 @@
using System;
using System.Reflection;
using System.Net;
using System.Net.Http;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using BasicDotnetTemplate.MainProject;
using BasicDotnetTemplate.MainProject.Models.Api.Response;
using Microsoft.Extensions.DependencyModel.Resolution;
using BasicDotnetTemplate.MainProject.Models.Api.Common.User;
using BasicDotnetTemplate.MainProject.Models.Api.Response.User;
using DatabaseSqlServer = BasicDotnetTemplate.MainProject.Models.Database.SqlServer;
using BasicDotnetTemplate.MainProject.Models.Api.Response.Auth;
using BasicDotnetTemplate.MainProject.Core.Middlewares;
using AutoMapper;
namespace BasicDotnetTemplate.MainProject.Tests;
[TestClass]
public class AutoMapperConfiguration_Tests
{
private IMapper? _mapper;
[TestInitialize]
public void Setup()
{
var config = new MapperConfiguration(cfg =>
{
cfg.AddProfile<AutoMapperConfiguration>();
});
_mapper = config.CreateMapper();
}
[TestMethod]
public void Mapper_UserDto()
{
try
{
DatabaseSqlServer.User user = ModelsInit.CreateUser();
UserDto? data = _mapper?.Map<UserDto>(user);
Assert.AreEqual(user.Guid, data?.Guid);
Assert.AreEqual(user.FirstName, data?.FirstName);
Assert.AreEqual(user.LastName, data?.LastName);
Assert.AreEqual(user.Email, data?.Email);
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException);
Assert.Fail($"An exception was thrown: {ex}");
}
}
}

View File

@@ -0,0 +1,44 @@
{
"AppSettings" :
{
"Settings": {
"Name": "MainProject",
"Version": "v1.0",
"Description": "This template contains basic configuration for a .Net 8 backend"
},
"DatabaseSettings": {
"SqlServerConnectionString": "SQLSERVER_DB_SERVER",
"MongoDbConnectionString": "MONGO_DB_SERVER",
"PostgreSQLConnectionString": "POSTGRESQL_DB_SERVER"
},
"OpenApiSettings": {
"TermsOfServiceUrl": "",
"OpenApiContact": {
"Name": "",
"Url": ""
},
"OpenApiLicense": {
"Name": "MIT License",
"Url": "https://github.com/csimonapastore/BasicDotnetTemplate/blob/main/LICENSE.md"
}
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"JwtSettings": {
"ValidAudience": "http://localhost:4200",
"ValidIssuer": "http://localhost:5000",
"Secret": "JWTAuthenticationHIGHsecuredPasswordVVVp1OH7Xzyr",
"ExpiredAfterMinsOfInactivity": 15
},
"EncryptionSettings": {
"SaltKey": "S7VIidfXQf1tOQYX",
"Salt": "u5CZAwq9vLGysC",
"Iterations": 10
}
}
}

View File

@@ -0,0 +1,27 @@
{
"AppSettings" :
{
"Settings": {
"Name": "MainProject",
"Version": "v1.0",
"Description": "This template contains basic configuration for a .Net 8 backend"
},
"DatabaseSettings": {
"SqlServerConnectionString": "SQLSERVER_DB_SERVER",
"MongoDbConnectionString": "MONGO_DB_SERVER",
"PostgreSQLConnectionString": "POSTGRESQL_DB_SERVER"
},
"OpenApiSettings": {
"TermsOfServiceUrl": "https://github.com/csimonapastore/BasicDotnetTemplate/blob/main/LICENSE.md",
"OpenApiContact": {
"Name": "README",
"Url": "https://github.com/csimonapastore/BasicDotnetTemplate/blob/main/README.md"
},
"OpenApiLicense": {
"Name": "MIT License",
"Url": "https://github.com/csimonapastore/BasicDotnetTemplate/blob/main/LICENSE.md"
}
}
}
}

View File

@@ -0,0 +1,7 @@
{
"AppSettings" :
{
}
}

View File

@@ -0,0 +1,44 @@
{
"AppSettings" :
{
"Settings": {
"Name": "MainProject",
"Version": "v1.0",
"Description": "This template contains basic configuration for a .Net 8 backend"
},
"DatabaseSettings": {
"SqlServerConnectionString": "SQLSERVER_DB_SERVER",
"MongoDbConnectionString": "MONGO_DB_SERVER",
"PostgreSQLConnectionString": "POSTGRESQL_DB_SERVER"
},
"OpenApiSettings": {
"TermsOfServiceUrl": "",
"OpenApiContact": {
"Name": "",
"Url": ""
},
"OpenApiLicense": {
"Name": "MIT License",
"Url": "https://github.com/csimonapastore/BasicDotnetTemplate/blob/main/LICENSE.md"
}
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"JwtSettings": {
"ValidAudience": "http://localhost:4200",
"ValidIssuer": "http://localhost:5000",
"Secret": "JWTAuthenticationHIGHsecuredPasswordVVVp1OH7Xzyr",
"ExpiredAfterMinsOfInactivity": 15
},
"EncryptionSettings": {
"SaltKey": "AAAAA",
"Salt": "",
"Iterations": 10
}
}
}

View File

@@ -2,7 +2,7 @@
"AppSettings" :
{
"Settings": {
"Name": "BasicDotnetTemplate",
"Name": "MainProject",
"Version": "v1.0",
"Description": "This template contains basic configuration for a .Net 8 backend"
},

View File

@@ -0,0 +1,16 @@
{
"AppSettings" :
{
"Settings": {
"Name": "MainProject",
"Version": "v1.0",
"Description": "This template contains basic configuration for a .Net 8 backend"
},
"DatabaseSettings": {
"SqlServerConnectionString": "",
"MongoDbConnectionString": "",
"PostgreSQLConnectionString": ""
}
}
}

View File

@@ -0,0 +1,40 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="coverlet.collector" Version="6.0.4">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="9.0.6" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />
<PackageReference Include="Moq" Version="4.20.72" />
<PackageReference Include="MSTest.TestAdapter" Version="3.9.3" />
<PackageReference Include="MSTest.TestFramework" Version="3.9.3" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
</ItemGroup>
<ItemGroup>
<Using Include="Microsoft.VisualStudio.TestTools.UnitTesting" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\MainProject\MainProject.csproj" />
</ItemGroup>
<ItemGroup>
<Content Include="JsonData/**" CopyToOutputDirectory="Always" CopyToPublishDirectory="Always" />
</ItemGroup>
<ItemGroup>
<Content Include="Config/**" CopyToOutputDirectory="Always" CopyToPublishDirectory="Always" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,36 @@
using System;
using System.Reflection;
using System.Net;
using System.Net.Http;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using BasicDotnetTemplate.MainProject;
using BasicDotnetTemplate.MainProject.Models.Api.Response;
using Microsoft.Extensions.DependencyModel.Resolution;
using BasicDotnetTemplate.MainProject.Models.Api.Common.User;
using BasicDotnetTemplate.MainProject.Models.Api.Common.Role;
using DatabaseSqlServer = BasicDotnetTemplate.MainProject.Models.Database.SqlServer;
using BasicDotnetTemplate.MainProject.Models.Api.Response.Auth;
namespace BasicDotnetTemplate.MainProject.Tests;
[TestClass]
public class UserRole_Tests
{
[TestMethod]
public void InitializeUserRoleFromRole()
{
try
{
DatabaseSqlServer.Role role = ModelsInit.CreateRole();
UserRole userRole = new(role);
Assert.AreEqual(role.Name, userRole.Name);
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException);
Assert.Fail($"An exception was thrown: {ex}");
}
}
}

View File

@@ -0,0 +1,39 @@
using System;
using System.Reflection;
using System.Net;
using System.Net.Http;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using BasicDotnetTemplate.MainProject;
using BasicDotnetTemplate.MainProject.Models.Api.Response;
using Microsoft.Extensions.DependencyModel.Resolution;
using BasicDotnetTemplate.MainProject.Models.Api.Common.User;
using BasicDotnetTemplate.MainProject.Models.Api.Common.Role;
using DatabaseSqlServer = BasicDotnetTemplate.MainProject.Models.Database.SqlServer;
using BasicDotnetTemplate.MainProject.Models.Api.Response.Auth;
namespace BasicDotnetTemplate.MainProject.Tests;
[TestClass]
public class AuthenticatedUser_Tests
{
[TestMethod]
public void InitializeAuthenticatedUserFromUser()
{
try
{
DatabaseSqlServer.User user = ModelsInit.CreateUser();
AuthenticatedUser authenticatedUser = new AuthenticatedUser(user);
Assert.AreEqual(user.FirstName, authenticatedUser.FirstName);
Assert.AreEqual(user.LastName, authenticatedUser.LastName);
Assert.AreEqual(user.Email, authenticatedUser.Email);
Assert.IsInstanceOfType(authenticatedUser.Role, typeof(UserRole));
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException);
Assert.Fail($"An exception was thrown: {ex}");
}
}
}

View File

@@ -0,0 +1,81 @@
using System;
using System.Reflection;
using System.Net;
using System.Net.Http;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using BasicDotnetTemplate.MainProject;
using BasicDotnetTemplate.MainProject.Models.Api.Response;
using Microsoft.Extensions.DependencyModel.Resolution;
using Microsoft.AspNetCore.Http;
namespace BasicDotnetTemplate.MainProject.Tests;
[TestClass]
public class ApiResponse_Tests
{
[TestMethod]
public void IstantiateBaseResponse_OnlyStatus_Valid()
{
try
{
var baseResponse = new BaseResponse<object>(200, null, null);
Assert.IsTrue(baseResponse.Status == StatusCodes.Status200OK && String.IsNullOrEmpty(baseResponse.Message) && baseResponse.Data == null);
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException);
Assert.Fail($"An exception was thrown: {ex}");
}
}
[TestMethod]
public void IstantiateBaseResponse_OnlyStatus_IsInvalid()
{
try
{
var baseResponse = new BaseResponse<object>(201, null, null);
Assert.AreNotEqual(StatusCodes.Status200OK, baseResponse.Status);
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException);
Assert.Fail($"An exception was thrown: {ex}");
}
}
[TestMethod]
public void IstantiateBaseResponse_StatusAndMessage_Valid()
{
try
{
var baseResponse = new BaseResponse<object>(200, "This is a test message", null);
Assert.IsTrue(baseResponse.Status == StatusCodes.Status200OK && baseResponse.Message == "This is a test message" && baseResponse.Data == null);
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException);
Assert.Fail($"An exception was thrown: {ex}");
}
}
[TestMethod]
public void IstantiateBaseResponse_AllFields_Valid()
{
try
{
string[] data = { "Volvo", "BMW", "Ford", "Mazda" };
var baseResponse = new BaseResponse<string[]>(200, "This is a test message", data);
Assert.IsTrue(baseResponse.Status == StatusCodes.Status200OK && baseResponse.Message == "This is a test message" && baseResponse.Data == data);
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException);
Assert.Fail($"An exception was thrown: {ex}");
}
}
}

View File

@@ -0,0 +1,86 @@
using System;
using System.Reflection;
using System.Net;
using System.Net.Http;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using BasicDotnetTemplate.MainProject;
using BasicDotnetTemplate.MainProject.Models.Api.Response;
using Microsoft.Extensions.DependencyModel.Resolution;
using BasicDotnetTemplate.MainProject.Models.Api.Common.User;
using BasicDotnetTemplate.MainProject.Models.Api.Common.Role;
using DatabaseSqlServer = BasicDotnetTemplate.MainProject.Models.Database.SqlServer;
using BasicDotnetTemplate.MainProject.Models.Api.Response.Auth;
using Microsoft.AspNetCore.Http;
namespace BasicDotnetTemplate.MainProject.Tests;
[TestClass]
public class AuthenticateResponse_Tests
{
[TestMethod]
public void IstantiateAuthenticateResponse_OnlyStatus_Valid()
{
try
{
var authenticateResponse = new AuthenticateResponse(200, null, null);
Assert.IsTrue(authenticateResponse.Status == StatusCodes.Status200OK && String.IsNullOrEmpty(authenticateResponse.Message) && authenticateResponse.Data == null);
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException);
Assert.Fail($"An exception was thrown: {ex}");
}
}
[TestMethod]
public void IstantiateAuthenticateResponse_OnlyStatus_IsInvalid()
{
try
{
var authenticateResponse = new AuthenticateResponse(201, null, null);
Assert.AreNotEqual(StatusCodes.Status200OK, authenticateResponse.Status);
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException);
Assert.Fail($"An exception was thrown: {ex}");
}
}
[TestMethod]
public void IstantiateAuthenticateResponse_StatusAndMessage_Valid()
{
try
{
var authenticateResponse = new AuthenticateResponse(200, "This is a test message", null);
Assert.IsTrue(authenticateResponse.Status == StatusCodes.Status200OK && authenticateResponse.Message == "This is a test message" && authenticateResponse.Data == null);
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException);
Assert.Fail($"An exception was thrown: {ex}");
}
}
[TestMethod]
public void IstantiateAuthenticateResponse_AllFields_Valid()
{
try
{
DatabaseSqlServer.User user = ModelsInit.CreateUser();
AuthenticatedUser data = new AuthenticatedUser(user);
var authenticateResponse = new AuthenticateResponse(200, "This is a test message", data);
Assert.IsTrue(authenticateResponse.Status == StatusCodes.Status200OK && authenticateResponse.Message == "This is a test message" && authenticateResponse.Data == data);
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException);
Assert.Fail($"An exception was thrown: {ex}");
}
}
}

View File

@@ -0,0 +1,102 @@
using System;
using System.Reflection;
using System.Net;
using System.Net.Http;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using BasicDotnetTemplate.MainProject;
using BasicDotnetTemplate.MainProject.Models.Api.Response;
using Microsoft.Extensions.DependencyModel.Resolution;
using BasicDotnetTemplate.MainProject.Models.Api.Common.Role;
using BasicDotnetTemplate.MainProject.Models.Api.Response.Role;
using DatabaseSqlServer = BasicDotnetTemplate.MainProject.Models.Database.SqlServer;
using BasicDotnetTemplate.MainProject.Models.Api.Response.Auth;
using BasicDotnetTemplate.MainProject.Core.Middlewares;
using AutoMapper;
using Microsoft.AspNetCore.Http;
namespace BasicDotnetTemplate.MainProject.Tests;
[TestClass]
public class GetRoleResponse_Tests
{
private IMapper? _mapper;
[TestInitialize]
public void Setup()
{
var config = new MapperConfiguration(cfg =>
{
cfg.AddProfile<AutoMapperConfiguration>();
});
_mapper = config.CreateMapper();
}
[TestMethod]
public void IstantiateGetRoleResponse_OnlyStatus_Valid()
{
try
{
var getRoleResponse = new GetRoleResponse(200, null, null);
Assert.IsTrue(getRoleResponse.Status == StatusCodes.Status200OK && String.IsNullOrEmpty(getRoleResponse.Message) && getRoleResponse.Data == null);
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException);
Assert.Fail($"An exception was thrown: {ex}");
}
}
[TestMethod]
public void IstantiateGetRoleResponse_OnlyStatus_IsInvalid()
{
try
{
var getRoleResponse = new GetRoleResponse(201, null, null);
Assert.AreNotEqual(StatusCodes.Status200OK, getRoleResponse.Status);
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException);
Assert.Fail($"An exception was thrown: {ex}");
}
}
[TestMethod]
public void IstantiateGetRoleResponse_StatusAndMessage_Valid()
{
try
{
var getRoleResponse = new GetRoleResponse(200, "This is a test message", null);
Assert.IsTrue(getRoleResponse.Status == StatusCodes.Status200OK && getRoleResponse.Message == "This is a test message" && getRoleResponse.Data == null);
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException);
Assert.Fail($"An exception was thrown: {ex}");
}
}
[TestMethod]
public void IstantiateGetRoleResponse_AllFields_Valid()
{
try
{
DatabaseSqlServer.Role role = ModelsInit.CreateRole();
RoleDto? data = _mapper?.Map<RoleDto>(role);
var getRoleResponse = new GetRoleResponse(200, "This is a test message", data);
Assert.IsTrue(getRoleResponse.Status == StatusCodes.Status200OK && getRoleResponse.Message == "This is a test message" && getRoleResponse.Data == data);
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException);
Assert.Fail($"An exception was thrown: {ex}");
}
}
}

View File

@@ -0,0 +1,102 @@
using System;
using System.Reflection;
using System.Net;
using System.Net.Http;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using BasicDotnetTemplate.MainProject;
using BasicDotnetTemplate.MainProject.Models.Api.Response;
using Microsoft.Extensions.DependencyModel.Resolution;
using BasicDotnetTemplate.MainProject.Models.Api.Common.User;
using BasicDotnetTemplate.MainProject.Models.Api.Response.User;
using DatabaseSqlServer = BasicDotnetTemplate.MainProject.Models.Database.SqlServer;
using BasicDotnetTemplate.MainProject.Models.Api.Response.Auth;
using BasicDotnetTemplate.MainProject.Core.Middlewares;
using AutoMapper;
using Microsoft.AspNetCore.Http;
namespace BasicDotnetTemplate.MainProject.Tests;
[TestClass]
public class GetUserResponse_Tests
{
private IMapper? _mapper;
[TestInitialize]
public void Setup()
{
var config = new MapperConfiguration(cfg =>
{
cfg.AddProfile<AutoMapperConfiguration>();
});
_mapper = config.CreateMapper();
}
[TestMethod]
public void IstantiateGetUserResponse_OnlyStatus_Valid()
{
try
{
var getUserResponse = new GetUserResponse(200, null, null);
Assert.IsTrue(getUserResponse.Status == StatusCodes.Status200OK && String.IsNullOrEmpty(getUserResponse.Message) && getUserResponse.Data == null);
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException);
Assert.Fail($"An exception was thrown: {ex}");
}
}
[TestMethod]
public void IstantiateGetUserResponse_OnlyStatus_IsInvalid()
{
try
{
var getUserResponse = new GetUserResponse(201, null, null);
Assert.AreNotEqual(StatusCodes.Status200OK, getUserResponse.Status);
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException);
Assert.Fail($"An exception was thrown: {ex}");
}
}
[TestMethod]
public void IstantiateGetUserResponse_StatusAndMessage_Valid()
{
try
{
var getUserResponse = new GetUserResponse(200, "This is a test message", null);
Assert.IsTrue(getUserResponse.Status == StatusCodes.Status200OK && getUserResponse.Message == "This is a test message" && getUserResponse.Data == null);
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException);
Assert.Fail($"An exception was thrown: {ex}");
}
}
[TestMethod]
public void IstantiateGetUserResponse_AllFields_Valid()
{
try
{
DatabaseSqlServer.User user = ModelsInit.CreateUser();
UserDto? data = _mapper?.Map<UserDto>(user);
var getUserResponse = new GetUserResponse(200, "This is a test message", data);
Assert.IsTrue(getUserResponse.Status == StatusCodes.Status200OK && getUserResponse.Message == "This is a test message" && getUserResponse.Data == data);
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException);
Assert.Fail($"An exception was thrown: {ex}");
}
}
}

View File

@@ -0,0 +1,100 @@
using System;
using System.Reflection;
using System.Net;
using System.Net.Http;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using BasicDotnetTemplate.MainProject;
using BasicDotnetTemplate.MainProject.Models.Api.Response;
using Microsoft.Extensions.DependencyModel.Resolution;
using BasicDotnetTemplate.MainProject.Models.Settings;
using Microsoft.AspNetCore.Http;
namespace BasicDotnetTemplate.MainProject.Tests;
[TestClass]
public class Settings_Tests
{
[TestMethod]
public void IstantiatePrivateSettings_Valid()
{
try
{
var sqlServer = "Data Source=localhost; Initial Catalog=YourDatabase; User Id=YourUsername; Password=YourPassword;";
var mongodb = "mongodb://localhost:27017";
var postgres = "Server=localhost; Port=5432; Database=YourDatabase; User Id=YourUsername; Password=YourPassword;";
var privateSettings = new PrivateSettings()
{
DatabaseConnection = new DatabaseConnection()
{
SqlServer = sqlServer,
Mongodb = mongodb,
Postgres = postgres,
}
};
Assert.IsTrue(
privateSettings.DatabaseConnection != null &&
privateSettings.DatabaseConnection.SqlServer == sqlServer &&
privateSettings.DatabaseConnection.Mongodb == mongodb &&
privateSettings.DatabaseConnection.Postgres == postgres
);
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException);
Assert.Fail($"An exception was thrown: {ex}");
}
}
[TestMethod]
public void IstantiateBaseResponse_OnlyStatus_IsInvalid()
{
try
{
var baseResponse = new BaseResponse<object>(201, null, null);
Assert.AreNotEqual(StatusCodes.Status200OK, baseResponse.Status);
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException);
Assert.Fail($"An exception was thrown: {ex}");
}
}
[TestMethod]
public void IstantiateBaseResponse_StatusAndMessage_Valid()
{
try
{
var baseResponse = new BaseResponse<object>(200, "This is a test message", null);
Assert.IsTrue(baseResponse.Status == StatusCodes.Status200OK && baseResponse.Message == "This is a test message" && baseResponse.Data == null);
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException);
Assert.Fail($"An exception was thrown: {ex}");
}
}
[TestMethod]
public void IstantiateBaseResponse_AllFields_Valid()
{
try
{
string[] data = { "Volvo", "BMW", "Ford", "Mazda" };
var baseResponse = new BaseResponse<string[]>(200, "This is a test message", data);
Assert.IsTrue(baseResponse.Status == StatusCodes.Status200OK && baseResponse.Message == "This is a test message" && baseResponse.Data == data);
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException);
Assert.Fail($"An exception was thrown: {ex}");
}
}
}

View File

@@ -0,0 +1,76 @@
using System;
using System.Reflection;
using System.Net;
using System.Net.Http;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using BasicDotnetTemplate.MainProject;
namespace BasicDotnetTemplate.MainProject.Tests;
[TestClass]
public class Program_Tests
{
[TestMethod]
public void Program_Configuration_IsValid()
{
Environment.SetEnvironmentVariable("ASPNETCORE_ENVIRONMENT", "Development");
try
{
var reflectionType = typeof(ReflectionProgram);
if (reflectionType != null)
{
MethodInfo[] methods = reflectionType.GetMethods(); //Using BindingFlags.NonPublic does not show any results
MethodInfo? execute = null;
foreach (MethodInfo m in methods)
{
if (m.Name == "LaunchConfiguration")
{
execute = m;
}
}
if (execute != null)
{
object? initializeObj = execute != null ? execute.Invoke(null, Array.Empty<object>()) : throw new ArgumentNullException("LaunchConfiguration not found");
MethodInfo? initialize = initializeObj != null ? (MethodInfo)initializeObj : throw new ArgumentNullException("Unable to convert object because execute.Invoke is null");
if (initialize != null)
{
var success = false;
try
{
initialize.Invoke(null, new object[] { Array.Empty<string>() });
success = true;
}
catch (Exception innerException)
{
Assert.Fail($"An exception was thrown during initialize.Invoke: {innerException.Message}");
}
Assert.IsTrue(success);
}
else
{
Assert.Fail("Initialize is null.");
}
}
else
{
Assert.Fail("Initialize method not found in Program class.");
}
}
else
{
Assert.Fail("Program class not found in the assembly.");
}
}
catch (Exception ex)
{
Assert.Fail($"An exception was thrown: {ex}");
}
}
}

View File

@@ -0,0 +1,114 @@
using BasicDotnetTemplate.MainProject.Models.Settings;
using Microsoft.AspNetCore.Builder;
using Microsoft.EntityFrameworkCore;
using BasicDotnetTemplate.MainProject.Utils;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Configuration;
using Moq;
using Newtonsoft.Json;
using BasicDotnetTemplate.MainProject.Core.Database;
using BasicDotnetTemplate.MainProject.Services;
using BasicDotnetTemplate.MainProject.Models.Api.Response;
using BasicDotnetTemplate.MainProject.Models.Api.Request.Auth;
using BasicDotnetTemplate.MainProject.Models.Api.Data.Auth;
using BasicDotnetTemplate.MainProject.Models.Api.Common.User;
using BasicDotnetTemplate.MainProject.Models.Api.Common.Role;
using BasicDotnetTemplate.MainProject.Models.Api.Response.Auth;
using DatabaseSqlServer = BasicDotnetTemplate.MainProject.Models.Database.SqlServer;
namespace BasicDotnetTemplate.MainProject.Tests;
[TestClass]
public class AuthService_Tests
{
[TestMethod]
public void Inizialize()
{
try
{
var authService = TestUtils.CreateAuthService();
if (authService != null)
{
Assert.IsInstanceOfType(authService, typeof(AuthService));
}
else
{
Assert.Fail($"AuthService is null");
}
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException);
Assert.Fail($"An exception was thrown: {ex}");
}
}
[TestMethod]
public async Task AuthenticateAsync_UserNotFound()
{
try
{
var request = new AuthenticateRequest
{
Data = new AuthenticateRequestData
{
Email = "d2ejdI1f4GYpq2kTB1nmeQkZXqR3QSxH8Yqkl7iv7zgfQ13qG/0dUUsreG/WGHWRBE5mVWaV43A=",
Password = "d2ejdI1f4GYpq2kTB1nmeQkZXqR3QSxH8Yqkl7iv7zgfQ13qG/0dUUsreG/WGHWRBE5mVWaV43A="
}
};
var authService = TestUtils.CreateAuthService();
if (authService != null)
{
var authenticatedUser = await authService.AuthenticateAsync(request.Data);
Assert.IsNull(authenticatedUser);
}
else
{
Assert.Fail($"AuthService is null");
}
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException);
Assert.Fail($"An exception was thrown: {ex}");
}
}
[TestMethod]
public async Task AuthenticateAsync_UsernamePasswordInvalid()
{
try
{
var request = new AuthenticateRequest
{
Data = new AuthenticateRequestData
{
Email = "WGHWRBE5mVWaV=",
Password = "WGHWRBE5mVWaV="
}
};
var authService = TestUtils.CreateAuthService();
if (authService != null)
{
var authenticatedUser = await authService.AuthenticateAsync(request.Data);
Assert.IsNull(authenticatedUser);
}
else
{
Assert.Fail($"AuthService is null");
}
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException);
Assert.Fail($"An exception was thrown: {ex}");
}
}
}

View File

@@ -0,0 +1,76 @@
using BasicDotnetTemplate.MainProject.Models.Settings;
using Microsoft.AspNetCore.Builder;
using Microsoft.EntityFrameworkCore;
using BasicDotnetTemplate.MainProject.Utils;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Configuration;
using Moq;
using Newtonsoft.Json;
using BasicDotnetTemplate.MainProject.Core.Database;
using BasicDotnetTemplate.MainProject.Services;
using BasicDotnetTemplate.MainProject.Models.Api.Response;
using BasicDotnetTemplate.MainProject.Models.Api.Request.Auth;
using BasicDotnetTemplate.MainProject.Models.Api.Data.Auth;
using BasicDotnetTemplate.MainProject.Models.Api.Response.Auth;
using DatabaseSqlServer = BasicDotnetTemplate.MainProject.Models.Database.SqlServer;
namespace BasicDotnetTemplate.MainProject.Tests;
[TestClass]
public class JwtService_Tests
{
[TestMethod]
public void Inizialize()
{
try
{
var jwtService = TestUtils.CreateJwtService();
if (jwtService != null)
{
Assert.IsInstanceOfType(jwtService, typeof(JwtService));
}
else
{
Assert.Fail($"JwtService is null");
}
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException);
Assert.Fail($"An exception was thrown: {ex}");
}
}
[TestMethod]
public void GenerateToken()
{
try
{
var jwtService = TestUtils.CreateJwtService();
var testString = "test";
if (jwtService != null)
{
var jwt = jwtService.GenerateToken(testString);
Assert.IsNotNull(jwt);
Assert.IsInstanceOfType(jwt, typeof(string));
}
else
{
Assert.Fail($"JwtService is null");
}
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException);
Assert.Fail($"An exception was thrown: {ex}");
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,437 @@
using BasicDotnetTemplate.MainProject.Services;
using BasicDotnetTemplate.MainProject.Models.Api.Data.Role;
using BasicDotnetTemplate.MainProject.Models.Database.SqlServer;
using Newtonsoft.Json;
using BasicDotnetTemplate.MainProject.Models.Api.Common.Exceptions;
namespace BasicDotnetTemplate.MainProject.Tests;
[TestClass]
public class RoleService_Tests
{
private static Role? _expectedRole = ModelsInit.CreateRole();
private static Role? _role;
private static RoleService _roleService = TestUtils.CreateRoleService();
[TestMethod]
public void Inizialize()
{
try
{
var roleService = TestUtils.CreateRoleService();
if (roleService != null)
{
Assert.IsInstanceOfType(roleService, typeof(RoleService));
}
else
{
Assert.Fail($"RoleService is null");
}
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException);
Assert.Fail($"An exception was thrown: {ex}");
}
}
[TestMethod]
public async Task CheckIfNameIsValid_NameNotExists()
{
try
{
var expectedRole = ModelsInit.CreateRole();
if (_roleService != null)
{
var valid = await _roleService.CheckIfNameIsValid(expectedRole.Name);
Assert.IsTrue(valid);
}
else
{
Assert.Fail($"RoleService is null");
}
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException);
Assert.Fail($"An exception was thrown: {ex}");
}
}
[TestMethod]
public async Task CreateRoleAsync_Success()
{
try
{
CreateRoleRequestData data = new CreateRoleRequestData()
{
Name = _expectedRole?.Name ?? String.Empty,
IsNotEditable = false
};
if (_roleService != null)
{
var role = await _roleService.CreateRoleAsync(data);
Assert.IsInstanceOfType(role, typeof(Role));
Assert.IsNotNull(role);
Assert.AreEqual(_expectedRole?.Name, role.Name);
Assert.AreEqual(_expectedRole?.IsNotEditable, role.IsNotEditable);
_role = role;
}
else
{
Assert.Fail($"RoleService is null");
}
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException);
Assert.Fail($"An exception was thrown: {ex}");
}
}
[TestMethod]
public async Task CreateRoleAsync_Exception()
{
try
{
CreateRoleRequestData data = new CreateRoleRequestData()
{
Name = "Exception",
IsNotEditable = false
};
var exceptionRoleService = TestUtils.CreateRoleServiceException();
if (exceptionRoleService != null)
{
try
{
var role = await exceptionRoleService.CreateRoleAsync(data);
Assert.Fail($"Expected exception instead of response: {role?.Guid}");
}
catch (Exception exception)
{
Assert.IsInstanceOfType(exception, typeof(Exception));
Assert.IsInstanceOfType(exception, typeof(CreateException));
}
}
else
{
Assert.Fail($"RoleService is null");
}
}
catch (Exception ex)
{
Assert.Fail($"An exception was thrown: {ex}");
}
}
[TestMethod]
public async Task CheckIfNameIsValid_NameCurrentRole()
{
try
{
var expectedRole = ModelsInit.CreateRole();
if (_roleService != null)
{
var valid = await _roleService.CheckIfNameIsValid(expectedRole.Name, _role?.Guid ?? String.Empty);
Assert.IsTrue(valid);
}
else
{
Assert.Fail($"RoleService is null");
}
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException);
Assert.Fail($"An exception was thrown: {ex}");
}
}
[TestMethod]
public async Task CheckIfNameIsValid_NameAlreadyExists()
{
try
{
var expectedRole = ModelsInit.CreateRole();
if (_roleService != null)
{
var valid = await _roleService.CheckIfNameIsValid(expectedRole.Name);
Assert.IsFalse(valid);
}
else
{
Assert.Fail($"RoleService is null");
}
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException);
Assert.Fail($"An exception was thrown: {ex}");
}
}
[TestMethod]
public async Task GetRoleByIdAsync()
{
try
{
if (_roleService != null)
{
var role = await _roleService.GetRoleByIdAsync(_role?.Id ?? 0);
Assert.IsNotNull(role);
Assert.AreEqual(_role?.Id, _role?.Id);
}
else
{
Assert.Fail($"RoleService is null");
}
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException);
Assert.Fail($"An exception was thrown: {ex}");
}
}
[TestMethod]
public async Task GetRoleByGuidAsync()
{
try
{
if (_roleService != null)
{
var role = await _roleService.GetRoleByGuidAsync(_role?.Guid ?? String.Empty);
Assert.IsNotNull(role);
Assert.AreEqual(_role?.Guid, role.Guid);
}
else
{
Assert.Fail($"RoleService is null");
}
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException);
Assert.Fail($"An exception was thrown: {ex}");
}
}
[TestMethod]
public async Task GetRoleByGuidAsync_CurrentRole()
{
try
{
if (_roleService != null)
{
var role = await _roleService.GetRoleForUser(_role?.Guid);
Assert.IsNotNull(role);
Assert.AreEqual(_role?.Guid, role.Guid);
}
else
{
Assert.Fail($"RoleService is null");
}
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException);
Assert.Fail($"An exception was thrown: {ex}");
}
}
[TestMethod]
public async Task GetRoleByGuidAsync_Default()
{
try
{
if (_roleService != null)
{
CreateRoleRequestData data = new()
{
Name = "Default",
IsNotEditable = true
};
var roleCreated = await _roleService.CreateRoleAsync(data);
var role = await _roleService.GetRoleForUser(String.Empty);
Assert.IsNotNull(role);
Assert.AreEqual(role?.Guid, roleCreated?.Guid);
Assert.AreEqual("Default", role?.Name);
}
else
{
Assert.Fail($"RoleService is null");
}
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException);
Assert.Fail($"An exception was thrown: {ex}");
}
}
[TestMethod]
public async Task GetRoleByGuidAsync_Null()
{
try
{
if (_roleService != null)
{
var role = await _roleService.GetRoleForUser(Guid.NewGuid().ToString());
Assert.IsNull(role);
}
else
{
Assert.Fail($"RoleService is null");
}
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException);
Assert.Fail($"An exception was thrown: {ex}");
}
}
[TestMethod]
public async Task UpdateRoleAsync_Success()
{
try
{
CreateRoleRequestData data = new CreateRoleRequestData()
{
Name = "ChangedRoleName",
IsNotEditable = false
};
if (_roleService != null)
{
Assert.IsNotNull(_role);
var role = await _roleService.UpdateRoleAsync(data, _role!);
Assert.IsInstanceOfType(role, typeof(Role));
Assert.IsNotNull(role);
Assert.AreEqual(data.Name, role.Name);
Assert.AreEqual(data.IsNotEditable, role.IsNotEditable);
_role = role;
}
else
{
Assert.Fail($"RoleService is null");
}
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException);
Assert.Fail($"An exception was thrown: {ex}");
}
}
[TestMethod]
public async Task UpdateRoleAsync_NotEditable()
{
try
{
CreateRoleRequestData createRoleData = new CreateRoleRequestData()
{
Name = "NotEditableRole",
IsNotEditable = true
};
if (_roleService != null)
{
var role = await _roleService.CreateRoleAsync(createRoleData);
Assert.IsNotNull(role);
CreateRoleRequestData updateRoleData = new CreateRoleRequestData()
{
Name = "TryingToEditRole",
IsNotEditable = false
};
var roleUpdatedRole = await _roleService.UpdateRoleAsync(updateRoleData, role!);
Assert.IsInstanceOfType(roleUpdatedRole, typeof(Role));
Assert.IsNotNull(roleUpdatedRole);
Assert.AreEqual(createRoleData.Name, roleUpdatedRole.Name);
Assert.AreEqual(createRoleData.IsNotEditable, roleUpdatedRole.IsNotEditable);
}
else
{
Assert.Fail($"RoleService is null");
}
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException);
Assert.Fail($"An exception was thrown: {ex}");
}
}
[TestMethod]
public async Task UpdateRoleAsync_Exception()
{
try
{
CreateRoleRequestData data = new CreateRoleRequestData()
{
Name = "Exception",
IsNotEditable = false
};
var exceptionRoleService = TestUtils.CreateRoleServiceException();
if (exceptionRoleService != null)
{
Assert.IsNotNull(_role);
var role = await exceptionRoleService.UpdateRoleAsync(data, _role!);
Assert.Fail($"Expected exception instead of response: {role?.Guid}");
}
else
{
Assert.Fail($"RoleService is null");
}
}
catch (Exception ex)
{
Assert.IsInstanceOfType(ex, typeof(Exception));
}
}
[TestMethod]
public async Task DeleteRoleAsync()
{
try
{
if (_roleService != null)
{
var role = await _roleService.GetRoleByGuidAsync(_role?.Guid ?? String.Empty);
Assert.IsNotNull(role);
var deleted = await _roleService.DeleteRoleAsync(role);
Assert.IsTrue(deleted);
}
else
{
Assert.Fail($"RoleService is null");
}
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException);
Assert.Fail($"An exception was thrown: {ex}");
}
}
}

View File

@@ -0,0 +1,501 @@
using BasicDotnetTemplate.MainProject.Services;
using BasicDotnetTemplate.MainProject.Models.Api.Data.User;
using BasicDotnetTemplate.MainProject.Models.Database.SqlServer;
using Newtonsoft.Json;
using BasicDotnetTemplate.MainProject.Models.Api.Common.Exceptions;
namespace BasicDotnetTemplate.MainProject.Tests;
[TestClass]
public class UserService_Tests
{
private static User _user = ModelsInit.CreateUser();
private static UserService _userService = TestUtils.CreateUserService();
[TestMethod]
public void Inizialize()
{
try
{
var userService = TestUtils.CreateUserService();
if (userService != null)
{
Assert.IsInstanceOfType(userService, typeof(UserService));
}
else
{
Assert.Fail($"UserService is null");
}
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException);
Assert.Fail($"An exception was thrown: {ex.Message}");
}
}
[TestMethod]
public async Task CheckIfEmailIsValid_EmailNotExists()
{
try
{
if (_userService != null)
{
var valid = await _userService.CheckIfEmailIsValid(_user.Email ?? String.Empty);
Assert.IsTrue(valid);
}
else
{
Assert.Fail($"UserService is null");
}
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException);
Assert.Fail($"An exception was thrown: {ex}");
}
}
[TestMethod]
public async Task CreateUserAsync_Success()
{
try
{
var expectedUser = ModelsInit.CreateUser();
CreateUserRequestData data = new CreateUserRequestData()
{
FirstName = expectedUser.FirstName ?? String.Empty,
LastName = expectedUser.LastName ?? String.Empty,
Email = expectedUser.Email ?? String.Empty,
Password = "Password"
};
Role role = new()
{
Name = expectedUser.Role?.Name ?? String.Empty,
IsNotEditable = expectedUser.Role?.IsNotEditable ?? false,
Guid = expectedUser.Role?.Guid ?? String.Empty
};
var user = await _userService.CreateUserAsync(data, role);
Assert.IsInstanceOfType(user, typeof(User));
Assert.IsNotNull(user);
Assert.AreEqual(expectedUser.FirstName, user.FirstName);
Assert.AreEqual(expectedUser.LastName, user.LastName);
Assert.AreEqual(expectedUser.Email, user.Email);
Assert.AreEqual(expectedUser.Role?.Name, user.Role?.Name);
Assert.AreEqual(10, user.PasswordIterations);
Assert.IsNotNull(expectedUser.PasswordSalt);
Assert.IsNotNull(expectedUser.PasswordPepper);
Assert.IsNotNull(expectedUser.Password);
_user = user;
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException);
Assert.Fail($"An exception was thrown: {ex}");
}
}
[TestMethod]
public async Task GetUserByUsernameAndPassword_Null()
{
try
{
if (_userService != null)
{
var user = await _userService.GetUserByUsernameAndPassword(_user.Email, "WrongPassword");
Assert.IsNull(user);
}
else
{
Assert.Fail($"UserService is null");
}
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException);
Assert.Fail($"An exception was thrown: {ex}");
}
}
[TestMethod]
public async Task GetUserByUsernameAndPassword_Success()
{
try
{
var password = "Password";
if (_userService != null)
{
var user = await _userService.GetUserByUsernameAndPassword(_user.Email, password);
Assert.IsNotNull(user);
}
else
{
Assert.Fail($"UserService is null");
}
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException);
Assert.Fail($"An exception was thrown: {ex}");
}
}
[TestMethod]
public async Task CreateUserAsync_Exception()
{
try
{
var expectedUser = ModelsInit.CreateUser();
CreateUserRequestData data = new CreateUserRequestData()
{
FirstName = expectedUser.FirstName ?? String.Empty,
LastName = expectedUser.LastName ?? String.Empty,
Email = expectedUser.Email ?? String.Empty,
Password = expectedUser.Password ?? String.Empty
};
Role role = new()
{
Name = expectedUser.Role?.Name ?? String.Empty,
IsNotEditable = expectedUser.Role?.IsNotEditable ?? false,
Guid = expectedUser.Role?.Guid ?? String.Empty
};
var exceptionUserService = TestUtils.CreateUserServiceException();
if (exceptionUserService != null)
{
try
{
var user = await exceptionUserService.CreateUserAsync(data, role);
Assert.Fail($"Expected exception instead of response: {user?.Guid}");
}
catch (Exception exception)
{
Assert.IsInstanceOfType(exception, typeof(Exception));
Assert.IsInstanceOfType(exception, typeof(CreateException));
}
}
else
{
Assert.Fail($"UserService is null");
}
}
catch (Exception ex)
{
Assert.Fail($"An exception was thrown: {ex}");
}
}
[TestMethod]
public async Task CheckIfEmailIsValid_EmailCurrentUser()
{
try
{
if (_userService != null)
{
var valid = await _userService.CheckIfEmailIsValid(_user.Email ?? String.Empty, _user.Guid ?? String.Empty);
Assert.IsTrue(valid);
}
else
{
Assert.Fail($"UserService is null");
}
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException);
Assert.Fail($"An exception was thrown: {ex}");
}
}
[TestMethod]
public async Task CheckIfEmailIsValid_EmailAlreadyExists()
{
try
{
if (_userService != null)
{
var valid = await _userService.CheckIfEmailIsValid(_user.Email ?? String.Empty);
Assert.IsFalse(valid);
}
else
{
Assert.Fail($"UserService is null");
}
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException);
Assert.Fail($"An exception was thrown: {ex}");
}
}
[TestMethod]
public async Task GetUserByIdAsync()
{
try
{
if (_userService != null)
{
var user = await _userService.GetUserByIdAsync(_user.Id);
Assert.IsNotNull(user);
Assert.AreEqual(user.Id, _user?.Id);
}
else
{
Assert.Fail($"UserService is null");
}
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException);
Assert.Fail($"An exception was thrown: {ex}");
}
}
[TestMethod]
public async Task GetUserByGuidAsync()
{
try
{
if (_userService != null)
{
var user = await _userService.GetUserByGuidAsync(_user.Guid ?? String.Empty);
Assert.IsNotNull(user);
Assert.AreEqual(user.Guid, _user?.Guid);
}
else
{
Assert.Fail($"UserService is null");
}
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException);
Assert.Fail($"An exception was thrown: {ex}");
}
}
[TestMethod]
public async Task UpdateUserAsync_Success()
{
try
{
UpdateUserRequestData data = new UpdateUserRequestData()
{
FirstName = "ChangedUserFirstName",
LastName = "ChangedUserLastName"
};
if (_userService != null)
{
Assert.IsNotNull(_user);
var user = await _userService.UpdateUserAsync(data, _user!);
Assert.IsInstanceOfType(user, typeof(User));
Assert.IsNotNull(user);
Assert.AreEqual(data.FirstName, user.FirstName);
Assert.AreEqual(data.LastName, user.LastName);
_user = user;
}
else
{
Assert.Fail($"UserService is null");
}
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException);
Assert.Fail($"An exception was thrown: {ex}");
}
}
[TestMethod]
public async Task UpdateUserAsync_Exception()
{
try
{
UpdateUserRequestData data = new UpdateUserRequestData()
{
FirstName = "ChangedUserFirstName",
LastName = "ChangedUserLastName"
};
var exceptionUserService = TestUtils.CreateUserServiceException();
if (exceptionUserService != null)
{
Assert.IsNotNull(_user);
var user = await exceptionUserService.UpdateUserAsync(data, _user!);
Assert.Fail($"Expected exception instead of response: {user?.Guid}");
}
else
{
Assert.Fail($"UserService is null");
}
}
catch (Exception ex)
{
Assert.IsInstanceOfType(ex, typeof(Exception));
}
}
[TestMethod]
public async Task UpdateUserPasswordAsync_Success()
{
try
{
if (_userService != null)
{
Assert.IsNotNull(_user);
var oldPassword = _user.Password;
var user = await _userService.UpdateUserPasswordAsync(_user!, "this-is-a-new-password");
Assert.IsInstanceOfType(user, typeof(User));
Assert.IsNotNull(user);
Assert.AreNotEqual(user.Password, oldPassword);
}
else
{
Assert.Fail($"UserService is null");
}
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException);
Assert.Fail($"An exception was thrown: {ex}");
}
}
[TestMethod]
public async Task UpdateUserPasswordAsync_Exception()
{
try
{
var exceptionUserService = TestUtils.CreateUserServiceException();
if (exceptionUserService != null)
{
Assert.IsNotNull(_user);
var user = await exceptionUserService.UpdateUserPasswordAsync(_user!, "this-is-a-new-password");
Assert.Fail($"Expected exception instead of response: {user?.Guid}");
}
else
{
Assert.Fail($"UserService is null");
}
}
catch (Exception ex)
{
Assert.IsInstanceOfType(ex, typeof(Exception));
}
}
[TestMethod]
public async Task UpdateUserRoleAsync_Success()
{
try
{
if (_userService != null)
{
Assert.IsNotNull(_user);
Role role = new()
{
Name = "NewRole",
IsNotEditable = false,
Guid = Guid.NewGuid().ToString()
};
var oldRole = _user.Role;
var user = await _userService.UpdateUserRoleAsync(_user!, role);
Assert.IsInstanceOfType(user, typeof(User));
Assert.IsNotNull(user);
Assert.AreNotEqual(user.Role?.Id, oldRole?.Id);
}
else
{
Assert.Fail($"UserService is null");
}
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException);
Assert.Fail($"An exception was thrown: {ex}");
}
}
[TestMethod]
public async Task UpdateUserRoleAsync_Exception()
{
try
{
var exceptionUserService = TestUtils.CreateUserServiceException();
if (exceptionUserService != null)
{
Assert.IsNotNull(_user);
Role role = new()
{
Name = "NewRole",
IsNotEditable = false,
Guid = Guid.NewGuid().ToString()
};
var user = await exceptionUserService.UpdateUserRoleAsync(_user!, role);
Assert.Fail($"Expected exception instead of response: {user?.Guid}");
}
else
{
Assert.Fail($"UserService is null");
}
}
catch (Exception ex)
{
Assert.IsInstanceOfType(ex, typeof(Exception));
}
}
[TestMethod]
public async Task DeleteUser()
{
try
{
if (_userService != null)
{
var user = await _userService.GetUserByGuidAsync(_user.Guid ?? String.Empty);
Assert.IsNotNull(user);
var deleted = await _userService.DeleteUserAsync(user);
Assert.IsTrue(deleted);
}
else
{
Assert.Fail($"UserService is null");
}
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException);
Assert.Fail($"An exception was thrown: {ex}");
}
}
}

View File

@@ -0,0 +1,24 @@
using BasicDotnetTemplate.MainProject.Core.Database;
using Microsoft.EntityFrameworkCore;
using BasicDotnetTemplate.MainProject.Models.Database.SqlServer;
using Newtonsoft.Json;
namespace BasicDotnetTemplate.MainProject.Tests;
public class ExceptionSqlServerContext : SqlServerContext
{
public bool ThrowExceptionOnSave { get; set; }
public ExceptionSqlServerContext() : base(TestUtils.CreateInMemorySqlContextOptions())
{
}
public override Task<int> SaveChangesAsync(CancellationToken cancellationToken = default)
{
if (ThrowExceptionOnSave)
{
throw new Exception("Database error");
}
return base.SaveChangesAsync(cancellationToken);
}
}

View File

@@ -0,0 +1,36 @@
using DatabaseSqlServer = BasicDotnetTemplate.MainProject.Models.Database.SqlServer;
namespace BasicDotnetTemplate.MainProject.Tests;
public static class ModelsInit
{
public static DatabaseSqlServer.User CreateUser()
{
DatabaseSqlServer.User user = new DatabaseSqlServer.User()
{
Guid = Guid.NewGuid().ToString(),
FirstName = "FirstName",
LastName = "LastName",
Email = "test-new@email.it",
PasswordPepper = "PasswordPepper",
PasswordSalt = "PasswordSalt",
PasswordIterations = 0,
Password = "Password",
Role = CreateRole(),
IsTestUser = true
};
return user;
}
public static DatabaseSqlServer.Role CreateRole()
{
DatabaseSqlServer.Role role = new DatabaseSqlServer.Role()
{
Guid = Guid.NewGuid().ToString(),
Name = "Name",
IsNotEditable = false
};
return role;
}
}

View File

@@ -0,0 +1,172 @@
using System;
using System.Reflection;
using System.Net;
using System.Net.Http;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using BasicDotnetTemplate.MainProject;
using BasicDotnetTemplate.MainProject.Models.Api.Response;
using Microsoft.Extensions.DependencyModel.Resolution;
using BasicDotnetTemplate.MainProject.Models.Settings;
using Microsoft.AspNetCore.Builder;
using BasicDotnetTemplate.MainProject.Utils;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Configuration;
using Microsoft.OpenApi.Models;
using Microsoft.OpenApi.Interfaces;
using Microsoft.EntityFrameworkCore;
using Moq;
using BasicDotnetTemplate.MainProject.Core.Database;
using BasicDotnetTemplate.MainProject.Services;
using Microsoft.AspNetCore.Http;
using Newtonsoft.Json;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.Mvc.Controllers;
namespace BasicDotnetTemplate.MainProject.Tests;
public static class TestUtils
{
public static AuthorizationFilterContext CreateAuthorizationContext()
{
var httpContext = new DefaultHttpContext();
var actionContext = new ActionContext(httpContext, new RouteData(), new ControllerActionDescriptor());
return new AuthorizationFilterContext(actionContext, new List<IFilterMetadata>());
}
public static IConfiguration CreateConfiguration()
{
WebApplicationBuilder builder = WebApplication.CreateBuilder(Array.Empty<string>());
AppSettings appSettings = ProgramUtils.AddConfiguration(ref builder, System.AppDomain.CurrentDomain.BaseDirectory + "/JsonData");
ProgramUtils.AddOpenApi(ref builder, appSettings);
AppSettings _appSettings = new AppSettings();
builder.Configuration.GetSection("AppSettings").Bind(_appSettings);
return builder.Configuration;
}
public static IConfiguration CreateEmptyConfiguration(string? path = "", string? filename = "")
{
string appSettingsPath = String.IsNullOrEmpty(path) ? System.AppDomain.CurrentDomain.BaseDirectory : path;
return new ConfigurationBuilder()
.SetBasePath(appSettingsPath)
.AddJsonFile(String.IsNullOrEmpty(filename) ? "appsettings.json" : filename, optional: false, reloadOnChange: true)
.AddEnvironmentVariables()
.Build();
}
public static string GetSqlConnectionString(IConfiguration configuration)
{
AppSettings _appSettings = new AppSettings();
configuration.GetSection("AppSettings").Bind(_appSettings);
return _appSettings.DatabaseSettings?.SqlServerConnectionString ?? String.Empty;
}
public static string GetFakeConnectionString()
{
return "Server=127.0.0.1;Initial Catalog=MyFakeDatabase;User Id=MyFakeUser;Password='MyFakePassword';MultipleActiveResultSets=True;Encrypt=True;TrustServerCertificate=True;Connection Timeout=30";
}
public static DbContextOptions<SqlServerContext> CreateInMemorySqlContextOptions()
{
return new DbContextOptionsBuilder<SqlServerContext>()
.UseSqlite("DataSource=:memory:") // Database in-memory
.Options;
}
public static SqlServerContext CreateInMemorySqlContext()
{
var options = CreateInMemorySqlContextOptions();
var context = new SqlServerContext(options);
context.Database.OpenConnection();
context.Database.EnsureCreated();
return context;
}
public static BaseService CreateBaseService()
{
IConfiguration configuration = CreateConfiguration();
SqlServerContext sqlServerContext = CreateInMemorySqlContext();
var httpContextAccessor = new Mock<IHttpContextAccessor>();
return new BaseService(httpContextAccessor.Object, configuration, sqlServerContext);
}
public static AuthService CreateAuthService()
{
IConfiguration configuration = CreateConfiguration();
SqlServerContext sqlServerContext = CreateInMemorySqlContext();
var userServiceMock = new Mock<IUserService>();
var httpContextAccessor = new Mock<IHttpContextAccessor>();
return new AuthService(httpContextAccessor.Object, configuration, sqlServerContext, userServiceMock.Object);
}
public static UserService CreateUserService()
{
IConfiguration configuration = CreateConfiguration();
SqlServerContext sqlServerContext = CreateInMemorySqlContext();
var httpContextAccessor = new Mock<IHttpContextAccessor>();
return new UserService(httpContextAccessor.Object, configuration, sqlServerContext);
}
public static UserService CreateUserServiceException()
{
var sqlServerContext = new ExceptionSqlServerContext();
sqlServerContext.ThrowExceptionOnSave = true;
IConfiguration configuration = CreateConfiguration();
var httpContextAccessor = new Mock<IHttpContextAccessor>();
return new UserService(httpContextAccessor.Object, configuration, sqlServerContext);
}
public static JwtService CreateJwtService()
{
IConfiguration configuration = CreateConfiguration();
var optionsBuilder = new DbContextOptionsBuilder<SqlServerContext>();
optionsBuilder.UseSqlServer(GetSqlConnectionString(configuration));
SqlServerContext sqlServerContext = CreateInMemorySqlContext();
var httpContextAccessor = new Mock<IHttpContextAccessor>();
return new JwtService(httpContextAccessor.Object, configuration, sqlServerContext);
}
public static RoleService CreateRoleService()
{
IConfiguration configuration = CreateConfiguration();
var optionsBuilder = new DbContextOptionsBuilder<SqlServerContext>();
optionsBuilder.UseSqlServer(GetSqlConnectionString(configuration));
SqlServerContext sqlServerContext = CreateInMemorySqlContext();
var httpContextAccessor = new Mock<IHttpContextAccessor>();
return new RoleService(httpContextAccessor.Object, configuration, sqlServerContext);
}
public static RoleService CreateRoleServiceException()
{
var sqlServerContext = new ExceptionSqlServerContext();
sqlServerContext.ThrowExceptionOnSave = true;
IConfiguration configuration = CreateConfiguration();
var httpContextAccessor = new Mock<IHttpContextAccessor>();
return new RoleService(httpContextAccessor.Object, configuration, sqlServerContext);
}
public static PermissionService CreatePermissionService()
{
IConfiguration configuration = CreateConfiguration();
SqlServerContext sqlServerContext = CreateInMemorySqlContext();
var httpContextAccessor = new Mock<IHttpContextAccessor>();
return new PermissionService(httpContextAccessor.Object, configuration, sqlServerContext);
}
public static PermissionService CreatePermissionServiceException()
{
var sqlServerContext = new ExceptionSqlServerContext();
sqlServerContext.ThrowExceptionOnSave = true;
IConfiguration configuration = CreateConfiguration();
var httpContextAccessor = new Mock<IHttpContextAccessor>();
return new PermissionService(httpContextAccessor.Object, configuration, sqlServerContext);
}
}

View File

@@ -0,0 +1,164 @@
using System;
using BasicDotnetTemplate.MainProject.Models.Settings;
using Microsoft.AspNetCore.Builder;
using BasicDotnetTemplate.MainProject.Utils;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Configuration;
namespace BasicDotnetTemplate.MainProject.Tests;
[TestClass]
public class CryptoUtils_Tests
{
[TestMethod]
public void Decrypt_Success()
{
try
{
string encryptedData = "d2ejdI1f4GYpq2kTB1nmeQkZXqR3QSxH8Yqkl7iv7zgfQ13qG/0dUUsreG/WGHWRBE5mVWaV43A=";
WebApplicationBuilder builder = WebApplication.CreateBuilder(Array.Empty<string>());
AppSettings appSettings = ProgramUtils.AddConfiguration(ref builder, System.AppDomain.CurrentDomain.BaseDirectory + "/JsonData");
CryptUtils cryptoUtils = new CryptUtils(appSettings);
var decryptedData = cryptoUtils.Decrypt(encryptedData);
var isEqual = decryptedData == "ThisIsASuccessfullTest";
Assert.IsTrue(isEqual);
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException);
Assert.Fail($"An exception was thrown: {ex}");
}
}
[TestMethod]
public void Decrypt_Error()
{
try
{
string encryptedData = "d1ejdI1f4GYpq2kTB1nmeQkZXqR3QSxH8Yqkl7iv7zgfQ13qG/0dUUsreG/WGHWRBE5mVWaV43A=";
WebApplicationBuilder builder = WebApplication.CreateBuilder(Array.Empty<string>());
AppSettings appSettings = ProgramUtils.AddConfiguration(ref builder, System.AppDomain.CurrentDomain.BaseDirectory + "/JsonData");
CryptUtils cryptoUtils = new CryptUtils(appSettings);
var decryptedData = cryptoUtils.Decrypt(encryptedData);
var isEqual = decryptedData == "ThisIsASuccessfullTest";
Assert.IsFalse(isEqual);
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException);
Assert.Fail($"An exception was thrown: {ex}");
}
}
[TestMethod]
public void Decrypt_ArgumentException()
{
try
{
string encryptedData = "d1ejdI1f4GYpq2kTB1nmeQkZXqR3QSxH8Yqkl7iv7zgfQ13qG/0dUUsreG/WGHWRBE5mVWaV43A=";
WebApplicationBuilder builder = WebApplication.CreateBuilder(Array.Empty<string>());
AppSettings appSettings = ProgramUtils.AddConfiguration(ref builder, System.AppDomain.CurrentDomain.BaseDirectory + "/JsonData", "invalidCryptAppsettings.json");
CryptUtils cryptoUtils = new CryptUtils(appSettings);
try
{
var decryptedData = cryptoUtils.Decrypt(encryptedData);
Assert.Fail($"Expected exception instead of response: {decryptedData}");
}
catch (ArgumentException argumentException)
{
Assert.IsInstanceOfType(argumentException, typeof(ArgumentException));
}
catch (Exception exception)
{
Assert.IsInstanceOfType(exception, typeof(ArgumentException));
}
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException);
Assert.Fail($"An exception was thrown: {ex}");
}
}
[TestMethod]
public void Decrypt_Empty()
{
try
{
string encryptedData = "WGHWRBE5mVWaV=";
WebApplicationBuilder builder = WebApplication.CreateBuilder(Array.Empty<string>());
AppSettings appSettings = ProgramUtils.AddConfiguration(ref builder, System.AppDomain.CurrentDomain.BaseDirectory + "/JsonData");
CryptUtils cryptoUtils = new CryptUtils(appSettings);
var decryptedData = cryptoUtils.Decrypt(encryptedData);
var isEqual = decryptedData == String.Empty;
Assert.IsTrue(isEqual);
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException);
Assert.Fail($"An exception was thrown: {ex}");
}
}
[TestMethod]
public void GeneratePepper()
{
try
{
var salt = CryptUtils.GeneratePepper();
Assert.IsFalse(String.IsNullOrEmpty(salt));
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException);
Assert.Fail($"An exception was thrown: {ex}");
}
}
[TestMethod]
public void ComputeHash_Hashed()
{
try
{
var password = "P4ssw0rd@1!";
var pepper = CryptUtils.GeneratePepper();
Assert.IsFalse(String.IsNullOrEmpty(pepper));
WebApplicationBuilder builder = WebApplication.CreateBuilder(Array.Empty<string>());
AppSettings appSettings = ProgramUtils.AddConfiguration(ref builder, System.AppDomain.CurrentDomain.BaseDirectory + "/JsonData");
var salt = appSettings?.EncryptionSettings?.Salt ?? String.Empty;
var encryptedPassword = CryptUtils.GeneratePassword(password, salt, 0, pepper);
Assert.AreNotEqual(encryptedPassword, password);
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException);
Assert.Fail($"An exception was thrown: {ex}");
}
}
[TestMethod]
public void VerifyPassword_True()
{
try
{
var password = "P4ssw0rd@1!";
var salt = "Afi7PQYgEL2sPbNyVzduvg==";
var hashedPassword = "2lMeySZ9ciH1KtSg1Z7oSJRmJEjHMeDvdaNRcJcGutM=";
var verified = CryptUtils.VerifyPassword(hashedPassword, password, salt, 0);
Assert.IsTrue(verified);
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException);
Assert.Fail($"An exception was thrown: {ex}");
}
}
}

View File

@@ -0,0 +1,82 @@
using BasicDotnetTemplate.MainProject.Utils;
using BasicDotnetTemplate.MainProject.Models.Common;
namespace BasicDotnetTemplate.MainProject.Tests;
[TestClass]
public class FileUtils_Tests
{
[TestMethod]
public void ConvertFileToObject_NoFilePath()
{
try
{
PermissionsFile? permissionsFile = FileUtils.ConvertFileToObject<PermissionsFile>(String.Empty);
Assert.Fail($"Expected exception instead of response: {permissionsFile}");
}
catch (ArgumentException argumentException)
{
Assert.IsInstanceOfType(argumentException, typeof(ArgumentException));
}
catch (Exception exception)
{
Assert.Fail($"An exception was thrown: {exception}");
}
}
[TestMethod]
public void ConvertFileToObject_NoFile()
{
try
{
PermissionsFile? permissionsFile = FileUtils.ConvertFileToObject<PermissionsFile>(System.AppDomain.CurrentDomain.BaseDirectory + "Config/no-permissions.json");
Assert.Fail($"Expected exception instead of response: {permissionsFile}");
}
catch (FileNotFoundException fileNotFoundException)
{
Assert.IsInstanceOfType(fileNotFoundException, typeof(FileNotFoundException));
}
catch (Exception exception)
{
Assert.Fail($"An exception was thrown: {exception}");
}
}
[TestMethod]
public void ConvertFileToObject()
{
try
{
PermissionsFile? permissionsFile = FileUtils.ConvertFileToObject<PermissionsFile>(System.AppDomain.CurrentDomain.BaseDirectory + "Config/permissions.json");
Assert.IsNotNull(permissionsFile);
}
catch (Exception exception)
{
Assert.Fail($"An exception was thrown: {exception}");
}
}
[TestMethod]
public void ConvertFileToObject_InvalidOperationException()
{
try
{
PermissionsFile? permissionsFile = FileUtils.ConvertFileToObject<PermissionsFile>(System.AppDomain.CurrentDomain.BaseDirectory + "Config/invalid-permissions.json");
Assert.Fail($"Expected exception instead of response: {permissionsFile}");
}
catch (InvalidOperationException invalidOperationException)
{
Assert.IsInstanceOfType(invalidOperationException, typeof(InvalidOperationException));
}
catch (Exception exception)
{
Assert.Fail($"An exception was thrown: {exception}");
}
}
}

View File

@@ -0,0 +1,76 @@
using System;
using BasicDotnetTemplate.MainProject.Models.Settings;
using Microsoft.AspNetCore.Builder;
using BasicDotnetTemplate.MainProject.Utils;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Configuration;
namespace BasicDotnetTemplate.MainProject.Tests;
[TestClass]
public class JwtTokenUtils_Tests
{
private static string _guid = "15e4be58-e655-475e-b4b8-a9779b359f57";
[TestMethod]
public void GenerateToken()
{
try
{
WebApplicationBuilder builder = WebApplication.CreateBuilder(Array.Empty<string>());
AppSettings appSettings = ProgramUtils.AddConfiguration(ref builder, System.AppDomain.CurrentDomain.BaseDirectory + "/JsonData");
JwtTokenUtils jwtUtils = new JwtTokenUtils(appSettings);
var jwt = jwtUtils.GenerateToken(_guid);
Assert.IsFalse(String.IsNullOrEmpty(jwt));
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException);
Assert.Fail($"An exception was thrown: {ex}");
}
}
[TestMethod]
public void ValidateToken()
{
try
{
WebApplicationBuilder builder = WebApplication.CreateBuilder(Array.Empty<string>());
AppSettings appSettings = ProgramUtils.AddConfiguration(ref builder, System.AppDomain.CurrentDomain.BaseDirectory + "/JsonData");
JwtTokenUtils jwtUtils = new JwtTokenUtils(appSettings);
var jwt = jwtUtils.GenerateToken(_guid);
var guid = jwtUtils.ValidateToken($"Bearer {jwt}");
Assert.AreEqual(_guid, guid);
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException);
Assert.Fail($"An exception was thrown: {ex}");
}
}
[TestMethod]
public void ValidateToken_Empty()
{
try
{
WebApplicationBuilder builder = WebApplication.CreateBuilder(Array.Empty<string>());
AppSettings appSettings = ProgramUtils.AddConfiguration(ref builder, System.AppDomain.CurrentDomain.BaseDirectory + "/JsonData");
JwtTokenUtils jwtUtils = new JwtTokenUtils(appSettings);
var jwt = jwtUtils.GenerateToken(_guid);
var guid = jwtUtils.ValidateToken(jwt);
Assert.IsTrue(String.IsNullOrEmpty(guid));
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException);
Assert.Fail($"An exception was thrown: {ex}");
}
}
}

View File

@@ -0,0 +1,62 @@
using BasicDotnetTemplate.MainProject.Utils;
using BasicDotnetTemplate.MainProject.Models.Common;
using BasicDotnetTemplate.MainProject.Enum;
namespace BasicDotnetTemplate.MainProject.Tests;
[TestClass]
public class PasswordUtils_Test
{
[TestMethod]
public void PasswordValidation_Valid()
{
try
{
List<string> errors = PasswordUtils.ValidatePassword("#aBcDeFgHi01245#");
Assert.IsTrue(errors == null || errors.Count == 0);
}
catch (Exception exception)
{
Assert.Fail($"An exception was thrown: {exception}");
}
}
[TestMethod]
public void PasswordValidation_Invalid()
{
try
{
List<string> errors = PasswordUtils.ValidatePassword("aAa1#");
Assert.IsTrue(errors.Contains(PasswordValidationEnum.MIN_LENGTH));
Assert.IsTrue(errors.Contains(PasswordValidationEnum.MIN_UPPER));
Assert.IsTrue(errors.Contains(PasswordValidationEnum.MIN_NUMBER));
Assert.IsTrue(errors.Contains(PasswordValidationEnum.MIN_SPECIAL));
Assert.IsTrue(errors.Contains(PasswordValidationEnum.IDENTICAL_CHARS));
Assert.IsFalse(errors.Contains(PasswordValidationEnum.MIN_LOWER));
}
catch (Exception exception)
{
Assert.Fail($"An exception was thrown: {exception}");
}
}
[TestMethod]
public void PasswordValidation_ToLowerInvalid()
{
try
{
List<string> errors = PasswordUtils.ValidatePassword("AaBC0*TGH1#");
Assert.IsTrue(errors.Contains(PasswordValidationEnum.MIN_LOWER));
}
catch (Exception exception)
{
Assert.Fail($"An exception was thrown: {exception}");
}
}
}

View File

@@ -0,0 +1,316 @@
using BasicDotnetTemplate.MainProject.Models.Settings;
using Microsoft.AspNetCore.Builder;
using BasicDotnetTemplate.MainProject.Utils;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Configuration;
using Microsoft.OpenApi.Models;
using Microsoft.OpenApi.Interfaces;
namespace BasicDotnetTemplate.MainProject.Tests;
[TestClass]
public class ProgramUtils_Tests
{
[TestMethod]
public void NoOpenApiConfig_Valid()
{
try
{
OpenApiInfo expectedOpenApiInfo = new OpenApiInfo()
{
Title = "MainProject",
Description = "This template contains basic configuration for a .Net 8 backend",
Version = "v1.0",
Contact = null,
TermsOfService = null,
License = null,
Extensions = new Dictionary<string, IOpenApiExtension>()
};
WebApplicationBuilder builder = WebApplication.CreateBuilder(Array.Empty<string>());
AppSettings realAppSettings = ProgramUtils.AddConfiguration(ref builder, System.AppDomain.CurrentDomain.BaseDirectory + "/JsonData", "noApiConfigurationAppSettings.json");
OpenApiInfo realOpenApiInfo = ProgramUtils.CreateOpenApiInfo(realAppSettings);
var areEquals = expectedOpenApiInfo.Title == realOpenApiInfo.Title &&
expectedOpenApiInfo.Description == realOpenApiInfo.Description &&
expectedOpenApiInfo.Version == realOpenApiInfo.Version &&
expectedOpenApiInfo.Contact == realOpenApiInfo.Contact &&
expectedOpenApiInfo.TermsOfService == realOpenApiInfo.TermsOfService &&
expectedOpenApiInfo.License == realOpenApiInfo.License;
Assert.IsTrue(areEquals);
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException);
Assert.Fail($"An exception was thrown: {ex}");
}
}
[TestMethod]
public void CreateOpenApiInfo_EmptyAppSettings()
{
try
{
OpenApiInfo expectedOpenApiInfo = new OpenApiInfo()
{
Title = null,
Description = null,
Version = null,
Contact = null,
TermsOfService = null,
License = null,
Extensions = new Dictionary<string, IOpenApiExtension>()
};
WebApplicationBuilder builder = WebApplication.CreateBuilder(Array.Empty<string>());
AppSettings realAppSettings = ProgramUtils.AddConfiguration(ref builder, System.AppDomain.CurrentDomain.BaseDirectory + "/JsonData", "emptyAppsettings.json");
OpenApiInfo realOpenApiInfo = ProgramUtils.CreateOpenApiInfo(realAppSettings);
var areEquals = expectedOpenApiInfo.Title == realOpenApiInfo.Title &&
expectedOpenApiInfo.Description == realOpenApiInfo.Description &&
expectedOpenApiInfo.Version == realOpenApiInfo.Version &&
expectedOpenApiInfo.Contact == realOpenApiInfo.Contact &&
expectedOpenApiInfo.TermsOfService == realOpenApiInfo.TermsOfService &&
expectedOpenApiInfo.License == realOpenApiInfo.License;
Assert.IsTrue(areEquals);
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException);
Assert.Fail($"An exception was thrown: {ex}");
}
}
[TestMethod]
public void CreateOpenApiInfo_NullSettings()
{
try
{
AppSettings appSettings = new AppSettings();
OpenApiInfo realOpenApiInfo = ProgramUtils.CreateOpenApiInfo(appSettings);
Assert.IsNotNull(realOpenApiInfo);
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException);
Assert.Fail($"An exception was thrown: {ex}");
}
}
[TestMethod]
public void CreateOpenApiInfo_NullOpenApiSettings()
{
try
{
AppSettings appSettings = new AppSettings()
{
Settings = new Settings
{
Name = "Test",
Description = "This is a test description",
Version = "v1"
},
OpenApiSettings = null
};
OpenApiInfo realOpenApiInfo = ProgramUtils.CreateOpenApiInfo(appSettings);
Assert.IsNotNull(realOpenApiInfo);
Assert.AreEqual(appSettings.Settings.Name, realOpenApiInfo.Title);
Assert.AreEqual(appSettings.Settings.Description, realOpenApiInfo.Description);
Assert.AreEqual(appSettings.Settings.Version, realOpenApiInfo.Version);
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException);
Assert.Fail($"An exception was thrown: {ex}");
}
}
[TestMethod]
public void CreateOpenApiInfo_NullTermsOfServiceUrl()
{
try
{
AppSettings appSettings = new AppSettings()
{
Settings = new Settings
{
Name = "Test",
Description = "This is a test description",
Version = "v1"
},
OpenApiSettings = new OpenApiSettings
{
TermsOfServiceUrl = null,
OpenApiContact = null,
OpenApiLicense = null
}
};
OpenApiInfo realOpenApiInfo = ProgramUtils.CreateOpenApiInfo(appSettings);
Assert.IsNotNull(realOpenApiInfo);
Assert.AreEqual(appSettings.Settings.Name, realOpenApiInfo.Title);
Assert.AreEqual(appSettings.Settings.Description, realOpenApiInfo.Description);
Assert.AreEqual(appSettings.Settings.Version, realOpenApiInfo.Version);
Assert.IsNull(realOpenApiInfo.TermsOfService);
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException);
Assert.Fail($"An exception was thrown: {ex}");
}
}
[TestMethod]
public void OpenApiConfig_NotNull()
{
try
{
OpenApiInfo expectedOpenApiInfo = new OpenApiInfo()
{
Title = "MainProject",
Description = "This template contains basic configuration for a .Net 8 backend",
Version = "v1.0",
Contact = null,
TermsOfService = null,
License = null,
Extensions = new Dictionary<string, IOpenApiExtension>()
};
WebApplicationBuilder builder = WebApplication.CreateBuilder(Array.Empty<string>());
AppSettings appSettings = ProgramUtils.AddConfiguration(ref builder, System.AppDomain.CurrentDomain.BaseDirectory + "/JsonData", "completeAppSettings.json");
OpenApiInfo realOpenApiInfo = ProgramUtils.CreateOpenApiInfo(appSettings);
var areEquals = expectedOpenApiInfo.Title == realOpenApiInfo.Title &&
expectedOpenApiInfo.Description == realOpenApiInfo.Description &&
expectedOpenApiInfo.Version == realOpenApiInfo.Version &&
expectedOpenApiInfo.Contact == realOpenApiInfo.Contact &&
expectedOpenApiInfo.TermsOfService == realOpenApiInfo.TermsOfService &&
expectedOpenApiInfo.License == realOpenApiInfo.License;
Assert.IsFalse(areEquals);
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException);
Assert.Fail($"An exception was thrown: {ex}");
}
}
[TestMethod]
public void AddOpenApi_Valid()
{
try
{
WebApplicationBuilder builder = WebApplication.CreateBuilder(Array.Empty<string>());
AppSettings appSettings = ProgramUtils.AddConfiguration(ref builder, System.AppDomain.CurrentDomain.BaseDirectory + "/JsonData");
ProgramUtils.AddOpenApi(ref builder, appSettings);
AppSettings _appSettings = new AppSettings();
builder.Configuration.GetSection("AppSettings").Bind(_appSettings);
var areEquals = appSettings.OpenApiSettings?.OpenApiContact?.Name == _appSettings.OpenApiSettings?.OpenApiContact?.Name &&
appSettings.OpenApiSettings?.OpenApiContact?.Url == _appSettings.OpenApiSettings?.OpenApiContact?.Url &&
appSettings.OpenApiSettings?.OpenApiLicense?.Name == _appSettings.OpenApiSettings?.OpenApiLicense?.Name &&
appSettings.OpenApiSettings?.OpenApiLicense?.Url == _appSettings.OpenApiSettings?.OpenApiLicense?.Url &&
appSettings.OpenApiSettings?.TermsOfServiceUrl == _appSettings.OpenApiSettings?.TermsOfServiceUrl;
Assert.IsTrue(areEquals);
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException);
Assert.Fail($"An exception was thrown: {ex}");
}
}
[TestMethod]
public void AddSqlServerContext_Valid()
{
try
{
WebApplicationBuilder builder = WebApplication.CreateBuilder(Array.Empty<string>());
AppSettings appSettings = ProgramUtils.AddConfiguration(ref builder, System.AppDomain.CurrentDomain.BaseDirectory + "/JsonData");
ProgramUtils.AddDbContext(ref builder, appSettings);
AppSettings _appSettings = new AppSettings();
builder.Configuration.GetSection("AppSettings").Bind(_appSettings);
var areEquals = appSettings.DatabaseSettings?.SqlServerConnectionString == _appSettings.DatabaseSettings?.SqlServerConnectionString;
Assert.IsTrue(areEquals);
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException);
Assert.Fail($"An exception was thrown: {ex}");
}
}
[TestMethod]
public void AddMongoDbContext_Valid()
{
try
{
WebApplicationBuilder builder = WebApplication.CreateBuilder(Array.Empty<string>());
AppSettings appSettings = ProgramUtils.AddConfiguration(ref builder, System.AppDomain.CurrentDomain.BaseDirectory + "/JsonData");
ProgramUtils.AddDbContext(ref builder, appSettings);
AppSettings _appSettings = new AppSettings();
builder.Configuration.GetSection("AppSettings").Bind(_appSettings);
var areEquals = appSettings.DatabaseSettings?.MongoDbConnectionString == _appSettings.DatabaseSettings?.MongoDbConnectionString;
Assert.IsTrue(areEquals);
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException);
Assert.Fail($"An exception was thrown: {ex}");
}
}
[TestMethod]
public void AddPostgreSqlDbContext_Valid()
{
try
{
WebApplicationBuilder builder = WebApplication.CreateBuilder(Array.Empty<string>());
AppSettings appSettings = ProgramUtils.AddConfiguration(ref builder, System.AppDomain.CurrentDomain.BaseDirectory + "/JsonData");
ProgramUtils.AddDbContext(ref builder, appSettings);
AppSettings _appSettings = new AppSettings();
builder.Configuration.GetSection("AppSettings").Bind(_appSettings);
var areEquals = appSettings.DatabaseSettings?.PostgreSQLConnectionString == _appSettings.DatabaseSettings?.PostgreSQLConnectionString;
Assert.IsTrue(areEquals);
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException);
Assert.Fail($"An exception was thrown: {ex}");
}
}
[TestMethod]
public void NoSqlServerContext_Empty()
{
try
{
DatabaseSettings expectedDbSettings = new DatabaseSettings()
{
SqlServerConnectionString = null
};
WebApplicationBuilder builder = WebApplication.CreateBuilder(Array.Empty<string>());
AppSettings realAppSettings = ProgramUtils.AddConfiguration(ref builder, System.AppDomain.CurrentDomain.BaseDirectory + "/JsonData", "noApiConfigurationAppSettings.json");
ProgramUtils.AddDbContext(ref builder, realAppSettings);
var areEquals = expectedDbSettings.SqlServerConnectionString == realAppSettings.DatabaseSettings?.SqlServerConnectionString;
Assert.IsTrue(areEquals);
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException);
Assert.Fail($"An exception was thrown: {ex}");
}
}
}

View File

@@ -0,0 +1,32 @@
{
"PermissionInfos": [
{
"System": "base",
"RolePermissionModuleOperations": [
{
"Module": "roles",
"Operations": [
{ "Operation": "create", "Roles": [] },
{ "Operation": "read", "Roles": [] },
{ "Operation": "update", "Roles": [] },
{ "Operation": "delete", "Roles": [] },
{ "Operation": "list", "Roles": [] },
{ "Operation": "use", "Roles": [] }
]
},
{
"Module": "users",
"Operations": [
{ "Operation": "create", "Roles": [] },
{ "Operation": "read", "Roles": [] },
{ "Operation": "update", "Roles": [] },
{ "Operation": "delete", "Roles": [] },
{ "Operation": "list", "Roles": [] },
{ "Operation": "use", "Roles": [] }
]
}
]
}
]
}

View File

@@ -0,0 +1,51 @@
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using BasicDotnetTemplate.MainProject.Core.Attributes;
using BasicDotnetTemplate.MainProject.Models.Api.Request.Auth;
using BasicDotnetTemplate.MainProject.Models.Api.Response;
using BasicDotnetTemplate.MainProject.Models.Api.Response.Auth;
using BasicDotnetTemplate.MainProject.Services;
using BasicDotnetTemplate.MainProject.Core.Filters;
namespace BasicDotnetTemplate.MainProject.Controllers
{
[Route("[controller]")]
public class AuthController : BaseController
{
private readonly IAuthService _authService;
public AuthController(
IConfiguration configuration,
IAuthService authService
) : base(configuration)
{
this._authService = authService;
}
[ModelStateValidationHandledByFilterAttribute]
[HttpPost("authenticate")]
[ProducesResponseType<AuthenticateResponse>(StatusCodes.Status200OK)]
[ProducesResponseType<BaseResponse<object>>(StatusCodes.Status404NotFound)]
[ProducesResponseType<BaseResponse<object>>(StatusCodes.Status400BadRequest)]
[ProducesResponseType<BaseResponse<object>>(StatusCodes.Status500InternalServerError)]
public async Task<IActionResult> AuthenticateAsync([FromBody] AuthenticateRequest request) //NOSONAR
{
try
{
var data = await this._authService.AuthenticateAsync(request!.Data!);
if (data == null)
{
return NotFound();
}
return Success(String.Empty, data);
}
catch (Exception exception)
{
return InternalServerError(exception);
}
}
}
}

View File

@@ -0,0 +1,81 @@
using System.Net;
using Microsoft.AspNetCore.Mvc;
using BasicDotnetTemplate.MainProject.Models.Api.Response;
using BasicDotnetTemplate.MainProject.Models.Settings;
using AutoMapper;
using BasicDotnetTemplate.MainProject.Core.Middlewares;
namespace BasicDotnetTemplate.MainProject.Controllers
{
public abstract class BaseController : ControllerBase
{
protected readonly IMapper? _mapper;
protected readonly IConfiguration _configuration;
protected readonly AppSettings _appSettings;
protected readonly string _somethingWentWrong = "Something went wrong";
protected BaseController(
IConfiguration configuration
)
{
_configuration = configuration;
_appSettings = new AppSettings();
_configuration.GetSection("AppSettings").Bind(_appSettings);
var config = new MapperConfiguration(cfg =>
{
cfg.AddProfile<AutoMapperConfiguration>();
});
_mapper = config.CreateMapper();
}
#nullable enable
private static BaseResponse<T> CreateResponse<T>(HttpStatusCode status, string message, T? data)
{
return new BaseResponse<T>((int)status, message, data);
}
protected new IActionResult Created(string message, object? data = null)
{
message = String.IsNullOrEmpty(message) ? "Created" : message;
return StatusCode((int)HttpStatusCode.Created, CreateResponse(HttpStatusCode.Created, message, data));
}
protected IActionResult Success(string message, object? data = null)
{
message = String.IsNullOrEmpty(message) ? "Success" : message;
return StatusCode((int)HttpStatusCode.OK, CreateResponse(HttpStatusCode.OK, message, data));
}
protected IActionResult NotModified(string message, object? data = null)
{
message = String.IsNullOrEmpty(message) ? "Not modified" : message;
return StatusCode((int)HttpStatusCode.NotModified, CreateResponse(HttpStatusCode.NotModified, message, data));
}
protected IActionResult NotFound(string message, object? data = null)
{
message = String.IsNullOrEmpty(message) ? "Not found" : message;
return StatusCode((int)HttpStatusCode.NotFound, CreateResponse(HttpStatusCode.NotFound, message, data));
}
protected IActionResult BadRequest(string message, object? data = null)
{
message = String.IsNullOrEmpty(message) ? "Bad request" : message;
return StatusCode((int)HttpStatusCode.BadRequest, CreateResponse(HttpStatusCode.BadRequest, message, data));
}
protected IActionResult InternalServerError(Exception exception)
{
var message = this._somethingWentWrong;
if (!String.IsNullOrEmpty(exception.Message))
{
message += $". {exception.Message}";
}
return StatusCode((int)HttpStatusCode.InternalServerError, CreateResponse(HttpStatusCode.InternalServerError, message, new object()));
}
#nullable disable
}
}

View File

@@ -0,0 +1,168 @@
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using BasicDotnetTemplate.MainProject.Core.Attributes;
using BasicDotnetTemplate.MainProject.Services;
using BasicDotnetTemplate.MainProject.Models.Api.Request.Role;
using BasicDotnetTemplate.MainProject.Models.Api.Response;
using BasicDotnetTemplate.MainProject.Models.Api.Response.Role;
using BasicDotnetTemplate.MainProject.Models.Database.SqlServer;
using BasicDotnetTemplate.MainProject.Models.Api.Common.Role;
using BasicDotnetTemplate.MainProject.Core.Filters;
namespace BasicDotnetTemplate.MainProject.Controllers
{
[Route("[controller]")]
public class RoleController : BaseController
{
private readonly IRoleService _roleService;
public RoleController(
IConfiguration configuration,
IRoleService roleService
) : base(configuration)
{
this._roleService = roleService;
}
[JwtAuthorization()]
[ModelStateValidationHandledByFilterAttribute]
[HttpGet("get/{guid}")]
[ProducesResponseType<GetRoleResponse>(StatusCodes.Status200OK)]
[ProducesResponseType<BaseResponse<object>>(StatusCodes.Status404NotFound)]
[ProducesResponseType<BaseResponse<object>>(StatusCodes.Status400BadRequest)]
[ProducesResponseType<BaseResponse<object>>(StatusCodes.Status500InternalServerError)]
public async Task<IActionResult> GetRoleByGuidAsync(string guid)
{
try
{
var role = await this._roleService.GetRoleByGuidAsync(guid);
if (role == null || String.IsNullOrEmpty(role.Guid))
{
return NotFound();
}
var roleDto = _mapper?.Map<RoleDto>(role);
return Success(String.Empty, roleDto);
}
catch (Exception exception)
{
return InternalServerError(exception);
}
}
[JwtAuthorization()]
[ModelStateValidationHandledByFilterAttribute]
[HttpPost("create")]
[ProducesResponseType<GetRoleResponse>(StatusCodes.Status201Created)]
[ProducesResponseType<BaseResponse<object>>(StatusCodes.Status400BadRequest)]
[ProducesResponseType<BaseResponse<object>>(StatusCodes.Status500InternalServerError)]
public async Task<IActionResult> CreateRoleAsync([FromBody] CreateRoleRequest request) //NOSONAR
{
try
{
if (await this._roleService.CheckIfNameIsValid(request!.Data!.Name))
{
var role = await this._roleService.CreateRoleAsync(request!.Data);
if (role == null || String.IsNullOrEmpty(role.Guid))
{
return BadRequest("Not created");
}
var roleDto = _mapper?.Map<RoleDto>(role);
return Success(String.Empty, roleDto);
}
else
{
return BadRequest("Invalid name");
}
}
catch (Exception exception)
{
return InternalServerError(exception);
}
}
[JwtAuthorization()]
[ModelStateValidationHandledByFilterAttribute]
[HttpPut("update/{guid}")]
[ProducesResponseType<GetRoleResponse>(StatusCodes.Status200OK)]
[ProducesResponseType<BaseResponse<object>>(StatusCodes.Status400BadRequest)]
[ProducesResponseType<BaseResponse<object>>(StatusCodes.Status500InternalServerError)]
public async Task<IActionResult> UpdateRoleAsync([FromBody] CreateRoleRequest request, string guid) //NOSONAR
{
try
{
var role = await this._roleService.GetRoleByGuidAsync(guid);
if (role == null || String.IsNullOrEmpty(role.Guid))
{
return NotFound();
}
if (role.IsNotEditable)
{
return BadRequest("This role is not editable");
}
if (
await this._roleService.CheckIfNameIsValid(request!.Data!.Name) ||
await this._roleService.CheckIfNameIsValid(request!.Data!.Name, guid)
)
{
role = await this._roleService.UpdateRoleAsync(request.Data, role);
var roleDto = _mapper?.Map<RoleDto>(role);
return Success(String.Empty, roleDto);
}
else
{
return BadRequest("Invalid name");
}
}
catch (Exception exception)
{
return InternalServerError(exception);
}
}
[JwtAuthorization()]
[ModelStateValidationHandledByFilterAttribute]
[HttpDelete("{guid}")]
[ProducesResponseType<GetRoleResponse>(StatusCodes.Status200OK)]
[ProducesResponseType<BaseResponse<object>>(StatusCodes.Status404NotFound)]
[ProducesResponseType<BaseResponse<object>>(StatusCodes.Status400BadRequest)]
[ProducesResponseType<BaseResponse<object>>(StatusCodes.Status500InternalServerError)]
public async Task<IActionResult> DeleteRoleByGuidAsync(string guid)
{
try
{
var role = await this._roleService.GetRoleByGuidAsync(guid);
if (role == null || String.IsNullOrEmpty(role.Guid))
{
return NotFound();
}
await this._roleService.DeleteRoleAsync(role);
return Success(String.Empty);
}
catch (Exception exception)
{
return InternalServerError(exception);
}
}
}
}

View File

@@ -0,0 +1,18 @@
using Microsoft.AspNetCore.Mvc;
using BasicDotnetTemplate.MainProject.Models.Settings;
using Microsoft.AspNetCore.Http.HttpResults;
namespace BasicDotnetTemplate.MainProject.Controllers
{
[Route("")]
public class RootController : ControllerBase
{
public RootController() { }
[HttpGet("")]
public IActionResult GetRoot()
{
return Ok();
}
}
}

View File

@@ -0,0 +1,227 @@
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using BasicDotnetTemplate.MainProject.Core.Attributes;
using BasicDotnetTemplate.MainProject.Services;
using BasicDotnetTemplate.MainProject.Models.Api.Request.User;
using BasicDotnetTemplate.MainProject.Models.Api.Response;
using BasicDotnetTemplate.MainProject.Models.Api.Response.User;
using BasicDotnetTemplate.MainProject.Models.Database.SqlServer;
using BasicDotnetTemplate.MainProject.Models.Api.Common.User;
using BasicDotnetTemplate.MainProject.Core.Filters;
namespace BasicDotnetTemplate.MainProject.Controllers
{
[Route("[controller]")]
public class UserController : BaseController
{
private readonly IUserService _userService;
private readonly IRoleService _roleService;
public UserController(
IConfiguration configuration,
IUserService userService,
IRoleService roleService
) : base(configuration)
{
this._userService = userService;
this._roleService = roleService;
}
[JwtAuthorization()]
[ModelStateValidationHandledByFilterAttribute]
[HttpGet("get/{guid}")]
[ProducesResponseType<GetUserResponse>(StatusCodes.Status200OK)]
[ProducesResponseType<BaseResponse<object>>(StatusCodes.Status404NotFound)]
[ProducesResponseType<BaseResponse<object>>(StatusCodes.Status400BadRequest)]
[ProducesResponseType<BaseResponse<object>>(StatusCodes.Status500InternalServerError)]
public async Task<IActionResult> GetUserByGuidAsync(string guid)
{
try
{
var user = await this._userService.GetUserByGuidAsync(guid);
if (user == null || String.IsNullOrEmpty(user.Guid))
{
return NotFound();
}
var userDto = _mapper?.Map<UserDto>(user);
return Success(String.Empty, userDto);
}
catch (Exception exception)
{
return InternalServerError(exception);
}
}
[JwtAuthorization()]
[ModelStateValidationHandledByFilterAttribute]
[HttpPost("create")]
[ProducesResponseType<GetUserResponse>(StatusCodes.Status201Created)]
[ProducesResponseType<BaseResponse<object>>(StatusCodes.Status400BadRequest)]
[ProducesResponseType<BaseResponse<object>>(StatusCodes.Status500InternalServerError)]
public async Task<IActionResult> CreateUserAsync([FromBody] CreateUserRequest request) //NOSONAR
{
try
{
if (await this._userService.CheckIfEmailIsValid(request!.Data!.Email))
{
var role = await this._roleService.GetRoleForUser(request!.Data!.RoleGuid);
if (role == null)
{
return BadRequest("Role not found");
}
var user = await this._userService.CreateUserAsync(request!.Data, role);
if (user == null || String.IsNullOrEmpty(user.Guid))
{
return BadRequest("Not created");
}
var userDto = _mapper?.Map<UserDto>(user);
return Success(String.Empty, userDto);
}
else
{
return BadRequest("Invalid email");
}
}
catch (Exception exception)
{
return InternalServerError(exception);
}
}
[JwtAuthorization()]
[ModelStateValidationHandledByFilterAttribute]
[HttpPut("update/{guid}")]
[ProducesResponseType<GetUserResponse>(StatusCodes.Status200OK)]
[ProducesResponseType<BaseResponse<object>>(StatusCodes.Status400BadRequest)]
[ProducesResponseType<BaseResponse<object>>(StatusCodes.Status500InternalServerError)]
public async Task<IActionResult> UpdateUserAsync([FromBody] UpdateUserRequest request, string guid) //NOSONAR
{
try
{
var user = await this._userService.GetUserByGuidAsync(guid);
if (user == null)
{
return NotFound();
}
user = await this._userService.UpdateUserAsync(request!.Data!, user);
var userDto = _mapper?.Map<UserDto>(user);
return Success(String.Empty, userDto);
}
catch (Exception exception)
{
return InternalServerError(exception);
}
}
[JwtAuthorization()]
[ModelStateValidationHandledByFilterAttribute]
[HttpPut("update/{guid}/password")]
[ProducesResponseType<GetUserResponse>(StatusCodes.Status200OK)]
[ProducesResponseType<BaseResponse<object>>(StatusCodes.Status400BadRequest)]
[ProducesResponseType<BaseResponse<object>>(StatusCodes.Status500InternalServerError)]
public async Task<IActionResult> UpdateUserPasswordAsync(string guid, string newPassword)
{
try
{
var user = await this._userService.GetUserByGuidAsync(guid);
if (user == null)
{
return NotFound();
}
user = await this._userService.UpdateUserPasswordAsync(user, newPassword);
var userDto = _mapper?.Map<UserDto>(user);
return Success(String.Empty, userDto);
}
catch (Exception exception)
{
return InternalServerError(exception);
}
}
[JwtAuthorization()]
[ModelStateValidationHandledByFilterAttribute]
[HttpPut("update/{guid}/role")]
[ProducesResponseType<GetUserResponse>(StatusCodes.Status200OK)]
[ProducesResponseType<BaseResponse<object>>(StatusCodes.Status400BadRequest)]
[ProducesResponseType<BaseResponse<object>>(StatusCodes.Status500InternalServerError)]
public async Task<IActionResult> UpdateUserRoleAsync(string guid, string roleGuid)
{
try
{
var role = await this._roleService.GetRoleByGuidAsync(roleGuid);
if (role == null)
{
return BadRequest("Role not found");
}
var user = await this._userService.GetUserByGuidAsync(guid);
if (user == null)
{
return NotFound();
}
user = await this._userService.UpdateUserRoleAsync(user, role);
var userDto = _mapper?.Map<UserDto>(user);
return Success(String.Empty, userDto);
}
catch (Exception exception)
{
return InternalServerError(exception);
}
}
[JwtAuthorization()]
[ModelStateValidationHandledByFilterAttribute]
[HttpDelete("{guid}")]
[ProducesResponseType<GetUserResponse>(StatusCodes.Status200OK)]
[ProducesResponseType<BaseResponse<object>>(StatusCodes.Status404NotFound)]
[ProducesResponseType<BaseResponse<object>>(StatusCodes.Status400BadRequest)]
[ProducesResponseType<BaseResponse<object>>(StatusCodes.Status500InternalServerError)]
public async Task<IActionResult> DeleteUserByGuidAsync(string guid)
{
try
{
var user = await this._userService.GetUserByGuidAsync(guid);
if (user == null || String.IsNullOrEmpty(user.Guid))
{
return NotFound();
}
await this._userService.DeleteUserAsync(user);
return Success(String.Empty);
}
catch (Exception exception)
{
return InternalServerError(exception);
}
}
}
}

View File

@@ -0,0 +1,16 @@
using Microsoft.AspNetCore.Mvc;
using BasicDotnetTemplate.MainProject.Models.Settings;
namespace BasicDotnetTemplate.MainProject.Controllers
{
[Route("[controller]")]
public class VersionController : BaseController
{
public VersionController(
IConfiguration configuration
) : base(configuration) { }
[HttpGet("get")]
public IActionResult GetVersion() => Success(String.Empty, _appSettings?.Settings?.Version);
}
}

View File

@@ -0,0 +1,85 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.IdentityModel.Tokens;
using System;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Text;
using Microsoft.AspNetCore.Authorization;
using BasicDotnetTemplate.MainProject.Models.Settings;
using BasicDotnetTemplate.MainProject.Services;
using DatabaseSqlServer = BasicDotnetTemplate.MainProject.Models.Database.SqlServer;
using BasicDotnetTemplate.MainProject.Utils;
using BasicDotnetTemplate.MainProject.Models.Api.Common.User;
namespace BasicDotnetTemplate.MainProject.Core.Attributes
{
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited = true)]
public class JwtAuthorizationAttribute : Attribute, IAuthorizationFilter
{
public JwtAuthorizationAttribute(
)
{
}
public static void Unauthorized(AuthorizationFilterContext context)
{
context.Result = new UnauthorizedResult();
}
public void OnAuthorization(AuthorizationFilterContext context)
{
// If [AllowAnonymous], skip
if (context.ActionDescriptor.EndpointMetadata.Any(em => em is AllowAnonymousAttribute))
{
return;
}
string? userGuidFromToken = null;
var configuration = context.HttpContext.RequestServices.GetRequiredService<IConfiguration>();
var appSettings = new AppSettings();
configuration.GetSection("AppSettings").Bind(appSettings);
string? headerAuthorization = context.HttpContext.Request.Headers.Authorization.FirstOrDefault();
AuthenticatedUser? userContext = context.HttpContext.Items["User"] != null ? (AuthenticatedUser?)context.HttpContext.Items["User"] : null;
if (userContext == null)
{
Unauthorized(context);
}
else
{
if (!String.IsNullOrEmpty(headerAuthorization))
{
userGuidFromToken = JwtAuthorizationAttribute.ValidateToken(headerAuthorization!, appSettings);
if (String.IsNullOrEmpty(userGuidFromToken))
{
Unauthorized(context);
}
else
{
if (userContext!.Guid != userGuidFromToken)
{
Unauthorized(context);
}
}
}
else
{
Unauthorized(context);
}
}
}
private static string? ValidateToken(string headerAuthorization, AppSettings appSettings)
{
JwtTokenUtils _jwtTokenUtils = new(appSettings);
return _jwtTokenUtils.ValidateToken(headerAuthorization);
}
}
}

View File

@@ -0,0 +1,12 @@
using System;
namespace BasicDotnetTemplate.MainProject.Core.Attributes
{
/// <summary>
/// Indicates that ModelState validation is handled automatically by an Action Filter.
/// Used to suppress SonarCloud warnings about missing ModelState.IsValid checks.
/// </summary>
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public class ModelStateValidationHandledByFilterAttribute : Attribute
{ }
}

View File

@@ -0,0 +1,26 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using MongoDB.Bson;
using MongoDB.Driver;
using MongoDB.EntityFrameworkCore;
using MongoDB.EntityFrameworkCore.Extensions;
using BasicDotnetTemplate.MainProject.Models.Database.Mongo;
namespace BasicDotnetTemplate.MainProject.Core.Database
{
public class MongoDbContext : DbContext
{
public MongoDbContext(DbContextOptions<MongoDbContext> options) : base(options) { }
public DbSet<Log> Logs { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Log>().ToCollection("Logs");
}
}
}

View File

@@ -0,0 +1,18 @@
using Microsoft.EntityFrameworkCore;
using BasicDotnetTemplate.MainProject.Models.Database.SqlServer;
namespace BasicDotnetTemplate.MainProject.Core.Database
{
public class PostgreSqlDbContext : DbContext
{
public PostgreSqlDbContext(DbContextOptions<PostgreSqlDbContext> options)
: base(options)
{
}
}
}

View File

@@ -0,0 +1,83 @@
using Microsoft.EntityFrameworkCore;
using BasicDotnetTemplate.MainProject.Models.Database.SqlServer;
namespace BasicDotnetTemplate.MainProject.Core.Database
{
public class SqlServerContext : DbContext
{
private const string _isDeletedFalse = "[IsDeleted] = 0";
private const string _isEnabled = "[Enabled] = 1";
public SqlServerContext(DbContextOptions<SqlServerContext> options)
: base(options)
{
}
public DbSet<PermissionModule> PermissionModules { get; set; }
public DbSet<PermissionOperation> PermissionOperations { get; set; }
public DbSet<PermissionSystem> PermissionSystems { get; set; }
public DbSet<PermissionSystemModule> PermissionSystemModules { get; set; }
public DbSet<PermissionSystemModuleOperation> PermissionSystemModuleOperations { get; set; }
public DbSet<RolePermissionSystemModuleOperation> RolePermissionSystemModuleOperations { get; set; }
public DbSet<Role> Roles { get; set; }
public DbSet<User> Users { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
#region "INDEXES"
// Indexes
modelBuilder.Entity<User>()
.HasIndex(x => x.Email, "IX_Email");
modelBuilder.Entity<User>()
.HasIndex(x => new { x.IsDeleted, x.Guid }, "IX_IsDeleted_Guid")
.HasFilter(_isDeletedFalse);
modelBuilder.Entity<Role>()
.HasIndex(x => new { x.IsDeleted, x.Guid }, "IX_IsDeleted_Guid")
.HasFilter(_isDeletedFalse);
modelBuilder.Entity<PermissionSystem>()
.HasIndex(x => new { x.IsDeleted }, "IX_IsDeleted")
.HasFilter(_isDeletedFalse);
modelBuilder.Entity<PermissionSystem>()
.HasIndex(x => new { x.Enabled }, "IX_Enabled")
.HasFilter(_isEnabled);
modelBuilder.Entity<PermissionSystem>()
.HasIndex(x => new { x.IsDeleted, x.Name, x.Enabled }, "IX_IsDeleted_Name_Enabled")
.HasFilter(_isEnabled)
.HasFilter(_isDeletedFalse);
modelBuilder.Entity<PermissionModule>()
.HasIndex(x => new { x.IsDeleted }, "IX_IsDeleted")
.HasFilter(_isDeletedFalse);
modelBuilder.Entity<PermissionModule>()
.HasIndex(x => new { x.Enabled }, "IX_Enabled")
.HasFilter(_isEnabled);
modelBuilder.Entity<PermissionModule>()
.HasIndex(x => new { x.IsDeleted, x.Name, x.Enabled }, "IX_IsDeleted_Name_Enabled")
.HasFilter(_isEnabled)
.HasFilter(_isDeletedFalse);
modelBuilder.Entity<PermissionOperation>()
.HasIndex(x => new { x.IsDeleted, x.Name }, "IX_IsDeleted_Name");
modelBuilder.Entity<PermissionSystemModuleOperation>()
.HasIndex(x => new { x.IsDeleted, x.Enabled, x.Guid }, "IX_IsDeleted_Enabled_Guid");
#endregion
}
}
}

View File

@@ -0,0 +1,43 @@
using BasicDotnetTemplate.MainProject.Models.Api.Base;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using System.Threading.Tasks;
namespace BasicDotnetTemplate.MainProject.Core.Filters
{
public class ValidationActionFilter : IAsyncActionFilter
{
private readonly string _requestNotWellFormedMessage = "Request is not well formed";
public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
{
if (!context.ModelState.IsValid)
{
context.Result = new BadRequestObjectResult(new ValidationError
{
Message = _requestNotWellFormedMessage,
Errors = context.ModelState.Where(m =>
m.Value != null && m.Value.Errors.Any())
.ToDictionary(
m => m.Key,
m => m.Value!.Errors.Select(e => e.ErrorMessage).ToList()
)
});
return;
}
var requestBody = context.ActionArguments.Values.FirstOrDefault(arg => arg != null && !arg.GetType().IsPrimitive && arg is not string);
if (requestBody == null)
{
context.Result = new BadRequestObjectResult(new ValidationError
{
Message = _requestNotWellFormedMessage
});
return;
}
await next();
}
}
}

View File

@@ -0,0 +1,16 @@
using BasicDotnetTemplate.MainProject.Models.Api.Common.User;
using SqlServerDatabase = BasicDotnetTemplate.MainProject.Models.Database.SqlServer;
using AutoMapper;
using BasicDotnetTemplate.MainProject.Models.Api.Common.Role;
namespace BasicDotnetTemplate.MainProject.Core.Middlewares;
public class AutoMapperConfiguration : Profile
{
public AutoMapperConfiguration()
{
CreateMap<SqlServerDatabase.Role, RoleDto>();
CreateMap<SqlServerDatabase.User, UserDto>();
}
}

View File

@@ -0,0 +1,10 @@
namespace BasicDotnetTemplate.MainProject.Enum;
public static class PasswordValidationEnum
{
public const string MIN_LENGTH = "Password must be at least 8 characters long";
public const string MIN_UPPER = "Password must have at least 2 uppercase letters";
public const string MIN_LOWER = "Password must have at least 2 lowercase letters";
public const string MIN_NUMBER = "Password must be at least 2 numbers";
public const string MIN_SPECIAL = "Password must be at least 2 special characters";
public const string IDENTICAL_CHARS = "Password cannot have 3 or more consecutive identical characters";
}

View File

@@ -0,0 +1,50 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<OutputType>Exe</OutputType>
<Configuration>Debug</Configuration>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="AutoMapper" Version="14.0.0" />
<PackageReference Include="coverlet.msbuild" Version="6.0.4">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="Microsoft.AspNetCore" Version="2.3.0" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.17" />
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="8.0.17" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.6" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Abstractions" Version="9.0.6" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.6">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="9.0.6" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="9.0.6" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="9.0.6">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="Microsoft.Extensions.Hosting" Version="9.0.6" />
<PackageReference Include="Microsoft.Identity.Web" Version="3.9.3" />
<PackageReference Include="MongoDB.Driver" Version="3.4.0" />
<PackageReference Include="MongoDB.EntityFrameworkCore" Version="9.0.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="NLog" Version="5.5.0" />
<PackageReference Include="NLog.Extensions.Logging" Version="5.5.0" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="9.0.4" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="9.0.1" />
<PackageReference Include="Swashbuckle.AspNetCore.Annotations" Version="9.0.1" />
<PackageReference Include="Swashbuckle.AspNetCore.Filters" Version="9.0.0" />
<PackageReference Include="Swashbuckle.AspNetCore.Filters.Abstractions" Version="9.0.0" />
<PackageReference Include="Swashbuckle.AspNetCore.Newtonsoft" Version="9.0.1" />
<PackageReference Include="Swashbuckle.AspNetCore.Swagger" Version="9.0.1" />
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerGen" Version="9.0.1" />
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerUI" Version="9.0.1" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,132 @@
// <auto-generated />
using System;
using BasicDotnetTemplate.MainProject.Core.Database;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
#nullable disable
namespace MainProject.Migrations
{
[DbContext(typeof(SqlServerContext))]
[Migration("20240904211920_InitialCreate")]
partial class InitialCreate
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "8.0.8")
.HasAnnotation("Relational:MaxIdentifierLength", 128);
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
modelBuilder.Entity("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.Role", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime2");
b.Property<int>("CreationUserId")
.HasColumnType("int");
b.Property<DateTime>("DeletionTime")
.HasColumnType("datetime2");
b.Property<int>("DeletionUserId")
.HasColumnType("int");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<DateTime>("UpdateTime")
.HasColumnType("datetime2");
b.Property<int>("UpdateUserId")
.HasColumnType("int");
b.HasKey("Id");
b.ToTable("Role");
});
modelBuilder.Entity("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.User", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime2");
b.Property<int>("CreationUserId")
.HasColumnType("int");
b.Property<DateTime>("DeletionTime")
.HasColumnType("datetime2");
b.Property<int>("DeletionUserId")
.HasColumnType("int");
b.Property<string>("Email")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("FirstName")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("LastName")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("PasswordHash")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<int>("RoleId")
.HasColumnType("int");
b.Property<DateTime>("UpdateTime")
.HasColumnType("datetime2");
b.Property<int>("UpdateUserId")
.HasColumnType("int");
b.Property<string>("Username")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.HasKey("Id");
b.HasIndex("RoleId");
b.ToTable("Users");
});
modelBuilder.Entity("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.User", b =>
{
b.HasOne("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.Role", "Role")
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Role");
});
#pragma warning restore 612, 618
}
}
}

View File

@@ -0,0 +1,79 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace MainProject.Migrations
{
/// <inheritdoc />
public partial class InitialCreate : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Role",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
Name = table.Column<string>(type: "nvarchar(max)", nullable: false),
CreationTime = table.Column<DateTime>(type: "datetime2", nullable: false),
CreationUserId = table.Column<int>(type: "int", nullable: false),
UpdateTime = table.Column<DateTime>(type: "datetime2", nullable: false),
UpdateUserId = table.Column<int>(type: "int", nullable: false),
DeletionTime = table.Column<DateTime>(type: "datetime2", nullable: false),
DeletionUserId = table.Column<int>(type: "int", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Role", x => x.Id);
});
migrationBuilder.CreateTable(
name: "Users",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
Username = table.Column<string>(type: "nvarchar(max)", nullable: false),
FirstName = table.Column<string>(type: "nvarchar(max)", nullable: false),
LastName = table.Column<string>(type: "nvarchar(max)", nullable: false),
Email = table.Column<string>(type: "nvarchar(max)", nullable: false),
RoleId = table.Column<int>(type: "int", nullable: false),
PasswordHash = table.Column<string>(type: "nvarchar(max)", nullable: false),
CreationTime = table.Column<DateTime>(type: "datetime2", nullable: false),
CreationUserId = table.Column<int>(type: "int", nullable: false),
UpdateTime = table.Column<DateTime>(type: "datetime2", nullable: false),
UpdateUserId = table.Column<int>(type: "int", nullable: false),
DeletionTime = table.Column<DateTime>(type: "datetime2", nullable: false),
DeletionUserId = table.Column<int>(type: "int", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Users", x => x.Id);
table.ForeignKey(
name: "FK_Users_Role_RoleId",
column: x => x.RoleId,
principalTable: "Role",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateIndex(
name: "IX_Users_RoleId",
table: "Users",
column: "RoleId");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Users");
migrationBuilder.DropTable(
name: "Role");
}
}
}

View File

@@ -0,0 +1,132 @@
// <auto-generated />
using System;
using BasicDotnetTemplate.MainProject.Core.Database;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
#nullable disable
namespace MainProject.Migrations
{
[DbContext(typeof(SqlServerContext))]
[Migration("20241129231345_Try")]
partial class Try
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "8.0.8")
.HasAnnotation("Relational:MaxIdentifierLength", 128);
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
modelBuilder.Entity("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.Role", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime2");
b.Property<int>("CreationUserId")
.HasColumnType("int");
b.Property<DateTime>("DeletionTime")
.HasColumnType("datetime2");
b.Property<int>("DeletionUserId")
.HasColumnType("int");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<DateTime>("UpdateTime")
.HasColumnType("datetime2");
b.Property<int>("UpdateUserId")
.HasColumnType("int");
b.HasKey("Id");
b.ToTable("Role");
});
modelBuilder.Entity("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.User", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime2");
b.Property<int>("CreationUserId")
.HasColumnType("int");
b.Property<DateTime>("DeletionTime")
.HasColumnType("datetime2");
b.Property<int>("DeletionUserId")
.HasColumnType("int");
b.Property<string>("Email")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("FirstName")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("LastName")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("PasswordHash")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<int>("RoleId")
.HasColumnType("int");
b.Property<DateTime>("UpdateTime")
.HasColumnType("datetime2");
b.Property<int>("UpdateUserId")
.HasColumnType("int");
b.Property<string>("Username")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.HasKey("Id");
b.HasIndex("RoleId");
b.ToTable("Users");
});
modelBuilder.Entity("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.User", b =>
{
b.HasOne("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.Role", "Role")
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Role");
});
#pragma warning restore 612, 618
}
}
}

View File

@@ -0,0 +1,22 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace MainProject.Migrations
{
/// <inheritdoc />
public partial class Try : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
}
}
}

View File

@@ -0,0 +1,154 @@
// <auto-generated />
using System;
using BasicDotnetTemplate.MainProject.Core.Database;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
#nullable disable
namespace MainProject.Migrations
{
[DbContext(typeof(SqlServerContext))]
[Migration("20250311195750_AlterTableUser")]
partial class AlterTableUser
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "9.0.2")
.HasAnnotation("Relational:MaxIdentifierLength", 128);
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
modelBuilder.Entity("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.Role", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime2");
b.Property<int>("CreationUserId")
.HasColumnType("int");
b.Property<DateTime>("DeletionTime")
.HasColumnType("datetime2");
b.Property<int>("DeletionUserId")
.HasColumnType("int");
b.Property<string>("Guid")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<bool>("IsDeleted")
.HasColumnType("bit");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<DateTime>("UpdateTime")
.HasColumnType("datetime2");
b.Property<int>("UpdateUserId")
.HasColumnType("int");
b.HasKey("Id");
b.ToTable("Role");
});
modelBuilder.Entity("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.User", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime2");
b.Property<int>("CreationUserId")
.HasColumnType("int");
b.Property<DateTime>("DeletionTime")
.HasColumnType("datetime2");
b.Property<int>("DeletionUserId")
.HasColumnType("int");
b.Property<string>("Email")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("FirstName")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("Guid")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<bool>("IsDeleted")
.HasColumnType("bit");
b.Property<string>("LastName")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("Password")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("PasswordHash")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("PasswordSalt")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<int>("RoleId")
.HasColumnType("int");
b.Property<DateTime>("UpdateTime")
.HasColumnType("datetime2");
b.Property<int>("UpdateUserId")
.HasColumnType("int");
b.Property<string>("Username")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.HasKey("Id");
b.HasIndex("RoleId");
b.ToTable("Users");
});
modelBuilder.Entity("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.User", b =>
{
b.HasOne("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.Role", "Role")
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Role");
});
#pragma warning restore 612, 618
}
}
}

View File

@@ -0,0 +1,84 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace MainProject.Migrations
{
/// <inheritdoc />
public partial class AlterTableUser : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<string>(
name: "Guid",
table: "Users",
type: "nvarchar(max)",
nullable: false,
defaultValue: "");
migrationBuilder.AddColumn<bool>(
name: "IsDeleted",
table: "Users",
type: "bit",
nullable: false,
defaultValue: false);
migrationBuilder.AddColumn<string>(
name: "Password",
table: "Users",
type: "nvarchar(max)",
nullable: false,
defaultValue: "");
migrationBuilder.AddColumn<string>(
name: "PasswordSalt",
table: "Users",
type: "nvarchar(max)",
nullable: false,
defaultValue: "");
migrationBuilder.AddColumn<string>(
name: "Guid",
table: "Role",
type: "nvarchar(max)",
nullable: false,
defaultValue: "");
migrationBuilder.AddColumn<bool>(
name: "IsDeleted",
table: "Role",
type: "bit",
nullable: false,
defaultValue: false);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "Guid",
table: "Users");
migrationBuilder.DropColumn(
name: "IsDeleted",
table: "Users");
migrationBuilder.DropColumn(
name: "Password",
table: "Users");
migrationBuilder.DropColumn(
name: "PasswordSalt",
table: "Users");
migrationBuilder.DropColumn(
name: "Guid",
table: "Role");
migrationBuilder.DropColumn(
name: "IsDeleted",
table: "Role");
}
}
}

View File

@@ -0,0 +1,170 @@
// <auto-generated />
using System;
using BasicDotnetTemplate.MainProject.Core.Database;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
#nullable disable
namespace MainProject.Migrations
{
[DbContext(typeof(SqlServerContext))]
[Migration("20250312234517_AlterTableUserMaxLengthIndexes")]
partial class AlterTableUserMaxLengthIndexes
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "9.0.2")
.HasAnnotation("Relational:MaxIdentifierLength", 128);
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
modelBuilder.Entity("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.Role", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime2");
b.Property<int>("CreationUserId")
.HasColumnType("int");
b.Property<DateTime>("DeletionTime")
.HasColumnType("datetime2");
b.Property<int>("DeletionUserId")
.HasColumnType("int");
b.Property<string>("Guid")
.IsRequired()
.HasMaxLength(45)
.HasColumnType("nvarchar(45)");
b.Property<bool>("IsDeleted")
.HasColumnType("bit");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<DateTime>("UpdateTime")
.HasColumnType("datetime2");
b.Property<int>("UpdateUserId")
.HasColumnType("int");
b.HasKey("Id");
b.ToTable("Role");
});
modelBuilder.Entity("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.User", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime2");
b.Property<int>("CreationUserId")
.HasColumnType("int");
b.Property<DateTime>("DeletionTime")
.HasColumnType("datetime2");
b.Property<int>("DeletionUserId")
.HasColumnType("int");
b.Property<string>("Email")
.IsRequired()
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<string>("FirstName")
.IsRequired()
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<string>("Guid")
.IsRequired()
.HasMaxLength(45)
.HasColumnType("nvarchar(45)");
b.Property<bool>("IsDeleted")
.HasColumnType("bit");
b.Property<bool>("IsTestUser")
.HasColumnType("bit");
b.Property<string>("LastName")
.IsRequired()
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<string>("Password")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("PasswordHash")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("PasswordSalt")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<int>("RoleId")
.HasColumnType("int");
b.Property<DateTime>("UpdateTime")
.HasColumnType("datetime2");
b.Property<int>("UpdateUserId")
.HasColumnType("int");
b.Property<string>("Username")
.IsRequired()
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.HasKey("Id");
b.HasIndex("RoleId");
b.HasIndex(new[] { "Email" }, "IX_Email");
b.HasIndex(new[] { "IsDeleted", "Guid" }, "IX_IsDeleted_Guid")
.HasFilter("[IsDeleted] = 0");
b.HasIndex(new[] { "Username" }, "IX_Username");
b.ToTable("Users");
});
modelBuilder.Entity("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.User", b =>
{
b.HasOne("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.Role", "Role")
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Role");
});
#pragma warning restore 612, 618
}
}
}

View File

@@ -0,0 +1,165 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace MainProject.Migrations
{
/// <inheritdoc />
public partial class AlterTableUserMaxLengthIndexes : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterColumn<string>(
name: "Username",
table: "Users",
type: "nvarchar(200)",
maxLength: 200,
nullable: false,
oldClrType: typeof(string),
oldType: "nvarchar(max)");
migrationBuilder.AlterColumn<string>(
name: "LastName",
table: "Users",
type: "nvarchar(200)",
maxLength: 200,
nullable: false,
oldClrType: typeof(string),
oldType: "nvarchar(max)");
migrationBuilder.AlterColumn<string>(
name: "Guid",
table: "Users",
type: "nvarchar(45)",
maxLength: 45,
nullable: false,
oldClrType: typeof(string),
oldType: "nvarchar(max)");
migrationBuilder.AlterColumn<string>(
name: "FirstName",
table: "Users",
type: "nvarchar(200)",
maxLength: 200,
nullable: false,
oldClrType: typeof(string),
oldType: "nvarchar(max)");
migrationBuilder.AlterColumn<string>(
name: "Email",
table: "Users",
type: "nvarchar(200)",
maxLength: 200,
nullable: false,
oldClrType: typeof(string),
oldType: "nvarchar(max)");
migrationBuilder.AddColumn<bool>(
name: "IsTestUser",
table: "Users",
type: "bit",
nullable: false,
defaultValue: false);
migrationBuilder.AlterColumn<string>(
name: "Guid",
table: "Role",
type: "nvarchar(45)",
maxLength: 45,
nullable: false,
oldClrType: typeof(string),
oldType: "nvarchar(max)");
migrationBuilder.CreateIndex(
name: "IX_Email",
table: "Users",
column: "Email");
migrationBuilder.CreateIndex(
name: "IX_IsDeleted_Guid",
table: "Users",
columns: new[] { "IsDeleted", "Guid" },
filter: "[IsDeleted] = 0");
migrationBuilder.CreateIndex(
name: "IX_Username",
table: "Users",
column: "Username");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropIndex(
name: "IX_Email",
table: "Users");
migrationBuilder.DropIndex(
name: "IX_IsDeleted_Guid",
table: "Users");
migrationBuilder.DropIndex(
name: "IX_Username",
table: "Users");
migrationBuilder.DropColumn(
name: "IsTestUser",
table: "Users");
migrationBuilder.AlterColumn<string>(
name: "Username",
table: "Users",
type: "nvarchar(max)",
nullable: false,
oldClrType: typeof(string),
oldType: "nvarchar(200)",
oldMaxLength: 200);
migrationBuilder.AlterColumn<string>(
name: "LastName",
table: "Users",
type: "nvarchar(max)",
nullable: false,
oldClrType: typeof(string),
oldType: "nvarchar(200)",
oldMaxLength: 200);
migrationBuilder.AlterColumn<string>(
name: "Guid",
table: "Users",
type: "nvarchar(max)",
nullable: false,
oldClrType: typeof(string),
oldType: "nvarchar(45)",
oldMaxLength: 45);
migrationBuilder.AlterColumn<string>(
name: "FirstName",
table: "Users",
type: "nvarchar(max)",
nullable: false,
oldClrType: typeof(string),
oldType: "nvarchar(200)",
oldMaxLength: 200);
migrationBuilder.AlterColumn<string>(
name: "Email",
table: "Users",
type: "nvarchar(max)",
nullable: false,
oldClrType: typeof(string),
oldType: "nvarchar(200)",
oldMaxLength: 200);
migrationBuilder.AlterColumn<string>(
name: "Guid",
table: "Role",
type: "nvarchar(max)",
nullable: false,
oldClrType: typeof(string),
oldType: "nvarchar(45)",
oldMaxLength: 45);
}
}
}

View File

@@ -0,0 +1,167 @@
// <auto-generated />
using System;
using BasicDotnetTemplate.MainProject.Core.Database;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
#nullable disable
namespace MainProject.Migrations
{
[DbContext(typeof(SqlServerContext))]
[Migration("20250316014620_AlterTablesUsersAndRoles")]
partial class AlterTablesUsersAndRoles
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "9.0.2")
.HasAnnotation("Relational:MaxIdentifierLength", 128);
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
modelBuilder.Entity("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.Role", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime2");
b.Property<int?>("CreationUserId")
.HasColumnType("int");
b.Property<DateTime>("DeletionTime")
.HasColumnType("datetime2");
b.Property<int?>("DeletionUserId")
.HasColumnType("int");
b.Property<string>("Guid")
.IsRequired()
.HasMaxLength(45)
.HasColumnType("nvarchar(45)");
b.Property<bool>("IsDeleted")
.HasColumnType("bit");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("nvarchar(100)");
b.Property<DateTime>("UpdateTime")
.HasColumnType("datetime2");
b.Property<int?>("UpdateUserId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex(new[] { "IsDeleted", "Guid" }, "IX_IsDeleted_Guid")
.HasFilter("[IsDeleted] = 0");
b.ToTable("Roles");
});
modelBuilder.Entity("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.User", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime2");
b.Property<int?>("CreationUserId")
.HasColumnType("int");
b.Property<DateTime>("DeletionTime")
.HasColumnType("datetime2");
b.Property<int?>("DeletionUserId")
.HasColumnType("int");
b.Property<string>("Email")
.IsRequired()
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<string>("FirstName")
.IsRequired()
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<string>("Guid")
.IsRequired()
.HasMaxLength(45)
.HasColumnType("nvarchar(45)");
b.Property<bool>("IsDeleted")
.HasColumnType("bit");
b.Property<bool>("IsTestUser")
.HasColumnType("bit");
b.Property<string>("LastName")
.IsRequired()
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<string>("Password")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("PasswordHash")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("PasswordSalt")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<int>("RoleId")
.HasColumnType("int");
b.Property<DateTime>("UpdateTime")
.HasColumnType("datetime2");
b.Property<int?>("UpdateUserId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("RoleId");
b.HasIndex(new[] { "Email" }, "IX_Email");
b.HasIndex(new[] { "IsDeleted", "Guid" }, "IX_IsDeleted_Guid")
.HasFilter("[IsDeleted] = 0");
b.ToTable("Users");
});
modelBuilder.Entity("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.User", b =>
{
b.HasOne("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.Role", "Role")
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Role");
});
#pragma warning restore 612, 618
}
}
}

View File

@@ -0,0 +1,225 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace MainProject.Migrations
{
/// <inheritdoc />
public partial class AlterTablesUsersAndRoles : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "FK_Users_Role_RoleId",
table: "Users");
migrationBuilder.DropIndex(
name: "IX_Username",
table: "Users");
migrationBuilder.DropPrimaryKey(
name: "PK_Role",
table: "Role");
migrationBuilder.DropColumn(
name: "Username",
table: "Users");
migrationBuilder.RenameTable(
name: "Role",
newName: "Roles");
migrationBuilder.AlterColumn<int>(
name: "UpdateUserId",
table: "Users",
type: "int",
nullable: true,
oldClrType: typeof(int),
oldType: "int");
migrationBuilder.AlterColumn<int>(
name: "DeletionUserId",
table: "Users",
type: "int",
nullable: true,
oldClrType: typeof(int),
oldType: "int");
migrationBuilder.AlterColumn<int>(
name: "CreationUserId",
table: "Users",
type: "int",
nullable: true,
oldClrType: typeof(int),
oldType: "int");
migrationBuilder.AlterColumn<int>(
name: "UpdateUserId",
table: "Roles",
type: "int",
nullable: true,
oldClrType: typeof(int),
oldType: "int");
migrationBuilder.AlterColumn<string>(
name: "Name",
table: "Roles",
type: "nvarchar(100)",
maxLength: 100,
nullable: false,
oldClrType: typeof(string),
oldType: "nvarchar(max)");
migrationBuilder.AlterColumn<int>(
name: "DeletionUserId",
table: "Roles",
type: "int",
nullable: true,
oldClrType: typeof(int),
oldType: "int");
migrationBuilder.AlterColumn<int>(
name: "CreationUserId",
table: "Roles",
type: "int",
nullable: true,
oldClrType: typeof(int),
oldType: "int");
migrationBuilder.AddPrimaryKey(
name: "PK_Roles",
table: "Roles",
column: "Id");
migrationBuilder.CreateIndex(
name: "IX_IsDeleted_Guid",
table: "Roles",
columns: new[] { "IsDeleted", "Guid" },
filter: "[IsDeleted] = 0");
migrationBuilder.AddForeignKey(
name: "FK_Users_Roles_RoleId",
table: "Users",
column: "RoleId",
principalTable: "Roles",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "FK_Users_Roles_RoleId",
table: "Users");
migrationBuilder.DropPrimaryKey(
name: "PK_Roles",
table: "Roles");
migrationBuilder.DropIndex(
name: "IX_IsDeleted_Guid",
table: "Roles");
migrationBuilder.RenameTable(
name: "Roles",
newName: "Role");
migrationBuilder.AlterColumn<int>(
name: "UpdateUserId",
table: "Users",
type: "int",
nullable: false,
defaultValue: 0,
oldClrType: typeof(int),
oldType: "int",
oldNullable: true);
migrationBuilder.AlterColumn<int>(
name: "DeletionUserId",
table: "Users",
type: "int",
nullable: false,
defaultValue: 0,
oldClrType: typeof(int),
oldType: "int",
oldNullable: true);
migrationBuilder.AlterColumn<int>(
name: "CreationUserId",
table: "Users",
type: "int",
nullable: false,
defaultValue: 0,
oldClrType: typeof(int),
oldType: "int",
oldNullable: true);
migrationBuilder.AddColumn<string>(
name: "Username",
table: "Users",
type: "nvarchar(200)",
maxLength: 200,
nullable: false,
defaultValue: "");
migrationBuilder.AlterColumn<int>(
name: "UpdateUserId",
table: "Role",
type: "int",
nullable: false,
defaultValue: 0,
oldClrType: typeof(int),
oldType: "int",
oldNullable: true);
migrationBuilder.AlterColumn<string>(
name: "Name",
table: "Role",
type: "nvarchar(max)",
nullable: false,
oldClrType: typeof(string),
oldType: "nvarchar(100)",
oldMaxLength: 100);
migrationBuilder.AlterColumn<int>(
name: "DeletionUserId",
table: "Role",
type: "int",
nullable: false,
defaultValue: 0,
oldClrType: typeof(int),
oldType: "int",
oldNullable: true);
migrationBuilder.AlterColumn<int>(
name: "CreationUserId",
table: "Role",
type: "int",
nullable: false,
defaultValue: 0,
oldClrType: typeof(int),
oldType: "int",
oldNullable: true);
migrationBuilder.AddPrimaryKey(
name: "PK_Role",
table: "Role",
column: "Id");
migrationBuilder.CreateIndex(
name: "IX_Username",
table: "Users",
column: "Username");
migrationBuilder.AddForeignKey(
name: "FK_Users_Role_RoleId",
table: "Users",
column: "RoleId",
principalTable: "Role",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
}
}
}

View File

@@ -0,0 +1,167 @@
// <auto-generated />
using System;
using BasicDotnetTemplate.MainProject.Core.Database;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
#nullable disable
namespace MainProject.Migrations
{
[DbContext(typeof(SqlServerContext))]
[Migration("20250316212343_AlterBaseUpdateTimeDeletionTimeNullable")]
partial class AlterBaseUpdateTimeDeletionTimeNullable
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "9.0.2")
.HasAnnotation("Relational:MaxIdentifierLength", 128);
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
modelBuilder.Entity("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.Role", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime2");
b.Property<int?>("CreationUserId")
.HasColumnType("int");
b.Property<DateTime?>("DeletionTime")
.HasColumnType("datetime2");
b.Property<int?>("DeletionUserId")
.HasColumnType("int");
b.Property<string>("Guid")
.IsRequired()
.HasMaxLength(45)
.HasColumnType("nvarchar(45)");
b.Property<bool>("IsDeleted")
.HasColumnType("bit");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("nvarchar(100)");
b.Property<DateTime?>("UpdateTime")
.HasColumnType("datetime2");
b.Property<int?>("UpdateUserId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex(new[] { "IsDeleted", "Guid" }, "IX_IsDeleted_Guid")
.HasFilter("[IsDeleted] = 0");
b.ToTable("Roles");
});
modelBuilder.Entity("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.User", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime2");
b.Property<int?>("CreationUserId")
.HasColumnType("int");
b.Property<DateTime?>("DeletionTime")
.HasColumnType("datetime2");
b.Property<int?>("DeletionUserId")
.HasColumnType("int");
b.Property<string>("Email")
.IsRequired()
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<string>("FirstName")
.IsRequired()
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<string>("Guid")
.IsRequired()
.HasMaxLength(45)
.HasColumnType("nvarchar(45)");
b.Property<bool>("IsDeleted")
.HasColumnType("bit");
b.Property<bool>("IsTestUser")
.HasColumnType("bit");
b.Property<string>("LastName")
.IsRequired()
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<string>("Password")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("PasswordHash")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("PasswordSalt")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<int>("RoleId")
.HasColumnType("int");
b.Property<DateTime?>("UpdateTime")
.HasColumnType("datetime2");
b.Property<int?>("UpdateUserId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("RoleId");
b.HasIndex(new[] { "Email" }, "IX_Email");
b.HasIndex(new[] { "IsDeleted", "Guid" }, "IX_IsDeleted_Guid")
.HasFilter("[IsDeleted] = 0");
b.ToTable("Users");
});
modelBuilder.Entity("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.User", b =>
{
b.HasOne("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.Role", "Role")
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Role");
});
#pragma warning restore 612, 618
}
}
}

View File

@@ -0,0 +1,91 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace MainProject.Migrations
{
/// <inheritdoc />
public partial class AlterBaseUpdateTimeDeletionTimeNullable : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterColumn<DateTime>(
name: "UpdateTime",
table: "Users",
type: "datetime2",
nullable: true,
oldClrType: typeof(DateTime),
oldType: "datetime2");
migrationBuilder.AlterColumn<DateTime>(
name: "DeletionTime",
table: "Users",
type: "datetime2",
nullable: true,
oldClrType: typeof(DateTime),
oldType: "datetime2");
migrationBuilder.AlterColumn<DateTime>(
name: "UpdateTime",
table: "Roles",
type: "datetime2",
nullable: true,
oldClrType: typeof(DateTime),
oldType: "datetime2");
migrationBuilder.AlterColumn<DateTime>(
name: "DeletionTime",
table: "Roles",
type: "datetime2",
nullable: true,
oldClrType: typeof(DateTime),
oldType: "datetime2");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterColumn<DateTime>(
name: "UpdateTime",
table: "Users",
type: "datetime2",
nullable: false,
defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified),
oldClrType: typeof(DateTime),
oldType: "datetime2",
oldNullable: true);
migrationBuilder.AlterColumn<DateTime>(
name: "DeletionTime",
table: "Users",
type: "datetime2",
nullable: false,
defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified),
oldClrType: typeof(DateTime),
oldType: "datetime2",
oldNullable: true);
migrationBuilder.AlterColumn<DateTime>(
name: "UpdateTime",
table: "Roles",
type: "datetime2",
nullable: false,
defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified),
oldClrType: typeof(DateTime),
oldType: "datetime2",
oldNullable: true);
migrationBuilder.AlterColumn<DateTime>(
name: "DeletionTime",
table: "Roles",
type: "datetime2",
nullable: false,
defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified),
oldClrType: typeof(DateTime),
oldType: "datetime2",
oldNullable: true);
}
}
}

View File

@@ -0,0 +1,170 @@
// <auto-generated />
using System;
using BasicDotnetTemplate.MainProject.Core.Database;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
#nullable disable
namespace MainProject.Migrations
{
[DbContext(typeof(SqlServerContext))]
[Migration("20250316212722_AlterTableRoleAddedIsNotEditable")]
partial class AlterTableRoleAddedIsNotEditable
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "9.0.2")
.HasAnnotation("Relational:MaxIdentifierLength", 128);
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
modelBuilder.Entity("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.Role", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime2");
b.Property<int?>("CreationUserId")
.HasColumnType("int");
b.Property<DateTime?>("DeletionTime")
.HasColumnType("datetime2");
b.Property<int?>("DeletionUserId")
.HasColumnType("int");
b.Property<string>("Guid")
.IsRequired()
.HasMaxLength(45)
.HasColumnType("nvarchar(45)");
b.Property<bool>("IsDeleted")
.HasColumnType("bit");
b.Property<bool>("IsNotEditable")
.HasColumnType("bit");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("nvarchar(100)");
b.Property<DateTime?>("UpdateTime")
.HasColumnType("datetime2");
b.Property<int?>("UpdateUserId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex(new[] { "IsDeleted", "Guid" }, "IX_IsDeleted_Guid")
.HasFilter("[IsDeleted] = 0");
b.ToTable("Roles");
});
modelBuilder.Entity("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.User", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime2");
b.Property<int?>("CreationUserId")
.HasColumnType("int");
b.Property<DateTime?>("DeletionTime")
.HasColumnType("datetime2");
b.Property<int?>("DeletionUserId")
.HasColumnType("int");
b.Property<string>("Email")
.IsRequired()
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<string>("FirstName")
.IsRequired()
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<string>("Guid")
.IsRequired()
.HasMaxLength(45)
.HasColumnType("nvarchar(45)");
b.Property<bool>("IsDeleted")
.HasColumnType("bit");
b.Property<bool>("IsTestUser")
.HasColumnType("bit");
b.Property<string>("LastName")
.IsRequired()
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<string>("Password")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("PasswordHash")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("PasswordSalt")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<int>("RoleId")
.HasColumnType("int");
b.Property<DateTime?>("UpdateTime")
.HasColumnType("datetime2");
b.Property<int?>("UpdateUserId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("RoleId");
b.HasIndex(new[] { "Email" }, "IX_Email");
b.HasIndex(new[] { "IsDeleted", "Guid" }, "IX_IsDeleted_Guid")
.HasFilter("[IsDeleted] = 0");
b.ToTable("Users");
});
modelBuilder.Entity("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.User", b =>
{
b.HasOne("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.Role", "Role")
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Role");
});
#pragma warning restore 612, 618
}
}
}

View File

@@ -0,0 +1,29 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace MainProject.Migrations
{
/// <inheritdoc />
public partial class AlterTableRoleAddedIsNotEditable : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<bool>(
name: "IsNotEditable",
table: "Roles",
type: "bit",
nullable: false,
defaultValue: false);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "IsNotEditable",
table: "Roles");
}
}
}

View File

@@ -0,0 +1,543 @@
// <auto-generated />
using System;
using BasicDotnetTemplate.MainProject.Core.Database;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
#nullable disable
namespace MainProject.Migrations
{
[DbContext(typeof(SqlServerContext))]
[Migration("20250426183010_AddingPermissionsTables")]
partial class AddingPermissionsTables
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "9.0.2")
.HasAnnotation("Relational:MaxIdentifierLength", 128);
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
modelBuilder.Entity("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.PermissionModule", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime2");
b.Property<int?>("CreationUserId")
.HasColumnType("int");
b.Property<DateTime?>("DeletionTime")
.HasColumnType("datetime2");
b.Property<int?>("DeletionUserId")
.HasColumnType("int");
b.Property<bool>("Enabled")
.HasColumnType("bit");
b.Property<string>("Guid")
.IsRequired()
.HasMaxLength(45)
.HasColumnType("nvarchar(45)");
b.Property<bool>("IsDeleted")
.HasColumnType("bit");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("nvarchar(100)");
b.Property<DateTime?>("UpdateTime")
.HasColumnType("datetime2");
b.Property<int?>("UpdateUserId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex(new[] { "Enabled" }, "IX_Enabled")
.HasFilter("[Enabled] = 1");
b.HasIndex(new[] { "IsDeleted" }, "IX_IsDeleted")
.HasFilter("[IsDeleted] = 0");
b.HasIndex(new[] { "IsDeleted", "Name", "Enabled" }, "IX_IsDeleted_Name_Enabled")
.HasFilter("[IsDeleted] = 0");
b.ToTable("PermissionModules");
});
modelBuilder.Entity("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.PermissionOperation", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime2");
b.Property<int?>("CreationUserId")
.HasColumnType("int");
b.Property<DateTime?>("DeletionTime")
.HasColumnType("datetime2");
b.Property<int?>("DeletionUserId")
.HasColumnType("int");
b.Property<string>("Guid")
.IsRequired()
.HasMaxLength(45)
.HasColumnType("nvarchar(45)");
b.Property<bool>("IsDeleted")
.HasColumnType("bit");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("nvarchar(100)");
b.Property<DateTime?>("UpdateTime")
.HasColumnType("datetime2");
b.Property<int?>("UpdateUserId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex(new[] { "IsDeleted", "Name" }, "IX_IsDeleted_Name");
b.ToTable("PermissionOperations");
});
modelBuilder.Entity("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.PermissionSystem", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime2");
b.Property<int?>("CreationUserId")
.HasColumnType("int");
b.Property<DateTime?>("DeletionTime")
.HasColumnType("datetime2");
b.Property<int?>("DeletionUserId")
.HasColumnType("int");
b.Property<bool>("Enabled")
.HasColumnType("bit");
b.Property<string>("Guid")
.IsRequired()
.HasMaxLength(45)
.HasColumnType("nvarchar(45)");
b.Property<bool>("IsDeleted")
.HasColumnType("bit");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("nvarchar(100)");
b.Property<DateTime?>("UpdateTime")
.HasColumnType("datetime2");
b.Property<int?>("UpdateUserId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex(new[] { "Enabled" }, "IX_Enabled")
.HasFilter("[Enabled] = 1");
b.HasIndex(new[] { "IsDeleted" }, "IX_IsDeleted")
.HasFilter("[IsDeleted] = 0");
b.HasIndex(new[] { "IsDeleted", "Name", "Enabled" }, "IX_IsDeleted_Name_Enabled")
.HasFilter("[IsDeleted] = 0");
b.ToTable("PermissionSystems");
});
modelBuilder.Entity("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.PermissionSystemModule", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime2");
b.Property<int?>("CreationUserId")
.HasColumnType("int");
b.Property<DateTime?>("DeletionTime")
.HasColumnType("datetime2");
b.Property<int?>("DeletionUserId")
.HasColumnType("int");
b.Property<bool>("Enabled")
.HasColumnType("bit");
b.Property<string>("Guid")
.IsRequired()
.HasMaxLength(45)
.HasColumnType("nvarchar(45)");
b.Property<bool>("IsDeleted")
.HasColumnType("bit");
b.Property<int>("PermissionModuleId")
.HasColumnType("int");
b.Property<int>("PermissionSystemId")
.HasColumnType("int");
b.Property<DateTime?>("UpdateTime")
.HasColumnType("datetime2");
b.Property<int?>("UpdateUserId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("PermissionModuleId");
b.HasIndex("PermissionSystemId");
b.ToTable("PermissionSystemModules");
});
modelBuilder.Entity("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.PermissionSystemModuleOperation", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime2");
b.Property<int?>("CreationUserId")
.HasColumnType("int");
b.Property<DateTime?>("DeletionTime")
.HasColumnType("datetime2");
b.Property<int?>("DeletionUserId")
.HasColumnType("int");
b.Property<bool>("Enabled")
.HasColumnType("bit");
b.Property<string>("Guid")
.IsRequired()
.HasMaxLength(45)
.HasColumnType("nvarchar(45)");
b.Property<bool>("IsDeleted")
.HasColumnType("bit");
b.Property<int>("PermissionOperationId")
.HasColumnType("int");
b.Property<int>("PermissionSystemModuleId")
.HasColumnType("int");
b.Property<DateTime?>("UpdateTime")
.HasColumnType("datetime2");
b.Property<int?>("UpdateUserId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("PermissionOperationId");
b.HasIndex("PermissionSystemModuleId");
b.HasIndex(new[] { "IsDeleted", "Enabled", "Guid" }, "IX_IsDeleted_Enabled_Guid");
b.ToTable("PermissionSystemModuleOperations");
});
modelBuilder.Entity("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.Role", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime2");
b.Property<int?>("CreationUserId")
.HasColumnType("int");
b.Property<DateTime?>("DeletionTime")
.HasColumnType("datetime2");
b.Property<int?>("DeletionUserId")
.HasColumnType("int");
b.Property<string>("Guid")
.IsRequired()
.HasMaxLength(45)
.HasColumnType("nvarchar(45)");
b.Property<bool>("IsDeleted")
.HasColumnType("bit");
b.Property<bool>("IsNotEditable")
.HasColumnType("bit");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("nvarchar(100)");
b.Property<DateTime?>("UpdateTime")
.HasColumnType("datetime2");
b.Property<int?>("UpdateUserId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex(new[] { "IsDeleted", "Guid" }, "IX_IsDeleted_Guid")
.HasFilter("[IsDeleted] = 0");
b.ToTable("Roles");
});
modelBuilder.Entity("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.RolePermissionSystemModuleOperation", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<bool>("Active")
.HasColumnType("bit");
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime2");
b.Property<int?>("CreationUserId")
.HasColumnType("int");
b.Property<DateTime?>("DeletionTime")
.HasColumnType("datetime2");
b.Property<int?>("DeletionUserId")
.HasColumnType("int");
b.Property<string>("Guid")
.IsRequired()
.HasMaxLength(45)
.HasColumnType("nvarchar(45)");
b.Property<bool>("IsDeleted")
.HasColumnType("bit");
b.Property<int>("PermissionSystemModuleOperationId")
.HasColumnType("int");
b.Property<int>("RoleId")
.HasColumnType("int");
b.Property<DateTime?>("UpdateTime")
.HasColumnType("datetime2");
b.Property<int?>("UpdateUserId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("PermissionSystemModuleOperationId");
b.HasIndex("RoleId");
b.ToTable("RolePermissionSystemModuleOperations");
});
modelBuilder.Entity("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.User", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime2");
b.Property<int?>("CreationUserId")
.HasColumnType("int");
b.Property<DateTime?>("DeletionTime")
.HasColumnType("datetime2");
b.Property<int?>("DeletionUserId")
.HasColumnType("int");
b.Property<string>("Email")
.IsRequired()
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<string>("FirstName")
.IsRequired()
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<string>("Guid")
.IsRequired()
.HasMaxLength(45)
.HasColumnType("nvarchar(45)");
b.Property<bool>("IsDeleted")
.HasColumnType("bit");
b.Property<bool>("IsTestUser")
.HasColumnType("bit");
b.Property<string>("LastName")
.IsRequired()
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<string>("Password")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("PasswordHash")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<string>("PasswordSalt")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<int>("RoleId")
.HasColumnType("int");
b.Property<DateTime?>("UpdateTime")
.HasColumnType("datetime2");
b.Property<int?>("UpdateUserId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("RoleId");
b.HasIndex(new[] { "Email" }, "IX_Email");
b.HasIndex(new[] { "IsDeleted", "Guid" }, "IX_IsDeleted_Guid")
.HasFilter("[IsDeleted] = 0");
b.ToTable("Users");
});
modelBuilder.Entity("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.PermissionSystemModule", b =>
{
b.HasOne("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.PermissionModule", "PermissionModule")
.WithMany()
.HasForeignKey("PermissionModuleId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.PermissionSystem", "PermissionSystem")
.WithMany()
.HasForeignKey("PermissionSystemId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("PermissionModule");
b.Navigation("PermissionSystem");
});
modelBuilder.Entity("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.PermissionSystemModuleOperation", b =>
{
b.HasOne("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.PermissionOperation", "PermissionOperation")
.WithMany()
.HasForeignKey("PermissionOperationId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.PermissionSystemModule", "PermissionSystemModule")
.WithMany()
.HasForeignKey("PermissionSystemModuleId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("PermissionOperation");
b.Navigation("PermissionSystemModule");
});
modelBuilder.Entity("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.RolePermissionSystemModuleOperation", b =>
{
b.HasOne("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.PermissionSystemModuleOperation", "PermissionSystemModuleOperation")
.WithMany()
.HasForeignKey("PermissionSystemModuleOperationId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.Role", "Role")
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("PermissionSystemModuleOperation");
b.Navigation("Role");
});
modelBuilder.Entity("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.User", b =>
{
b.HasOne("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.Role", "Role")
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Role");
});
#pragma warning restore 612, 618
}
}
}

View File

@@ -0,0 +1,283 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace MainProject.Migrations
{
/// <inheritdoc />
public partial class AddingPermissionsTables : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "PermissionModules",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
Name = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: false),
Enabled = table.Column<bool>(type: "bit", nullable: false),
Guid = table.Column<string>(type: "nvarchar(45)", maxLength: 45, nullable: false),
IsDeleted = table.Column<bool>(type: "bit", nullable: false),
CreationTime = table.Column<DateTime>(type: "datetime2", nullable: false),
CreationUserId = table.Column<int>(type: "int", nullable: true),
UpdateTime = table.Column<DateTime>(type: "datetime2", nullable: true),
UpdateUserId = table.Column<int>(type: "int", nullable: true),
DeletionTime = table.Column<DateTime>(type: "datetime2", nullable: true),
DeletionUserId = table.Column<int>(type: "int", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_PermissionModules", x => x.Id);
});
migrationBuilder.CreateTable(
name: "PermissionOperations",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
Name = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: false),
Guid = table.Column<string>(type: "nvarchar(45)", maxLength: 45, nullable: false),
IsDeleted = table.Column<bool>(type: "bit", nullable: false),
CreationTime = table.Column<DateTime>(type: "datetime2", nullable: false),
CreationUserId = table.Column<int>(type: "int", nullable: true),
UpdateTime = table.Column<DateTime>(type: "datetime2", nullable: true),
UpdateUserId = table.Column<int>(type: "int", nullable: true),
DeletionTime = table.Column<DateTime>(type: "datetime2", nullable: true),
DeletionUserId = table.Column<int>(type: "int", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_PermissionOperations", x => x.Id);
});
migrationBuilder.CreateTable(
name: "PermissionSystems",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
Name = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: false),
Enabled = table.Column<bool>(type: "bit", nullable: false),
Guid = table.Column<string>(type: "nvarchar(45)", maxLength: 45, nullable: false),
IsDeleted = table.Column<bool>(type: "bit", nullable: false),
CreationTime = table.Column<DateTime>(type: "datetime2", nullable: false),
CreationUserId = table.Column<int>(type: "int", nullable: true),
UpdateTime = table.Column<DateTime>(type: "datetime2", nullable: true),
UpdateUserId = table.Column<int>(type: "int", nullable: true),
DeletionTime = table.Column<DateTime>(type: "datetime2", nullable: true),
DeletionUserId = table.Column<int>(type: "int", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_PermissionSystems", x => x.Id);
});
migrationBuilder.CreateTable(
name: "PermissionSystemModules",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
PermissionSystemId = table.Column<int>(type: "int", nullable: false),
PermissionModuleId = table.Column<int>(type: "int", nullable: false),
Enabled = table.Column<bool>(type: "bit", nullable: false),
Guid = table.Column<string>(type: "nvarchar(45)", maxLength: 45, nullable: false),
IsDeleted = table.Column<bool>(type: "bit", nullable: false),
CreationTime = table.Column<DateTime>(type: "datetime2", nullable: false),
CreationUserId = table.Column<int>(type: "int", nullable: true),
UpdateTime = table.Column<DateTime>(type: "datetime2", nullable: true),
UpdateUserId = table.Column<int>(type: "int", nullable: true),
DeletionTime = table.Column<DateTime>(type: "datetime2", nullable: true),
DeletionUserId = table.Column<int>(type: "int", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_PermissionSystemModules", x => x.Id);
table.ForeignKey(
name: "FK_PermissionSystemModules_PermissionModules_PermissionModuleId",
column: x => x.PermissionModuleId,
principalTable: "PermissionModules",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_PermissionSystemModules_PermissionSystems_PermissionSystemId",
column: x => x.PermissionSystemId,
principalTable: "PermissionSystems",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "PermissionSystemModuleOperations",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
PermissionSystemModuleId = table.Column<int>(type: "int", nullable: false),
PermissionOperationId = table.Column<int>(type: "int", nullable: false),
Enabled = table.Column<bool>(type: "bit", nullable: false),
Guid = table.Column<string>(type: "nvarchar(45)", maxLength: 45, nullable: false),
IsDeleted = table.Column<bool>(type: "bit", nullable: false),
CreationTime = table.Column<DateTime>(type: "datetime2", nullable: false),
CreationUserId = table.Column<int>(type: "int", nullable: true),
UpdateTime = table.Column<DateTime>(type: "datetime2", nullable: true),
UpdateUserId = table.Column<int>(type: "int", nullable: true),
DeletionTime = table.Column<DateTime>(type: "datetime2", nullable: true),
DeletionUserId = table.Column<int>(type: "int", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_PermissionSystemModuleOperations", x => x.Id);
table.ForeignKey(
name: "FK_PermissionSystemModuleOperations_PermissionOperations_PermissionOperationId",
column: x => x.PermissionOperationId,
principalTable: "PermissionOperations",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_PermissionSystemModuleOperations_PermissionSystemModules_PermissionSystemModuleId",
column: x => x.PermissionSystemModuleId,
principalTable: "PermissionSystemModules",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "RolePermissionSystemModuleOperations",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
RoleId = table.Column<int>(type: "int", nullable: false),
PermissionSystemModuleOperationId = table.Column<int>(type: "int", nullable: false),
Active = table.Column<bool>(type: "bit", nullable: false),
Guid = table.Column<string>(type: "nvarchar(45)", maxLength: 45, nullable: false),
IsDeleted = table.Column<bool>(type: "bit", nullable: false),
CreationTime = table.Column<DateTime>(type: "datetime2", nullable: false),
CreationUserId = table.Column<int>(type: "int", nullable: true),
UpdateTime = table.Column<DateTime>(type: "datetime2", nullable: true),
UpdateUserId = table.Column<int>(type: "int", nullable: true),
DeletionTime = table.Column<DateTime>(type: "datetime2", nullable: true),
DeletionUserId = table.Column<int>(type: "int", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_RolePermissionSystemModuleOperations", x => x.Id);
table.ForeignKey(
name: "FK_RolePermissionSystemModuleOperations_PermissionSystemModuleOperations_PermissionSystemModuleOperationId",
column: x => x.PermissionSystemModuleOperationId,
principalTable: "PermissionSystemModuleOperations",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_RolePermissionSystemModuleOperations_Roles_RoleId",
column: x => x.RoleId,
principalTable: "Roles",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateIndex(
name: "IX_Enabled",
table: "PermissionModules",
column: "Enabled",
filter: "[Enabled] = 1");
migrationBuilder.CreateIndex(
name: "IX_IsDeleted",
table: "PermissionModules",
column: "IsDeleted",
filter: "[IsDeleted] = 0");
migrationBuilder.CreateIndex(
name: "IX_IsDeleted_Name_Enabled",
table: "PermissionModules",
columns: new[] { "IsDeleted", "Name", "Enabled" },
filter: "[IsDeleted] = 0");
migrationBuilder.CreateIndex(
name: "IX_IsDeleted_Name",
table: "PermissionOperations",
columns: new[] { "IsDeleted", "Name" });
migrationBuilder.CreateIndex(
name: "IX_IsDeleted_Enabled_Guid",
table: "PermissionSystemModuleOperations",
columns: new[] { "IsDeleted", "Enabled", "Guid" });
migrationBuilder.CreateIndex(
name: "IX_PermissionSystemModuleOperations_PermissionOperationId",
table: "PermissionSystemModuleOperations",
column: "PermissionOperationId");
migrationBuilder.CreateIndex(
name: "IX_PermissionSystemModuleOperations_PermissionSystemModuleId",
table: "PermissionSystemModuleOperations",
column: "PermissionSystemModuleId");
migrationBuilder.CreateIndex(
name: "IX_PermissionSystemModules_PermissionModuleId",
table: "PermissionSystemModules",
column: "PermissionModuleId");
migrationBuilder.CreateIndex(
name: "IX_PermissionSystemModules_PermissionSystemId",
table: "PermissionSystemModules",
column: "PermissionSystemId");
migrationBuilder.CreateIndex(
name: "IX_Enabled",
table: "PermissionSystems",
column: "Enabled",
filter: "[Enabled] = 1");
migrationBuilder.CreateIndex(
name: "IX_IsDeleted",
table: "PermissionSystems",
column: "IsDeleted",
filter: "[IsDeleted] = 0");
migrationBuilder.CreateIndex(
name: "IX_IsDeleted_Name_Enabled",
table: "PermissionSystems",
columns: new[] { "IsDeleted", "Name", "Enabled" },
filter: "[IsDeleted] = 0");
migrationBuilder.CreateIndex(
name: "IX_RolePermissionSystemModuleOperations_PermissionSystemModuleOperationId",
table: "RolePermissionSystemModuleOperations",
column: "PermissionSystemModuleOperationId");
migrationBuilder.CreateIndex(
name: "IX_RolePermissionSystemModuleOperations_RoleId",
table: "RolePermissionSystemModuleOperations",
column: "RoleId");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "RolePermissionSystemModuleOperations");
migrationBuilder.DropTable(
name: "PermissionSystemModuleOperations");
migrationBuilder.DropTable(
name: "PermissionOperations");
migrationBuilder.DropTable(
name: "PermissionSystemModules");
migrationBuilder.DropTable(
name: "PermissionModules");
migrationBuilder.DropTable(
name: "PermissionSystems");
}
}
}

View File

@@ -0,0 +1,542 @@
// <auto-generated />
using System;
using BasicDotnetTemplate.MainProject.Core.Database;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
#nullable disable
namespace MainProject.Migrations
{
[DbContext(typeof(SqlServerContext))]
[Migration("20250617183212_AlterTableUsersForPasswordEncryption")]
partial class AlterTableUsersForPasswordEncryption
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "9.0.5")
.HasAnnotation("Relational:MaxIdentifierLength", 128);
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
modelBuilder.Entity("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.PermissionModule", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime2");
b.Property<int?>("CreationUserId")
.HasColumnType("int");
b.Property<DateTime?>("DeletionTime")
.HasColumnType("datetime2");
b.Property<int?>("DeletionUserId")
.HasColumnType("int");
b.Property<bool>("Enabled")
.HasColumnType("bit");
b.Property<string>("Guid")
.IsRequired()
.HasMaxLength(45)
.HasColumnType("nvarchar(45)");
b.Property<bool>("IsDeleted")
.HasColumnType("bit");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("nvarchar(100)");
b.Property<DateTime?>("UpdateTime")
.HasColumnType("datetime2");
b.Property<int?>("UpdateUserId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex(new[] { "Enabled" }, "IX_Enabled")
.HasFilter("[Enabled] = 1");
b.HasIndex(new[] { "IsDeleted" }, "IX_IsDeleted")
.HasFilter("[IsDeleted] = 0");
b.HasIndex(new[] { "IsDeleted", "Name", "Enabled" }, "IX_IsDeleted_Name_Enabled")
.HasFilter("[IsDeleted] = 0");
b.ToTable("PermissionModules");
});
modelBuilder.Entity("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.PermissionOperation", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime2");
b.Property<int?>("CreationUserId")
.HasColumnType("int");
b.Property<DateTime?>("DeletionTime")
.HasColumnType("datetime2");
b.Property<int?>("DeletionUserId")
.HasColumnType("int");
b.Property<string>("Guid")
.IsRequired()
.HasMaxLength(45)
.HasColumnType("nvarchar(45)");
b.Property<bool>("IsDeleted")
.HasColumnType("bit");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("nvarchar(100)");
b.Property<DateTime?>("UpdateTime")
.HasColumnType("datetime2");
b.Property<int?>("UpdateUserId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex(new[] { "IsDeleted", "Name" }, "IX_IsDeleted_Name");
b.ToTable("PermissionOperations");
});
modelBuilder.Entity("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.PermissionSystem", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime2");
b.Property<int?>("CreationUserId")
.HasColumnType("int");
b.Property<DateTime?>("DeletionTime")
.HasColumnType("datetime2");
b.Property<int?>("DeletionUserId")
.HasColumnType("int");
b.Property<bool>("Enabled")
.HasColumnType("bit");
b.Property<string>("Guid")
.IsRequired()
.HasMaxLength(45)
.HasColumnType("nvarchar(45)");
b.Property<bool>("IsDeleted")
.HasColumnType("bit");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("nvarchar(100)");
b.Property<DateTime?>("UpdateTime")
.HasColumnType("datetime2");
b.Property<int?>("UpdateUserId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex(new[] { "Enabled" }, "IX_Enabled")
.HasFilter("[Enabled] = 1");
b.HasIndex(new[] { "IsDeleted" }, "IX_IsDeleted")
.HasFilter("[IsDeleted] = 0");
b.HasIndex(new[] { "IsDeleted", "Name", "Enabled" }, "IX_IsDeleted_Name_Enabled")
.HasFilter("[IsDeleted] = 0");
b.ToTable("PermissionSystems");
});
modelBuilder.Entity("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.PermissionSystemModule", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime2");
b.Property<int?>("CreationUserId")
.HasColumnType("int");
b.Property<DateTime?>("DeletionTime")
.HasColumnType("datetime2");
b.Property<int?>("DeletionUserId")
.HasColumnType("int");
b.Property<bool>("Enabled")
.HasColumnType("bit");
b.Property<string>("Guid")
.IsRequired()
.HasMaxLength(45)
.HasColumnType("nvarchar(45)");
b.Property<bool>("IsDeleted")
.HasColumnType("bit");
b.Property<int>("PermissionModuleId")
.HasColumnType("int");
b.Property<int>("PermissionSystemId")
.HasColumnType("int");
b.Property<DateTime?>("UpdateTime")
.HasColumnType("datetime2");
b.Property<int?>("UpdateUserId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("PermissionModuleId");
b.HasIndex("PermissionSystemId");
b.ToTable("PermissionSystemModules");
});
modelBuilder.Entity("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.PermissionSystemModuleOperation", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime2");
b.Property<int?>("CreationUserId")
.HasColumnType("int");
b.Property<DateTime?>("DeletionTime")
.HasColumnType("datetime2");
b.Property<int?>("DeletionUserId")
.HasColumnType("int");
b.Property<bool>("Enabled")
.HasColumnType("bit");
b.Property<string>("Guid")
.IsRequired()
.HasMaxLength(45)
.HasColumnType("nvarchar(45)");
b.Property<bool>("IsDeleted")
.HasColumnType("bit");
b.Property<int>("PermissionOperationId")
.HasColumnType("int");
b.Property<int>("PermissionSystemModuleId")
.HasColumnType("int");
b.Property<DateTime?>("UpdateTime")
.HasColumnType("datetime2");
b.Property<int?>("UpdateUserId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("PermissionOperationId");
b.HasIndex("PermissionSystemModuleId");
b.HasIndex(new[] { "IsDeleted", "Enabled", "Guid" }, "IX_IsDeleted_Enabled_Guid");
b.ToTable("PermissionSystemModuleOperations");
});
modelBuilder.Entity("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.Role", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime2");
b.Property<int?>("CreationUserId")
.HasColumnType("int");
b.Property<DateTime?>("DeletionTime")
.HasColumnType("datetime2");
b.Property<int?>("DeletionUserId")
.HasColumnType("int");
b.Property<string>("Guid")
.IsRequired()
.HasMaxLength(45)
.HasColumnType("nvarchar(45)");
b.Property<bool>("IsDeleted")
.HasColumnType("bit");
b.Property<bool>("IsNotEditable")
.HasColumnType("bit");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("nvarchar(100)");
b.Property<DateTime?>("UpdateTime")
.HasColumnType("datetime2");
b.Property<int?>("UpdateUserId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex(new[] { "IsDeleted", "Guid" }, "IX_IsDeleted_Guid")
.HasFilter("[IsDeleted] = 0");
b.ToTable("Roles");
});
modelBuilder.Entity("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.RolePermissionSystemModuleOperation", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<bool>("Active")
.HasColumnType("bit");
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime2");
b.Property<int?>("CreationUserId")
.HasColumnType("int");
b.Property<DateTime?>("DeletionTime")
.HasColumnType("datetime2");
b.Property<int?>("DeletionUserId")
.HasColumnType("int");
b.Property<string>("Guid")
.IsRequired()
.HasMaxLength(45)
.HasColumnType("nvarchar(45)");
b.Property<bool>("IsDeleted")
.HasColumnType("bit");
b.Property<int>("PermissionSystemModuleOperationId")
.HasColumnType("int");
b.Property<int>("RoleId")
.HasColumnType("int");
b.Property<DateTime?>("UpdateTime")
.HasColumnType("datetime2");
b.Property<int?>("UpdateUserId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("PermissionSystemModuleOperationId");
b.HasIndex("RoleId");
b.ToTable("RolePermissionSystemModuleOperations");
});
modelBuilder.Entity("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.User", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime2");
b.Property<int?>("CreationUserId")
.HasColumnType("int");
b.Property<DateTime?>("DeletionTime")
.HasColumnType("datetime2");
b.Property<int?>("DeletionUserId")
.HasColumnType("int");
b.Property<string>("Email")
.IsRequired()
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<string>("FirstName")
.IsRequired()
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<string>("Guid")
.IsRequired()
.HasMaxLength(45)
.HasColumnType("nvarchar(45)");
b.Property<bool>("IsDeleted")
.HasColumnType("bit");
b.Property<bool>("IsTestUser")
.HasColumnType("bit");
b.Property<string>("LastName")
.IsRequired()
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<string>("Password")
.HasColumnType("nvarchar(max)");
b.Property<int>("PasswordIterations")
.HasColumnType("int");
b.Property<string>("PasswordPepper")
.HasColumnType("nvarchar(max)");
b.Property<string>("PasswordSalt")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<int?>("RoleId")
.HasColumnType("int");
b.Property<DateTime?>("UpdateTime")
.HasColumnType("datetime2");
b.Property<int?>("UpdateUserId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("RoleId");
b.HasIndex(new[] { "Email" }, "IX_Email");
b.HasIndex(new[] { "IsDeleted", "Guid" }, "IX_IsDeleted_Guid")
.HasFilter("[IsDeleted] = 0");
b.ToTable("Users");
});
modelBuilder.Entity("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.PermissionSystemModule", b =>
{
b.HasOne("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.PermissionModule", "PermissionModule")
.WithMany()
.HasForeignKey("PermissionModuleId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.PermissionSystem", "PermissionSystem")
.WithMany()
.HasForeignKey("PermissionSystemId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("PermissionModule");
b.Navigation("PermissionSystem");
});
modelBuilder.Entity("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.PermissionSystemModuleOperation", b =>
{
b.HasOne("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.PermissionOperation", "PermissionOperation")
.WithMany()
.HasForeignKey("PermissionOperationId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.PermissionSystemModule", "PermissionSystemModule")
.WithMany()
.HasForeignKey("PermissionSystemModuleId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("PermissionOperation");
b.Navigation("PermissionSystemModule");
});
modelBuilder.Entity("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.RolePermissionSystemModuleOperation", b =>
{
b.HasOne("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.PermissionSystemModuleOperation", "PermissionSystemModuleOperation")
.WithMany()
.HasForeignKey("PermissionSystemModuleOperationId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.Role", "Role")
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("PermissionSystemModuleOperation");
b.Navigation("Role");
});
modelBuilder.Entity("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.User", b =>
{
b.HasOne("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.Role", "Role")
.WithMany()
.HasForeignKey("RoleId");
b.Navigation("Role");
});
#pragma warning restore 612, 618
}
}
}

View File

@@ -0,0 +1,109 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace MainProject.Migrations
{
/// <inheritdoc />
public partial class AlterTableUsersForPasswordEncryption : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "FK_Users_Roles_RoleId",
table: "Users");
migrationBuilder.DropColumn(
name: "PasswordHash",
table: "Users");
migrationBuilder.AlterColumn<int>(
name: "RoleId",
table: "Users",
type: "int",
nullable: true,
oldClrType: typeof(int),
oldType: "int");
migrationBuilder.AlterColumn<string>(
name: "Password",
table: "Users",
type: "nvarchar(max)",
nullable: true,
oldClrType: typeof(string),
oldType: "nvarchar(max)");
migrationBuilder.AddColumn<int>(
name: "PasswordIterations",
table: "Users",
type: "int",
nullable: false,
defaultValue: 0);
migrationBuilder.AddColumn<string>(
name: "PasswordPepper",
table: "Users",
type: "nvarchar(max)",
nullable: true);
migrationBuilder.AddForeignKey(
name: "FK_Users_Roles_RoleId",
table: "Users",
column: "RoleId",
principalTable: "Roles",
principalColumn: "Id");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "FK_Users_Roles_RoleId",
table: "Users");
migrationBuilder.DropColumn(
name: "PasswordIterations",
table: "Users");
migrationBuilder.DropColumn(
name: "PasswordPepper",
table: "Users");
migrationBuilder.AlterColumn<int>(
name: "RoleId",
table: "Users",
type: "int",
nullable: false,
defaultValue: 0,
oldClrType: typeof(int),
oldType: "int",
oldNullable: true);
migrationBuilder.AlterColumn<string>(
name: "Password",
table: "Users",
type: "nvarchar(max)",
nullable: false,
defaultValue: "",
oldClrType: typeof(string),
oldType: "nvarchar(max)",
oldNullable: true);
migrationBuilder.AddColumn<string>(
name: "PasswordHash",
table: "Users",
type: "nvarchar(max)",
nullable: false,
defaultValue: "");
migrationBuilder.AddForeignKey(
name: "FK_Users_Roles_RoleId",
table: "Users",
column: "RoleId",
principalTable: "Roles",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
}
}
}

View File

@@ -0,0 +1,539 @@
// <auto-generated />
using System;
using BasicDotnetTemplate.MainProject.Core.Database;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
#nullable disable
namespace MainProject.Migrations
{
[DbContext(typeof(SqlServerContext))]
partial class SqlServerContextModelSnapshot : ModelSnapshot
{
protected override void BuildModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "9.0.5")
.HasAnnotation("Relational:MaxIdentifierLength", 128);
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
modelBuilder.Entity("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.PermissionModule", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime2");
b.Property<int?>("CreationUserId")
.HasColumnType("int");
b.Property<DateTime?>("DeletionTime")
.HasColumnType("datetime2");
b.Property<int?>("DeletionUserId")
.HasColumnType("int");
b.Property<bool>("Enabled")
.HasColumnType("bit");
b.Property<string>("Guid")
.IsRequired()
.HasMaxLength(45)
.HasColumnType("nvarchar(45)");
b.Property<bool>("IsDeleted")
.HasColumnType("bit");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("nvarchar(100)");
b.Property<DateTime?>("UpdateTime")
.HasColumnType("datetime2");
b.Property<int?>("UpdateUserId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex(new[] { "Enabled" }, "IX_Enabled")
.HasFilter("[Enabled] = 1");
b.HasIndex(new[] { "IsDeleted" }, "IX_IsDeleted")
.HasFilter("[IsDeleted] = 0");
b.HasIndex(new[] { "IsDeleted", "Name", "Enabled" }, "IX_IsDeleted_Name_Enabled")
.HasFilter("[IsDeleted] = 0");
b.ToTable("PermissionModules");
});
modelBuilder.Entity("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.PermissionOperation", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime2");
b.Property<int?>("CreationUserId")
.HasColumnType("int");
b.Property<DateTime?>("DeletionTime")
.HasColumnType("datetime2");
b.Property<int?>("DeletionUserId")
.HasColumnType("int");
b.Property<string>("Guid")
.IsRequired()
.HasMaxLength(45)
.HasColumnType("nvarchar(45)");
b.Property<bool>("IsDeleted")
.HasColumnType("bit");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("nvarchar(100)");
b.Property<DateTime?>("UpdateTime")
.HasColumnType("datetime2");
b.Property<int?>("UpdateUserId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex(new[] { "IsDeleted", "Name" }, "IX_IsDeleted_Name");
b.ToTable("PermissionOperations");
});
modelBuilder.Entity("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.PermissionSystem", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime2");
b.Property<int?>("CreationUserId")
.HasColumnType("int");
b.Property<DateTime?>("DeletionTime")
.HasColumnType("datetime2");
b.Property<int?>("DeletionUserId")
.HasColumnType("int");
b.Property<bool>("Enabled")
.HasColumnType("bit");
b.Property<string>("Guid")
.IsRequired()
.HasMaxLength(45)
.HasColumnType("nvarchar(45)");
b.Property<bool>("IsDeleted")
.HasColumnType("bit");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("nvarchar(100)");
b.Property<DateTime?>("UpdateTime")
.HasColumnType("datetime2");
b.Property<int?>("UpdateUserId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex(new[] { "Enabled" }, "IX_Enabled")
.HasFilter("[Enabled] = 1");
b.HasIndex(new[] { "IsDeleted" }, "IX_IsDeleted")
.HasFilter("[IsDeleted] = 0");
b.HasIndex(new[] { "IsDeleted", "Name", "Enabled" }, "IX_IsDeleted_Name_Enabled")
.HasFilter("[IsDeleted] = 0");
b.ToTable("PermissionSystems");
});
modelBuilder.Entity("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.PermissionSystemModule", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime2");
b.Property<int?>("CreationUserId")
.HasColumnType("int");
b.Property<DateTime?>("DeletionTime")
.HasColumnType("datetime2");
b.Property<int?>("DeletionUserId")
.HasColumnType("int");
b.Property<bool>("Enabled")
.HasColumnType("bit");
b.Property<string>("Guid")
.IsRequired()
.HasMaxLength(45)
.HasColumnType("nvarchar(45)");
b.Property<bool>("IsDeleted")
.HasColumnType("bit");
b.Property<int>("PermissionModuleId")
.HasColumnType("int");
b.Property<int>("PermissionSystemId")
.HasColumnType("int");
b.Property<DateTime?>("UpdateTime")
.HasColumnType("datetime2");
b.Property<int?>("UpdateUserId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("PermissionModuleId");
b.HasIndex("PermissionSystemId");
b.ToTable("PermissionSystemModules");
});
modelBuilder.Entity("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.PermissionSystemModuleOperation", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime2");
b.Property<int?>("CreationUserId")
.HasColumnType("int");
b.Property<DateTime?>("DeletionTime")
.HasColumnType("datetime2");
b.Property<int?>("DeletionUserId")
.HasColumnType("int");
b.Property<bool>("Enabled")
.HasColumnType("bit");
b.Property<string>("Guid")
.IsRequired()
.HasMaxLength(45)
.HasColumnType("nvarchar(45)");
b.Property<bool>("IsDeleted")
.HasColumnType("bit");
b.Property<int>("PermissionOperationId")
.HasColumnType("int");
b.Property<int>("PermissionSystemModuleId")
.HasColumnType("int");
b.Property<DateTime?>("UpdateTime")
.HasColumnType("datetime2");
b.Property<int?>("UpdateUserId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("PermissionOperationId");
b.HasIndex("PermissionSystemModuleId");
b.HasIndex(new[] { "IsDeleted", "Enabled", "Guid" }, "IX_IsDeleted_Enabled_Guid");
b.ToTable("PermissionSystemModuleOperations");
});
modelBuilder.Entity("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.Role", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime2");
b.Property<int?>("CreationUserId")
.HasColumnType("int");
b.Property<DateTime?>("DeletionTime")
.HasColumnType("datetime2");
b.Property<int?>("DeletionUserId")
.HasColumnType("int");
b.Property<string>("Guid")
.IsRequired()
.HasMaxLength(45)
.HasColumnType("nvarchar(45)");
b.Property<bool>("IsDeleted")
.HasColumnType("bit");
b.Property<bool>("IsNotEditable")
.HasColumnType("bit");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("nvarchar(100)");
b.Property<DateTime?>("UpdateTime")
.HasColumnType("datetime2");
b.Property<int?>("UpdateUserId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex(new[] { "IsDeleted", "Guid" }, "IX_IsDeleted_Guid")
.HasFilter("[IsDeleted] = 0");
b.ToTable("Roles");
});
modelBuilder.Entity("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.RolePermissionSystemModuleOperation", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<bool>("Active")
.HasColumnType("bit");
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime2");
b.Property<int?>("CreationUserId")
.HasColumnType("int");
b.Property<DateTime?>("DeletionTime")
.HasColumnType("datetime2");
b.Property<int?>("DeletionUserId")
.HasColumnType("int");
b.Property<string>("Guid")
.IsRequired()
.HasMaxLength(45)
.HasColumnType("nvarchar(45)");
b.Property<bool>("IsDeleted")
.HasColumnType("bit");
b.Property<int>("PermissionSystemModuleOperationId")
.HasColumnType("int");
b.Property<int>("RoleId")
.HasColumnType("int");
b.Property<DateTime?>("UpdateTime")
.HasColumnType("datetime2");
b.Property<int?>("UpdateUserId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("PermissionSystemModuleOperationId");
b.HasIndex("RoleId");
b.ToTable("RolePermissionSystemModuleOperations");
});
modelBuilder.Entity("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.User", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime2");
b.Property<int?>("CreationUserId")
.HasColumnType("int");
b.Property<DateTime?>("DeletionTime")
.HasColumnType("datetime2");
b.Property<int?>("DeletionUserId")
.HasColumnType("int");
b.Property<string>("Email")
.IsRequired()
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<string>("FirstName")
.IsRequired()
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<string>("Guid")
.IsRequired()
.HasMaxLength(45)
.HasColumnType("nvarchar(45)");
b.Property<bool>("IsDeleted")
.HasColumnType("bit");
b.Property<bool>("IsTestUser")
.HasColumnType("bit");
b.Property<string>("LastName")
.IsRequired()
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<string>("Password")
.HasColumnType("nvarchar(max)");
b.Property<int>("PasswordIterations")
.HasColumnType("int");
b.Property<string>("PasswordPepper")
.HasColumnType("nvarchar(max)");
b.Property<string>("PasswordSalt")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<int?>("RoleId")
.HasColumnType("int");
b.Property<DateTime?>("UpdateTime")
.HasColumnType("datetime2");
b.Property<int?>("UpdateUserId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("RoleId");
b.HasIndex(new[] { "Email" }, "IX_Email");
b.HasIndex(new[] { "IsDeleted", "Guid" }, "IX_IsDeleted_Guid")
.HasFilter("[IsDeleted] = 0");
b.ToTable("Users");
});
modelBuilder.Entity("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.PermissionSystemModule", b =>
{
b.HasOne("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.PermissionModule", "PermissionModule")
.WithMany()
.HasForeignKey("PermissionModuleId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.PermissionSystem", "PermissionSystem")
.WithMany()
.HasForeignKey("PermissionSystemId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("PermissionModule");
b.Navigation("PermissionSystem");
});
modelBuilder.Entity("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.PermissionSystemModuleOperation", b =>
{
b.HasOne("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.PermissionOperation", "PermissionOperation")
.WithMany()
.HasForeignKey("PermissionOperationId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.PermissionSystemModule", "PermissionSystemModule")
.WithMany()
.HasForeignKey("PermissionSystemModuleId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("PermissionOperation");
b.Navigation("PermissionSystemModule");
});
modelBuilder.Entity("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.RolePermissionSystemModuleOperation", b =>
{
b.HasOne("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.PermissionSystemModuleOperation", "PermissionSystemModuleOperation")
.WithMany()
.HasForeignKey("PermissionSystemModuleOperationId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.Role", "Role")
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("PermissionSystemModuleOperation");
b.Navigation("Role");
});
modelBuilder.Entity("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.User", b =>
{
b.HasOne("BasicDotnetTemplate.MainProject.Models.Database.SqlServer.Role", "Role")
.WithMany()
.HasForeignKey("RoleId");
b.Navigation("Role");
});
#pragma warning restore 612, 618
}
}
}

View File

@@ -0,0 +1,9 @@
using System;
namespace BasicDotnetTemplate.MainProject.Models.Api.Base;
public class ValidationError
{
public string? Message { get; set; }
public Dictionary<string, List<string>>? Errors { get; set; }
}

View File

@@ -0,0 +1,11 @@
using System;
namespace BasicDotnetTemplate.MainProject.Models.Api.Common.Exceptions;
public class CreateException : Exception
{
public CreateException(string message, Exception innerException)
: base(message, innerException)
{
}
}

View File

@@ -0,0 +1,11 @@
using System;
namespace BasicDotnetTemplate.MainProject.Models.Api.Common.Exceptions;
public class UpdateException : Exception
{
public UpdateException(string message, Exception innerException)
: base(message, innerException)
{
}
}

View File

@@ -0,0 +1,14 @@
namespace BasicDotnetTemplate.MainProject.Models.Api.Common.Role;
public class RoleDto
{
#nullable enable
public string? Guid { get; set; }
public string? Name { get; set; }
public bool? IsNotEditable { get; set; }
#nullable disable
}

View File

@@ -0,0 +1,19 @@
using DatabaseSqlServer = BasicDotnetTemplate.MainProject.Models.Database.SqlServer;
namespace BasicDotnetTemplate.MainProject.Models.Api.Common.Role;
public class UserRole
{
#nullable enable
public string? Guid { get; set; }
public string? Name { get; set; }
#nullable disable
public UserRole() { }
public UserRole(DatabaseSqlServer.Role role)
{
Guid = role.Guid;
Name = role.Name;
}
}

View File

@@ -0,0 +1,28 @@
using BasicDotnetTemplate.MainProject.Models.Api.Common.Role;
using DatabaseSqlServer = BasicDotnetTemplate.MainProject.Models.Database.SqlServer;
namespace BasicDotnetTemplate.MainProject.Models.Api.Common.User;
public class AuthenticatedUser
{
#nullable enable
public string? Guid { get; set; }
public string? FirstName { get; set; }
public string? LastName { get; set; }
public string? Email { get; set; }
public UserRole? Role { get; set; }
#nullable disable
public AuthenticatedUser(DatabaseSqlServer.User user)
{
Guid = user.Guid;
FirstName = user.FirstName;
LastName = user.LastName;
Email = user.Email;
Role = new UserRole(user.Role!);
}
}

View File

@@ -0,0 +1,18 @@
using BasicDotnetTemplate.MainProject.Models.Api.Common.Role;
using DatabaseSqlServer = BasicDotnetTemplate.MainProject.Models.Database.SqlServer;
namespace BasicDotnetTemplate.MainProject.Models.Api.Common.User;
public class UserDto
{
#nullable enable
public string? Guid { get; set; }
public string? FirstName { get; set; }
public string? LastName { get; set; }
public string? Email { get; set; }
#nullable disable
}

View File

@@ -0,0 +1,15 @@
using System.ComponentModel.DataAnnotations;
namespace BasicDotnetTemplate.MainProject.Models.Api.Data.Auth;
public class AuthenticateRequestData
{
[Required(ErrorMessage = "Email is required")]
public required string Email { get; set; }
[Required(ErrorMessage = "Password is required")]
public required string Password { get; set; }
}

View File

@@ -0,0 +1,11 @@
using System.ComponentModel.DataAnnotations;
namespace BasicDotnetTemplate.MainProject.Models.Api.Data.Role;
public class CreateRoleRequestData
{
[Required(ErrorMessage = "Name is required")]
public required string Name { get; set; }
public required bool IsNotEditable { get; set; }
}

View File

@@ -0,0 +1,20 @@
using System.ComponentModel.DataAnnotations;
namespace BasicDotnetTemplate.MainProject.Models.Api.Data.User;
public class CreateUserRequestData : UpdateUserRequestData
{
[Required(ErrorMessage = "Email is required")]
[StringLength(200, ErrorMessage = "Email's maxLength: 200")]
public required string Email { get; set; }
[Required(ErrorMessage = "Password is required")]
public required string Password { get; set; }
public string? RoleGuid { get; set; }
}

View File

@@ -0,0 +1,19 @@
using System.ComponentModel.DataAnnotations;
namespace BasicDotnetTemplate.MainProject.Models.Api.Data.User;
public class UpdateUserRequestData
{
[Required(ErrorMessage = "FirstName is required")]
[StringLength(200, ErrorMessage = "FirstName's maxLength: 200")]
public required string FirstName { get; set; }
[Required(ErrorMessage = "LastName is required")]
[StringLength(200, ErrorMessage = "LastName's maxLength: 200")]
public required string LastName { get; set; }
}

View File

@@ -0,0 +1,14 @@
using System.ComponentModel.DataAnnotations;
using BasicDotnetTemplate.MainProject.Models.Api.Data.Auth;
namespace BasicDotnetTemplate.MainProject.Models.Api.Request.Auth;
public class AuthenticateRequest
{
[Required(ErrorMessage = "Data is required")]
public required AuthenticateRequestData Data { get; set; }
}

View File

@@ -0,0 +1,10 @@
using System.ComponentModel.DataAnnotations;
using BasicDotnetTemplate.MainProject.Models.Api.Data.Role;
namespace BasicDotnetTemplate.MainProject.Models.Api.Request.Role;
public class CreateRoleRequest
{
[Required(ErrorMessage = "Data is required")]
public required CreateRoleRequestData? Data { get; set; }
}

View File

@@ -0,0 +1,14 @@
using System.ComponentModel.DataAnnotations;
using BasicDotnetTemplate.MainProject.Models.Api.Data.User;
namespace BasicDotnetTemplate.MainProject.Models.Api.Request.User;
public class CreateUserRequest
{
[Required(ErrorMessage = "Data is required")]
public required CreateUserRequestData Data { get; set; }
}

View File

@@ -0,0 +1,14 @@
using System.ComponentModel.DataAnnotations;
using BasicDotnetTemplate.MainProject.Models.Api.Data.User;
namespace BasicDotnetTemplate.MainProject.Models.Api.Request.User;
public class UpdateUserRequest
{
[Required(ErrorMessage = "Data is required")]
public required UpdateUserRequestData Data { get; set; }
}

View File

@@ -0,0 +1,8 @@
using BasicDotnetTemplate.MainProject.Models.Api.Common.User;
namespace BasicDotnetTemplate.MainProject.Models.Api.Response.Auth;
public class AuthenticateResponse : BaseResponse<AuthenticatedUser>
{
public AuthenticateResponse(int status, string? message, AuthenticatedUser? data) : base(status, message, data) { }
}

View File

@@ -0,0 +1,19 @@
namespace BasicDotnetTemplate.MainProject.Models.Api.Response;
public class BaseResponse<T>
{
#nullable enable
public BaseResponse(int status, string? message, T? data)
{
this.Status = status;
this.Message = message;
this.Data = data;
}
#nullable disable
public int Status { get; set; }
#nullable enable
public string? Message { get; set; }
public virtual dynamic? Data { get; set; }
#nullable disable
}

View File

@@ -0,0 +1,8 @@
using BasicDotnetTemplate.MainProject.Models.Api.Common.Role;
namespace BasicDotnetTemplate.MainProject.Models.Api.Response.Role;
public class GetRoleResponse : BaseResponse<RoleDto>
{
public GetRoleResponse(int status, string? message, RoleDto? data) : base(status, message, data) { }
}

View File

@@ -0,0 +1,8 @@
using BasicDotnetTemplate.MainProject.Models.Api.Common.User;
namespace BasicDotnetTemplate.MainProject.Models.Api.Response.User;
public class GetUserResponse : BaseResponse<UserDto>
{
public GetUserResponse(int status, string? message, UserDto? data) : base(status, message, data) { }
}

Some files were not shown because too many files have changed in this diff Show More