├── .gitattributes ├── .gitignore ├── DataAcess ├── ApplicationDbContext.cs ├── Configuration │ ├── ApplicationUserConfiguration.cs │ └── RoleConfiguration.cs ├── DataAcess.csproj ├── Migrations │ ├── 20250223093113_initIdentityTabels.Designer.cs │ ├── 20250223093113_initIdentityTabels.cs │ ├── 20250223094815_addNameToAspNetUserTabel.Designer.cs │ ├── 20250223094815_addNameToAspNetUserTabel.cs │ ├── 20250227215805_seed roles data.Designer.cs │ ├── 20250227215805_seed roles data.cs │ ├── 20250228210101_add imgUrl to user.Designer.cs │ ├── 20250228210101_add imgUrl to user.cs │ ├── 20250228220841_add image tbl and make fk to it In AppUsersTbl.Designer.cs │ ├── 20250228220841_add image tbl and make fk to it In AppUsersTbl.cs │ ├── 20250306171257_FkBtwImgAndUser.Designer.cs │ ├── 20250306171257_FkBtwImgAndUser.cs │ ├── 20250306173147_FkBtwImgAndUserupdateNoCycle.Designer.cs │ ├── 20250306173147_FkBtwImgAndUserupdateNoCycle.cs │ └── ApplicationDbContextModelSnapshot.cs └── Repos │ ├── IRepos │ ├── IImageRepository.cs │ ├── IRepository.cs │ └── IUserRepository.cs │ ├── ImageRepository.cs │ ├── Repository.cs │ └── UserRepository.cs ├── IdentityManager.Services ├── ControllerService │ ├── AuthService.cs │ ├── IControllerService │ │ ├── IAuthService.cs │ │ └── IUserService.cs │ └── UserService.cs └── IdentityManager.Services.csproj ├── IdentityManagerAPI.csproj ├── IdentityManagerAPI.http ├── IdentityManagerAPI.sln ├── IdentityManagerAPI ├── BearerSecuritySchemeTransformer.cs ├── Controllers │ ├── AuthUserController.cs │ └── UserController.cs ├── IdentityManagerAPI.csproj ├── IdentityManagerAPI.http ├── Images │ └── asd..jpg ├── Middlewares │ └── GlobalExceptionHandler.cs ├── Program.cs ├── Properties │ └── launchSettings.json ├── appsettings.Development.json └── appsettings.json ├── Models ├── DTOs │ ├── Auth │ │ ├── LoginRequestDTO.cs │ │ ├── LoginResponseDTO.cs │ │ └── RegisterRequestDTO.cs │ ├── Mapper │ │ └── MappingConfig.cs │ ├── User │ │ └── UserDTO.cs │ └── image │ │ └── ImageUploadRequestDto.cs ├── Domain │ ├── ApplicationUser.cs │ └── Image.cs └── Models.csproj ├── Program.cs ├── Properties └── launchSettings.json ├── README.md ├── appsettings.Development.json └── appsettings.json /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | ## Ignore Visual Studio temporary files, build results, and 3 | ## files generated by popular Visual Studio add-ons. 4 | ## 5 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 6 | 7 | # User-specific files 8 | *.rsuser 9 | *.suo 10 | *.user 11 | *.userosscache 12 | *.sln.docstates 13 | 14 | 15 | 16 | Images/ 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | # User-specific files (MonoDevelop/Xamarin Studio) 29 | *.userprefs 30 | 31 | # Mono auto generated files 32 | mono_crash.* 33 | 34 | # Build results 35 | [Dd]ebug/ 36 | [Dd]ebugPublic/ 37 | [Rr]elease/ 38 | [Rr]eleases/ 39 | x64/ 40 | x86/ 41 | [Ww][Ii][Nn]32/ 42 | [Aa][Rr][Mm]/ 43 | [Aa][Rr][Mm]64/ 44 | bld/ 45 | [Bb]in/ 46 | [Oo]bj/ 47 | [Oo]ut/ 48 | [Ll]og/ 49 | [Ll]ogs/ 50 | 51 | # Visual Studio 2015/2017 cache/options directory 52 | .vs/ 53 | # Uncomment if you have tasks that create the project's static files in wwwroot 54 | #wwwroot/ 55 | 56 | # Visual Studio 2017 auto generated files 57 | Generated\ Files/ 58 | 59 | # MSTest test Results 60 | [Tt]est[Rr]esult*/ 61 | [Bb]uild[Ll]og.* 62 | 63 | # NUnit 64 | *.VisualState.xml 65 | TestResult.xml 66 | nunit-*.xml 67 | 68 | # Build Results of an ATL Project 69 | [Dd]ebugPS/ 70 | [Rr]eleasePS/ 71 | dlldata.c 72 | 73 | 74 | 75 | 76 | 77 | # Benchmark Results 78 | BenchmarkDotNet.Artifacts/ 79 | 80 | # .NET Core 81 | project.lock.json 82 | project.fragment.lock.json 83 | artifacts/ 84 | 85 | # ASP.NET Scaffolding 86 | ScaffoldingReadMe.txt 87 | 88 | # StyleCop 89 | StyleCopReport.xml 90 | 91 | # Files built by Visual Studio 92 | *_i.c 93 | *_p.c 94 | *_h.h 95 | *.ilk 96 | *.meta 97 | *.obj 98 | *.iobj 99 | *.pch 100 | *.pdb 101 | *.ipdb 102 | *.pgc 103 | *.pgd 104 | *.rsp 105 | *.sbr 106 | *.tlb 107 | *.tli 108 | *.tlh 109 | *.tmp 110 | *.tmp_proj 111 | *_wpftmp.csproj 112 | *.log 113 | *.vspscc 114 | *.vssscc 115 | .builds 116 | *.pidb 117 | *.svclog 118 | *.scc 119 | 120 | # Chutzpah Test files 121 | _Chutzpah* 122 | 123 | # Visual C++ cache files 124 | ipch/ 125 | *.aps 126 | *.ncb 127 | *.opendb 128 | *.opensdf 129 | *.sdf 130 | *.cachefile 131 | *.VC.db 132 | *.VC.VC.opendb 133 | 134 | # Visual Studio profiler 135 | *.psess 136 | *.vsp 137 | *.vspx 138 | *.sap 139 | 140 | # Visual Studio Trace Files 141 | *.e2e 142 | 143 | # TFS 2012 Local Workspace 144 | $tf/ 145 | 146 | # Guidance Automation Toolkit 147 | *.gpState 148 | 149 | # ReSharper is a .NET coding add-in 150 | _ReSharper*/ 151 | *.[Rr]e[Ss]harper 152 | *.DotSettings.user 153 | 154 | # TeamCity is a build add-in 155 | _TeamCity* 156 | 157 | # DotCover is a Code Coverage Tool 158 | *.dotCover 159 | 160 | # AxoCover is a Code Coverage Tool 161 | .axoCover/* 162 | !.axoCover/settings.json 163 | 164 | # Coverlet is a free, cross platform Code Coverage Tool 165 | coverage*.json 166 | coverage*.xml 167 | coverage*.info 168 | 169 | # Visual Studio code coverage results 170 | *.coverage 171 | *.coveragexml 172 | 173 | # NCrunch 174 | _NCrunch_* 175 | .*crunch*.local.xml 176 | nCrunchTemp_* 177 | 178 | # MightyMoose 179 | *.mm.* 180 | AutoTest.Net/ 181 | 182 | # Web workbench (sass) 183 | .sass-cache/ 184 | 185 | # Installshield output folder 186 | [Ee]xpress/ 187 | 188 | # DocProject is a documentation generator add-in 189 | DocProject/buildhelp/ 190 | DocProject/Help/*.HxT 191 | DocProject/Help/*.HxC 192 | DocProject/Help/*.hhc 193 | DocProject/Help/*.hhk 194 | DocProject/Help/*.hhp 195 | DocProject/Help/Html2 196 | DocProject/Help/html 197 | 198 | # Click-Once directory 199 | publish/ 200 | 201 | # Publish Web Output 202 | *.[Pp]ublish.xml 203 | *.azurePubxml 204 | # Note: Comment the next line if you want to checkin your web deploy settings, 205 | # but database connection strings (with potential passwords) will be unencrypted 206 | *.pubxml 207 | *.publishproj 208 | 209 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 210 | # checkin your Azure Web App publish settings, but sensitive information contained 211 | # in these scripts will be unencrypted 212 | PublishScripts/ 213 | 214 | # NuGet Packages 215 | *.nupkg 216 | # NuGet Symbol Packages 217 | *.snupkg 218 | # The packages folder can be ignored because of Package Restore 219 | **/[Pp]ackages/* 220 | # except build/, which is used as an MSBuild target. 221 | !**/[Pp]ackages/build/ 222 | # Uncomment if necessary however generally it will be regenerated when needed 223 | #!**/[Pp]ackages/repositories.config 224 | # NuGet v3's project.json files produces more ignorable files 225 | *.nuget.props 226 | *.nuget.targets 227 | 228 | # Microsoft Azure Build Output 229 | csx/ 230 | *.build.csdef 231 | 232 | # Microsoft Azure Emulator 233 | ecf/ 234 | rcf/ 235 | 236 | # Windows Store app package directories and files 237 | AppPackages/ 238 | BundleArtifacts/ 239 | Package.StoreAssociation.xml 240 | _pkginfo.txt 241 | *.appx 242 | *.appxbundle 243 | *.appxupload 244 | 245 | # Visual Studio cache files 246 | # files ending in .cache can be ignored 247 | *.[Cc]ache 248 | # but keep track of directories ending in .cache 249 | !?*.[Cc]ache/ 250 | 251 | # Others 252 | ClientBin/ 253 | ~$* 254 | *~ 255 | *.dbmdl 256 | *.dbproj.schemaview 257 | *.jfm 258 | *.pfx 259 | *.publishsettings 260 | orleans.codegen.cs 261 | 262 | # Including strong name files can present a security risk 263 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 264 | #*.snk 265 | 266 | # Since there are multiple workflows, uncomment next line to ignore bower_components 267 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 268 | #bower_components/ 269 | 270 | # RIA/Silverlight projects 271 | Generated_Code/ 272 | 273 | # Backup & report files from converting an old project file 274 | # to a newer Visual Studio version. Backup files are not needed, 275 | # because we have git ;-) 276 | _UpgradeReport_Files/ 277 | Backup*/ 278 | UpgradeLog*.XML 279 | UpgradeLog*.htm 280 | ServiceFabricBackup/ 281 | *.rptproj.bak 282 | 283 | # SQL Server files 284 | *.mdf 285 | *.ldf 286 | *.ndf 287 | 288 | # Business Intelligence projects 289 | *.rdl.data 290 | *.bim.layout 291 | *.bim_*.settings 292 | *.rptproj.rsuser 293 | *- [Bb]ackup.rdl 294 | *- [Bb]ackup ([0-9]).rdl 295 | *- [Bb]ackup ([0-9][0-9]).rdl 296 | 297 | # Microsoft Fakes 298 | FakesAssemblies/ 299 | 300 | # GhostDoc plugin setting file 301 | *.GhostDoc.xml 302 | 303 | # Node.js Tools for Visual Studio 304 | .ntvs_analysis.dat 305 | node_modules/ 306 | 307 | # Visual Studio 6 build log 308 | *.plg 309 | 310 | # Visual Studio 6 workspace options file 311 | *.opt 312 | 313 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 314 | *.vbw 315 | 316 | # Visual Studio LightSwitch build output 317 | **/*.HTMLClient/GeneratedArtifacts 318 | **/*.DesktopClient/GeneratedArtifacts 319 | **/*.DesktopClient/ModelManifest.xml 320 | **/*.Server/GeneratedArtifacts 321 | **/*.Server/ModelManifest.xml 322 | _Pvt_Extensions 323 | 324 | # Paket dependency manager 325 | .paket/paket.exe 326 | paket-files/ 327 | 328 | # FAKE - F# Make 329 | .fake/ 330 | 331 | # CodeRush personal settings 332 | .cr/personal 333 | 334 | # Python Tools for Visual Studio (PTVS) 335 | __pycache__/ 336 | *.pyc 337 | 338 | # Cake - Uncomment if you are using it 339 | # tools/** 340 | # !tools/packages.config 341 | 342 | # Tabs Studio 343 | *.tss 344 | 345 | # Telerik's JustMock configuration file 346 | *.jmconfig 347 | 348 | # BizTalk build output 349 | *.btp.cs 350 | *.btm.cs 351 | *.odx.cs 352 | *.xsd.cs 353 | 354 | # OpenCover UI analysis results 355 | OpenCover/ 356 | 357 | # Azure Stream Analytics local run output 358 | ASALocalRun/ 359 | 360 | # MSBuild Binary and Structured Log 361 | *.binlog 362 | 363 | # NVidia Nsight GPU debugger configuration file 364 | *.nvuser 365 | 366 | # MFractors (Xamarin productivity tool) working folder 367 | .mfractor/ 368 | 369 | # Local History for Visual Studio 370 | .localhistory/ 371 | 372 | # BeatPulse healthcheck temp database 373 | healthchecksdb 374 | 375 | # Backup folder for Package Reference Convert tool in Visual Studio 2017 376 | MigrationBackup/ 377 | 378 | # Ionide (cross platform F# VS Code tools) working folder 379 | .ionide/ 380 | 381 | # Fody - auto-generated XML schema 382 | FodyWeavers.xsd -------------------------------------------------------------------------------- /DataAcess/ApplicationDbContext.cs: -------------------------------------------------------------------------------- 1 | using DataAcess.Configuration; 2 | using Microsoft.AspNetCore.Identity; 3 | using Microsoft.AspNetCore.Identity.EntityFrameworkCore; 4 | using Microsoft.EntityFrameworkCore; 5 | using Models.Domain; 6 | using System.Reflection.Emit; 7 | 8 | namespace DataAcess 9 | { 10 | public class ApplicationDbContext : IdentityDbContext 11 | { 12 | public ApplicationDbContext(DbContextOptions options) : base(options) 13 | { 14 | 15 | } 16 | public DbSet ApplicationUser { get; set; } 17 | public DbSet Image { get; set; } 18 | 19 | protected override void OnModelCreating(ModelBuilder builder) 20 | { 21 | base.OnModelCreating(builder); 22 | // Apply separate configuration classes 23 | builder.ApplyConfiguration(new ApplicationUserConfiguration()); 24 | builder.ApplyConfiguration(new RoleConfiguration()); 25 | 26 | } 27 | 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /DataAcess/Configuration/ApplicationUserConfiguration.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore.Metadata.Builders; 2 | using Microsoft.EntityFrameworkCore; 3 | using Models.Domain; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | 10 | namespace DataAcess.Configuration 11 | { 12 | public class ApplicationUserConfiguration : IEntityTypeConfiguration 13 | { 14 | public void Configure(EntityTypeBuilder builder) 15 | { 16 | 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /DataAcess/Configuration/RoleConfiguration.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Identity; 2 | using Microsoft.EntityFrameworkCore.Metadata.Builders; 3 | using Microsoft.EntityFrameworkCore; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | 10 | namespace DataAcess.Configuration 11 | { 12 | public class RoleConfiguration : IEntityTypeConfiguration 13 | { 14 | public void Configure(EntityTypeBuilder builder) 15 | { 16 | Dictionary roles = new Dictionary 17 | { 18 | { "43d0590f-2f82-4867-83c4-18f0488f9706", "admin" }, 19 | { "ff715d53-7725-48de-8d74-f064b8b41b45", "user" }, 20 | { "5654533a-52b5-4e1e-b9e5-fd8036ef35ff", "manager" }, 21 | { "2b440d41-47fa-4fe5-ae96-b4ae34d223a1", "guest" } 22 | }; 23 | 24 | foreach (var role in roles) 25 | { 26 | builder.HasData(new IdentityRole 27 | { 28 | Id = role.Key, 29 | Name = role.Value, 30 | NormalizedName = role.Value.ToUpper() 31 | }); 32 | } 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /DataAcess/DataAcess.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net9.0 5 | enable 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | all 22 | runtime; build; native; contentfiles; analyzers; buildtransitive 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /DataAcess/Migrations/20250223093113_initIdentityTabels.Designer.cs: -------------------------------------------------------------------------------- 1 | // 2 | using System; 3 | using DataAcess; 4 | using Microsoft.EntityFrameworkCore; 5 | using Microsoft.EntityFrameworkCore.Infrastructure; 6 | using Microsoft.EntityFrameworkCore.Metadata; 7 | using Microsoft.EntityFrameworkCore.Migrations; 8 | using Microsoft.EntityFrameworkCore.Storage.ValueConversion; 9 | 10 | #nullable disable 11 | 12 | namespace DataAcess.Migrations 13 | { 14 | [DbContext(typeof(ApplicationDbContext))] 15 | [Migration("20250223093113_initIdentityTabels")] 16 | partial class initIdentityTabels 17 | { 18 | /// 19 | protected override void BuildTargetModel(ModelBuilder modelBuilder) 20 | { 21 | #pragma warning disable 612, 618 22 | modelBuilder 23 | .HasAnnotation("ProductVersion", "9.0.2") 24 | .HasAnnotation("Relational:MaxIdentifierLength", 128); 25 | 26 | SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); 27 | 28 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => 29 | { 30 | b.Property("Id") 31 | .HasColumnType("nvarchar(450)"); 32 | 33 | b.Property("ConcurrencyStamp") 34 | .IsConcurrencyToken() 35 | .HasColumnType("nvarchar(max)"); 36 | 37 | b.Property("Name") 38 | .HasMaxLength(256) 39 | .HasColumnType("nvarchar(256)"); 40 | 41 | b.Property("NormalizedName") 42 | .HasMaxLength(256) 43 | .HasColumnType("nvarchar(256)"); 44 | 45 | b.HasKey("Id"); 46 | 47 | b.HasIndex("NormalizedName") 48 | .IsUnique() 49 | .HasDatabaseName("RoleNameIndex") 50 | .HasFilter("[NormalizedName] IS NOT NULL"); 51 | 52 | b.ToTable("AspNetRoles", (string)null); 53 | }); 54 | 55 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => 56 | { 57 | b.Property("Id") 58 | .ValueGeneratedOnAdd() 59 | .HasColumnType("int"); 60 | 61 | SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); 62 | 63 | b.Property("ClaimType") 64 | .HasColumnType("nvarchar(max)"); 65 | 66 | b.Property("ClaimValue") 67 | .HasColumnType("nvarchar(max)"); 68 | 69 | b.Property("RoleId") 70 | .IsRequired() 71 | .HasColumnType("nvarchar(450)"); 72 | 73 | b.HasKey("Id"); 74 | 75 | b.HasIndex("RoleId"); 76 | 77 | b.ToTable("AspNetRoleClaims", (string)null); 78 | }); 79 | 80 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUser", b => 81 | { 82 | b.Property("Id") 83 | .HasColumnType("nvarchar(450)"); 84 | 85 | b.Property("AccessFailedCount") 86 | .HasColumnType("int"); 87 | 88 | b.Property("ConcurrencyStamp") 89 | .IsConcurrencyToken() 90 | .HasColumnType("nvarchar(max)"); 91 | 92 | b.Property("Email") 93 | .HasMaxLength(256) 94 | .HasColumnType("nvarchar(256)"); 95 | 96 | b.Property("EmailConfirmed") 97 | .HasColumnType("bit"); 98 | 99 | b.Property("LockoutEnabled") 100 | .HasColumnType("bit"); 101 | 102 | b.Property("LockoutEnd") 103 | .HasColumnType("datetimeoffset"); 104 | 105 | b.Property("NormalizedEmail") 106 | .HasMaxLength(256) 107 | .HasColumnType("nvarchar(256)"); 108 | 109 | b.Property("NormalizedUserName") 110 | .HasMaxLength(256) 111 | .HasColumnType("nvarchar(256)"); 112 | 113 | b.Property("PasswordHash") 114 | .HasColumnType("nvarchar(max)"); 115 | 116 | b.Property("PhoneNumber") 117 | .HasColumnType("nvarchar(max)"); 118 | 119 | b.Property("PhoneNumberConfirmed") 120 | .HasColumnType("bit"); 121 | 122 | b.Property("SecurityStamp") 123 | .HasColumnType("nvarchar(max)"); 124 | 125 | b.Property("TwoFactorEnabled") 126 | .HasColumnType("bit"); 127 | 128 | b.Property("UserName") 129 | .HasMaxLength(256) 130 | .HasColumnType("nvarchar(256)"); 131 | 132 | b.HasKey("Id"); 133 | 134 | b.HasIndex("NormalizedEmail") 135 | .HasDatabaseName("EmailIndex"); 136 | 137 | b.HasIndex("NormalizedUserName") 138 | .IsUnique() 139 | .HasDatabaseName("UserNameIndex") 140 | .HasFilter("[NormalizedUserName] IS NOT NULL"); 141 | 142 | b.ToTable("AspNetUsers", (string)null); 143 | }); 144 | 145 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => 146 | { 147 | b.Property("Id") 148 | .ValueGeneratedOnAdd() 149 | .HasColumnType("int"); 150 | 151 | SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); 152 | 153 | b.Property("ClaimType") 154 | .HasColumnType("nvarchar(max)"); 155 | 156 | b.Property("ClaimValue") 157 | .HasColumnType("nvarchar(max)"); 158 | 159 | b.Property("UserId") 160 | .IsRequired() 161 | .HasColumnType("nvarchar(450)"); 162 | 163 | b.HasKey("Id"); 164 | 165 | b.HasIndex("UserId"); 166 | 167 | b.ToTable("AspNetUserClaims", (string)null); 168 | }); 169 | 170 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => 171 | { 172 | b.Property("LoginProvider") 173 | .HasColumnType("nvarchar(450)"); 174 | 175 | b.Property("ProviderKey") 176 | .HasColumnType("nvarchar(450)"); 177 | 178 | b.Property("ProviderDisplayName") 179 | .HasColumnType("nvarchar(max)"); 180 | 181 | b.Property("UserId") 182 | .IsRequired() 183 | .HasColumnType("nvarchar(450)"); 184 | 185 | b.HasKey("LoginProvider", "ProviderKey"); 186 | 187 | b.HasIndex("UserId"); 188 | 189 | b.ToTable("AspNetUserLogins", (string)null); 190 | }); 191 | 192 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => 193 | { 194 | b.Property("UserId") 195 | .HasColumnType("nvarchar(450)"); 196 | 197 | b.Property("RoleId") 198 | .HasColumnType("nvarchar(450)"); 199 | 200 | b.HasKey("UserId", "RoleId"); 201 | 202 | b.HasIndex("RoleId"); 203 | 204 | b.ToTable("AspNetUserRoles", (string)null); 205 | }); 206 | 207 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => 208 | { 209 | b.Property("UserId") 210 | .HasColumnType("nvarchar(450)"); 211 | 212 | b.Property("LoginProvider") 213 | .HasColumnType("nvarchar(450)"); 214 | 215 | b.Property("Name") 216 | .HasColumnType("nvarchar(450)"); 217 | 218 | b.Property("Value") 219 | .HasColumnType("nvarchar(max)"); 220 | 221 | b.HasKey("UserId", "LoginProvider", "Name"); 222 | 223 | b.ToTable("AspNetUserTokens", (string)null); 224 | }); 225 | 226 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => 227 | { 228 | b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) 229 | .WithMany() 230 | .HasForeignKey("RoleId") 231 | .OnDelete(DeleteBehavior.Cascade) 232 | .IsRequired(); 233 | }); 234 | 235 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => 236 | { 237 | b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) 238 | .WithMany() 239 | .HasForeignKey("UserId") 240 | .OnDelete(DeleteBehavior.Cascade) 241 | .IsRequired(); 242 | }); 243 | 244 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => 245 | { 246 | b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) 247 | .WithMany() 248 | .HasForeignKey("UserId") 249 | .OnDelete(DeleteBehavior.Cascade) 250 | .IsRequired(); 251 | }); 252 | 253 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => 254 | { 255 | b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) 256 | .WithMany() 257 | .HasForeignKey("RoleId") 258 | .OnDelete(DeleteBehavior.Cascade) 259 | .IsRequired(); 260 | 261 | b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) 262 | .WithMany() 263 | .HasForeignKey("UserId") 264 | .OnDelete(DeleteBehavior.Cascade) 265 | .IsRequired(); 266 | }); 267 | 268 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => 269 | { 270 | b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) 271 | .WithMany() 272 | .HasForeignKey("UserId") 273 | .OnDelete(DeleteBehavior.Cascade) 274 | .IsRequired(); 275 | }); 276 | #pragma warning restore 612, 618 277 | } 278 | } 279 | } 280 | -------------------------------------------------------------------------------- /DataAcess/Migrations/20250223093113_initIdentityTabels.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.EntityFrameworkCore.Migrations; 3 | 4 | #nullable disable 5 | 6 | namespace DataAcess.Migrations 7 | { 8 | /// 9 | public partial class initIdentityTabels : Migration 10 | { 11 | /// 12 | protected override void Up(MigrationBuilder migrationBuilder) 13 | { 14 | migrationBuilder.CreateTable( 15 | name: "AspNetRoles", 16 | columns: table => new 17 | { 18 | Id = table.Column(type: "nvarchar(450)", nullable: false), 19 | Name = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), 20 | NormalizedName = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), 21 | ConcurrencyStamp = table.Column(type: "nvarchar(max)", nullable: true) 22 | }, 23 | constraints: table => 24 | { 25 | table.PrimaryKey("PK_AspNetRoles", x => x.Id); 26 | }); 27 | 28 | migrationBuilder.CreateTable( 29 | name: "AspNetUsers", 30 | columns: table => new 31 | { 32 | Id = table.Column(type: "nvarchar(450)", nullable: false), 33 | UserName = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), 34 | NormalizedUserName = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), 35 | Email = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), 36 | NormalizedEmail = table.Column(type: "nvarchar(256)", maxLength: 256, nullable: true), 37 | EmailConfirmed = table.Column(type: "bit", nullable: false), 38 | PasswordHash = table.Column(type: "nvarchar(max)", nullable: true), 39 | SecurityStamp = table.Column(type: "nvarchar(max)", nullable: true), 40 | ConcurrencyStamp = table.Column(type: "nvarchar(max)", nullable: true), 41 | PhoneNumber = table.Column(type: "nvarchar(max)", nullable: true), 42 | PhoneNumberConfirmed = table.Column(type: "bit", nullable: false), 43 | TwoFactorEnabled = table.Column(type: "bit", nullable: false), 44 | LockoutEnd = table.Column(type: "datetimeoffset", nullable: true), 45 | LockoutEnabled = table.Column(type: "bit", nullable: false), 46 | AccessFailedCount = table.Column(type: "int", nullable: false) 47 | }, 48 | constraints: table => 49 | { 50 | table.PrimaryKey("PK_AspNetUsers", x => x.Id); 51 | }); 52 | 53 | migrationBuilder.CreateTable( 54 | name: "AspNetRoleClaims", 55 | columns: table => new 56 | { 57 | Id = table.Column(type: "int", nullable: false) 58 | .Annotation("SqlServer:Identity", "1, 1"), 59 | RoleId = table.Column(type: "nvarchar(450)", nullable: false), 60 | ClaimType = table.Column(type: "nvarchar(max)", nullable: true), 61 | ClaimValue = table.Column(type: "nvarchar(max)", nullable: true) 62 | }, 63 | constraints: table => 64 | { 65 | table.PrimaryKey("PK_AspNetRoleClaims", x => x.Id); 66 | table.ForeignKey( 67 | name: "FK_AspNetRoleClaims_AspNetRoles_RoleId", 68 | column: x => x.RoleId, 69 | principalTable: "AspNetRoles", 70 | principalColumn: "Id", 71 | onDelete: ReferentialAction.Cascade); 72 | }); 73 | 74 | migrationBuilder.CreateTable( 75 | name: "AspNetUserClaims", 76 | columns: table => new 77 | { 78 | Id = table.Column(type: "int", nullable: false) 79 | .Annotation("SqlServer:Identity", "1, 1"), 80 | UserId = table.Column(type: "nvarchar(450)", nullable: false), 81 | ClaimType = table.Column(type: "nvarchar(max)", nullable: true), 82 | ClaimValue = table.Column(type: "nvarchar(max)", nullable: true) 83 | }, 84 | constraints: table => 85 | { 86 | table.PrimaryKey("PK_AspNetUserClaims", x => x.Id); 87 | table.ForeignKey( 88 | name: "FK_AspNetUserClaims_AspNetUsers_UserId", 89 | column: x => x.UserId, 90 | principalTable: "AspNetUsers", 91 | principalColumn: "Id", 92 | onDelete: ReferentialAction.Cascade); 93 | }); 94 | 95 | migrationBuilder.CreateTable( 96 | name: "AspNetUserLogins", 97 | columns: table => new 98 | { 99 | LoginProvider = table.Column(type: "nvarchar(450)", nullable: false), 100 | ProviderKey = table.Column(type: "nvarchar(450)", nullable: false), 101 | ProviderDisplayName = table.Column(type: "nvarchar(max)", nullable: true), 102 | UserId = table.Column(type: "nvarchar(450)", nullable: false) 103 | }, 104 | constraints: table => 105 | { 106 | table.PrimaryKey("PK_AspNetUserLogins", x => new { x.LoginProvider, x.ProviderKey }); 107 | table.ForeignKey( 108 | name: "FK_AspNetUserLogins_AspNetUsers_UserId", 109 | column: x => x.UserId, 110 | principalTable: "AspNetUsers", 111 | principalColumn: "Id", 112 | onDelete: ReferentialAction.Cascade); 113 | }); 114 | 115 | migrationBuilder.CreateTable( 116 | name: "AspNetUserRoles", 117 | columns: table => new 118 | { 119 | UserId = table.Column(type: "nvarchar(450)", nullable: false), 120 | RoleId = table.Column(type: "nvarchar(450)", nullable: false) 121 | }, 122 | constraints: table => 123 | { 124 | table.PrimaryKey("PK_AspNetUserRoles", x => new { x.UserId, x.RoleId }); 125 | table.ForeignKey( 126 | name: "FK_AspNetUserRoles_AspNetRoles_RoleId", 127 | column: x => x.RoleId, 128 | principalTable: "AspNetRoles", 129 | principalColumn: "Id", 130 | onDelete: ReferentialAction.Cascade); 131 | table.ForeignKey( 132 | name: "FK_AspNetUserRoles_AspNetUsers_UserId", 133 | column: x => x.UserId, 134 | principalTable: "AspNetUsers", 135 | principalColumn: "Id", 136 | onDelete: ReferentialAction.Cascade); 137 | }); 138 | 139 | migrationBuilder.CreateTable( 140 | name: "AspNetUserTokens", 141 | columns: table => new 142 | { 143 | UserId = table.Column(type: "nvarchar(450)", nullable: false), 144 | LoginProvider = table.Column(type: "nvarchar(450)", nullable: false), 145 | Name = table.Column(type: "nvarchar(450)", nullable: false), 146 | Value = table.Column(type: "nvarchar(max)", nullable: true) 147 | }, 148 | constraints: table => 149 | { 150 | table.PrimaryKey("PK_AspNetUserTokens", x => new { x.UserId, x.LoginProvider, x.Name }); 151 | table.ForeignKey( 152 | name: "FK_AspNetUserTokens_AspNetUsers_UserId", 153 | column: x => x.UserId, 154 | principalTable: "AspNetUsers", 155 | principalColumn: "Id", 156 | onDelete: ReferentialAction.Cascade); 157 | }); 158 | 159 | migrationBuilder.CreateIndex( 160 | name: "IX_AspNetRoleClaims_RoleId", 161 | table: "AspNetRoleClaims", 162 | column: "RoleId"); 163 | 164 | migrationBuilder.CreateIndex( 165 | name: "RoleNameIndex", 166 | table: "AspNetRoles", 167 | column: "NormalizedName", 168 | unique: true, 169 | filter: "[NormalizedName] IS NOT NULL"); 170 | 171 | migrationBuilder.CreateIndex( 172 | name: "IX_AspNetUserClaims_UserId", 173 | table: "AspNetUserClaims", 174 | column: "UserId"); 175 | 176 | migrationBuilder.CreateIndex( 177 | name: "IX_AspNetUserLogins_UserId", 178 | table: "AspNetUserLogins", 179 | column: "UserId"); 180 | 181 | migrationBuilder.CreateIndex( 182 | name: "IX_AspNetUserRoles_RoleId", 183 | table: "AspNetUserRoles", 184 | column: "RoleId"); 185 | 186 | migrationBuilder.CreateIndex( 187 | name: "EmailIndex", 188 | table: "AspNetUsers", 189 | column: "NormalizedEmail"); 190 | 191 | migrationBuilder.CreateIndex( 192 | name: "UserNameIndex", 193 | table: "AspNetUsers", 194 | column: "NormalizedUserName", 195 | unique: true, 196 | filter: "[NormalizedUserName] IS NOT NULL"); 197 | } 198 | 199 | /// 200 | protected override void Down(MigrationBuilder migrationBuilder) 201 | { 202 | migrationBuilder.DropTable( 203 | name: "AspNetRoleClaims"); 204 | 205 | migrationBuilder.DropTable( 206 | name: "AspNetUserClaims"); 207 | 208 | migrationBuilder.DropTable( 209 | name: "AspNetUserLogins"); 210 | 211 | migrationBuilder.DropTable( 212 | name: "AspNetUserRoles"); 213 | 214 | migrationBuilder.DropTable( 215 | name: "AspNetUserTokens"); 216 | 217 | migrationBuilder.DropTable( 218 | name: "AspNetRoles"); 219 | 220 | migrationBuilder.DropTable( 221 | name: "AspNetUsers"); 222 | } 223 | } 224 | } 225 | -------------------------------------------------------------------------------- /DataAcess/Migrations/20250223094815_addNameToAspNetUserTabel.Designer.cs: -------------------------------------------------------------------------------- 1 | // 2 | using System; 3 | using DataAcess; 4 | using Microsoft.EntityFrameworkCore; 5 | using Microsoft.EntityFrameworkCore.Infrastructure; 6 | using Microsoft.EntityFrameworkCore.Metadata; 7 | using Microsoft.EntityFrameworkCore.Migrations; 8 | using Microsoft.EntityFrameworkCore.Storage.ValueConversion; 9 | 10 | #nullable disable 11 | 12 | namespace DataAcess.Migrations 13 | { 14 | [DbContext(typeof(ApplicationDbContext))] 15 | [Migration("20250223094815_addNameToAspNetUserTabel")] 16 | partial class addNameToAspNetUserTabel 17 | { 18 | /// 19 | protected override void BuildTargetModel(ModelBuilder modelBuilder) 20 | { 21 | #pragma warning disable 612, 618 22 | modelBuilder 23 | .HasAnnotation("ProductVersion", "9.0.2") 24 | .HasAnnotation("Relational:MaxIdentifierLength", 128); 25 | 26 | SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); 27 | 28 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => 29 | { 30 | b.Property("Id") 31 | .HasColumnType("nvarchar(450)"); 32 | 33 | b.Property("ConcurrencyStamp") 34 | .IsConcurrencyToken() 35 | .HasColumnType("nvarchar(max)"); 36 | 37 | b.Property("Name") 38 | .HasMaxLength(256) 39 | .HasColumnType("nvarchar(256)"); 40 | 41 | b.Property("NormalizedName") 42 | .HasMaxLength(256) 43 | .HasColumnType("nvarchar(256)"); 44 | 45 | b.HasKey("Id"); 46 | 47 | b.HasIndex("NormalizedName") 48 | .IsUnique() 49 | .HasDatabaseName("RoleNameIndex") 50 | .HasFilter("[NormalizedName] IS NOT NULL"); 51 | 52 | b.ToTable("AspNetRoles", (string)null); 53 | }); 54 | 55 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => 56 | { 57 | b.Property("Id") 58 | .ValueGeneratedOnAdd() 59 | .HasColumnType("int"); 60 | 61 | SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); 62 | 63 | b.Property("ClaimType") 64 | .HasColumnType("nvarchar(max)"); 65 | 66 | b.Property("ClaimValue") 67 | .HasColumnType("nvarchar(max)"); 68 | 69 | b.Property("RoleId") 70 | .IsRequired() 71 | .HasColumnType("nvarchar(450)"); 72 | 73 | b.HasKey("Id"); 74 | 75 | b.HasIndex("RoleId"); 76 | 77 | b.ToTable("AspNetRoleClaims", (string)null); 78 | }); 79 | 80 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUser", b => 81 | { 82 | b.Property("Id") 83 | .HasColumnType("nvarchar(450)"); 84 | 85 | b.Property("AccessFailedCount") 86 | .HasColumnType("int"); 87 | 88 | b.Property("ConcurrencyStamp") 89 | .IsConcurrencyToken() 90 | .HasColumnType("nvarchar(max)"); 91 | 92 | b.Property("Discriminator") 93 | .IsRequired() 94 | .HasMaxLength(21) 95 | .HasColumnType("nvarchar(21)"); 96 | 97 | b.Property("Email") 98 | .HasMaxLength(256) 99 | .HasColumnType("nvarchar(256)"); 100 | 101 | b.Property("EmailConfirmed") 102 | .HasColumnType("bit"); 103 | 104 | b.Property("LockoutEnabled") 105 | .HasColumnType("bit"); 106 | 107 | b.Property("LockoutEnd") 108 | .HasColumnType("datetimeoffset"); 109 | 110 | b.Property("NormalizedEmail") 111 | .HasMaxLength(256) 112 | .HasColumnType("nvarchar(256)"); 113 | 114 | b.Property("NormalizedUserName") 115 | .HasMaxLength(256) 116 | .HasColumnType("nvarchar(256)"); 117 | 118 | b.Property("PasswordHash") 119 | .HasColumnType("nvarchar(max)"); 120 | 121 | b.Property("PhoneNumber") 122 | .HasColumnType("nvarchar(max)"); 123 | 124 | b.Property("PhoneNumberConfirmed") 125 | .HasColumnType("bit"); 126 | 127 | b.Property("SecurityStamp") 128 | .HasColumnType("nvarchar(max)"); 129 | 130 | b.Property("TwoFactorEnabled") 131 | .HasColumnType("bit"); 132 | 133 | b.Property("UserName") 134 | .HasMaxLength(256) 135 | .HasColumnType("nvarchar(256)"); 136 | 137 | b.HasKey("Id"); 138 | 139 | b.HasIndex("NormalizedEmail") 140 | .HasDatabaseName("EmailIndex"); 141 | 142 | b.HasIndex("NormalizedUserName") 143 | .IsUnique() 144 | .HasDatabaseName("UserNameIndex") 145 | .HasFilter("[NormalizedUserName] IS NOT NULL"); 146 | 147 | b.ToTable("AspNetUsers", (string)null); 148 | 149 | b.HasDiscriminator().HasValue("IdentityUser"); 150 | 151 | b.UseTphMappingStrategy(); 152 | }); 153 | 154 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => 155 | { 156 | b.Property("Id") 157 | .ValueGeneratedOnAdd() 158 | .HasColumnType("int"); 159 | 160 | SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); 161 | 162 | b.Property("ClaimType") 163 | .HasColumnType("nvarchar(max)"); 164 | 165 | b.Property("ClaimValue") 166 | .HasColumnType("nvarchar(max)"); 167 | 168 | b.Property("UserId") 169 | .IsRequired() 170 | .HasColumnType("nvarchar(450)"); 171 | 172 | b.HasKey("Id"); 173 | 174 | b.HasIndex("UserId"); 175 | 176 | b.ToTable("AspNetUserClaims", (string)null); 177 | }); 178 | 179 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => 180 | { 181 | b.Property("LoginProvider") 182 | .HasColumnType("nvarchar(450)"); 183 | 184 | b.Property("ProviderKey") 185 | .HasColumnType("nvarchar(450)"); 186 | 187 | b.Property("ProviderDisplayName") 188 | .HasColumnType("nvarchar(max)"); 189 | 190 | b.Property("UserId") 191 | .IsRequired() 192 | .HasColumnType("nvarchar(450)"); 193 | 194 | b.HasKey("LoginProvider", "ProviderKey"); 195 | 196 | b.HasIndex("UserId"); 197 | 198 | b.ToTable("AspNetUserLogins", (string)null); 199 | }); 200 | 201 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => 202 | { 203 | b.Property("UserId") 204 | .HasColumnType("nvarchar(450)"); 205 | 206 | b.Property("RoleId") 207 | .HasColumnType("nvarchar(450)"); 208 | 209 | b.HasKey("UserId", "RoleId"); 210 | 211 | b.HasIndex("RoleId"); 212 | 213 | b.ToTable("AspNetUserRoles", (string)null); 214 | }); 215 | 216 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => 217 | { 218 | b.Property("UserId") 219 | .HasColumnType("nvarchar(450)"); 220 | 221 | b.Property("LoginProvider") 222 | .HasColumnType("nvarchar(450)"); 223 | 224 | b.Property("Name") 225 | .HasColumnType("nvarchar(450)"); 226 | 227 | b.Property("Value") 228 | .HasColumnType("nvarchar(max)"); 229 | 230 | b.HasKey("UserId", "LoginProvider", "Name"); 231 | 232 | b.ToTable("AspNetUserTokens", (string)null); 233 | }); 234 | 235 | modelBuilder.Entity("Models.ApplicationUser", b => 236 | { 237 | b.HasBaseType("Microsoft.AspNetCore.Identity.IdentityUser"); 238 | 239 | b.Property("Name") 240 | .IsRequired() 241 | .HasColumnType("nvarchar(max)"); 242 | 243 | b.HasDiscriminator().HasValue("ApplicationUser"); 244 | }); 245 | 246 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => 247 | { 248 | b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) 249 | .WithMany() 250 | .HasForeignKey("RoleId") 251 | .OnDelete(DeleteBehavior.Cascade) 252 | .IsRequired(); 253 | }); 254 | 255 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => 256 | { 257 | b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) 258 | .WithMany() 259 | .HasForeignKey("UserId") 260 | .OnDelete(DeleteBehavior.Cascade) 261 | .IsRequired(); 262 | }); 263 | 264 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => 265 | { 266 | b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) 267 | .WithMany() 268 | .HasForeignKey("UserId") 269 | .OnDelete(DeleteBehavior.Cascade) 270 | .IsRequired(); 271 | }); 272 | 273 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => 274 | { 275 | b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) 276 | .WithMany() 277 | .HasForeignKey("RoleId") 278 | .OnDelete(DeleteBehavior.Cascade) 279 | .IsRequired(); 280 | 281 | b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) 282 | .WithMany() 283 | .HasForeignKey("UserId") 284 | .OnDelete(DeleteBehavior.Cascade) 285 | .IsRequired(); 286 | }); 287 | 288 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => 289 | { 290 | b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) 291 | .WithMany() 292 | .HasForeignKey("UserId") 293 | .OnDelete(DeleteBehavior.Cascade) 294 | .IsRequired(); 295 | }); 296 | #pragma warning restore 612, 618 297 | } 298 | } 299 | } 300 | -------------------------------------------------------------------------------- /DataAcess/Migrations/20250223094815_addNameToAspNetUserTabel.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore.Migrations; 2 | 3 | #nullable disable 4 | 5 | namespace DataAcess.Migrations 6 | { 7 | /// 8 | public partial class addNameToAspNetUserTabel : Migration 9 | { 10 | /// 11 | protected override void Up(MigrationBuilder migrationBuilder) 12 | { 13 | migrationBuilder.AddColumn( 14 | name: "Discriminator", 15 | table: "AspNetUsers", 16 | type: "nvarchar(21)", 17 | maxLength: 21, 18 | nullable: false, 19 | defaultValue: ""); 20 | 21 | migrationBuilder.AddColumn( 22 | name: "Name", 23 | table: "AspNetUsers", 24 | type: "nvarchar(max)", 25 | nullable: true); 26 | } 27 | 28 | /// 29 | protected override void Down(MigrationBuilder migrationBuilder) 30 | { 31 | migrationBuilder.DropColumn( 32 | name: "Discriminator", 33 | table: "AspNetUsers"); 34 | 35 | migrationBuilder.DropColumn( 36 | name: "Name", 37 | table: "AspNetUsers"); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /DataAcess/Migrations/20250227215805_seed roles data.Designer.cs: -------------------------------------------------------------------------------- 1 | // 2 | using System; 3 | using DataAcess; 4 | using Microsoft.EntityFrameworkCore; 5 | using Microsoft.EntityFrameworkCore.Infrastructure; 6 | using Microsoft.EntityFrameworkCore.Metadata; 7 | using Microsoft.EntityFrameworkCore.Migrations; 8 | using Microsoft.EntityFrameworkCore.Storage.ValueConversion; 9 | 10 | #nullable disable 11 | 12 | namespace DataAcess.Migrations 13 | { 14 | [DbContext(typeof(ApplicationDbContext))] 15 | [Migration("20250227215805_seed roles data")] 16 | partial class seedrolesdata 17 | { 18 | /// 19 | protected override void BuildTargetModel(ModelBuilder modelBuilder) 20 | { 21 | #pragma warning disable 612, 618 22 | modelBuilder 23 | .HasAnnotation("ProductVersion", "9.0.2") 24 | .HasAnnotation("Relational:MaxIdentifierLength", 128); 25 | 26 | SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); 27 | 28 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => 29 | { 30 | b.Property("Id") 31 | .HasColumnType("nvarchar(450)"); 32 | 33 | b.Property("ConcurrencyStamp") 34 | .IsConcurrencyToken() 35 | .HasColumnType("nvarchar(max)"); 36 | 37 | b.Property("Name") 38 | .HasMaxLength(256) 39 | .HasColumnType("nvarchar(256)"); 40 | 41 | b.Property("NormalizedName") 42 | .HasMaxLength(256) 43 | .HasColumnType("nvarchar(256)"); 44 | 45 | b.HasKey("Id"); 46 | 47 | b.HasIndex("NormalizedName") 48 | .IsUnique() 49 | .HasDatabaseName("RoleNameIndex") 50 | .HasFilter("[NormalizedName] IS NOT NULL"); 51 | 52 | b.ToTable("AspNetRoles", (string)null); 53 | 54 | b.HasData( 55 | new 56 | { 57 | Id = "43d0590f-2f82-4867-83c4-18f0488f9706", 58 | Name = "admin", 59 | NormalizedName = "ADMIN" 60 | }, 61 | new 62 | { 63 | Id = "ff715d53-7725-48de-8d74-f064b8b41b45", 64 | Name = "user", 65 | NormalizedName = "USER" 66 | }, 67 | new 68 | { 69 | Id = "new-role-id-1", 70 | Name = "manager", 71 | NormalizedName = "MANAGER" 72 | }, 73 | new 74 | { 75 | Id = "new-role-id-2", 76 | Name = "guest", 77 | NormalizedName = "GUEST" 78 | }); 79 | }); 80 | 81 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => 82 | { 83 | b.Property("Id") 84 | .ValueGeneratedOnAdd() 85 | .HasColumnType("int"); 86 | 87 | SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); 88 | 89 | b.Property("ClaimType") 90 | .HasColumnType("nvarchar(max)"); 91 | 92 | b.Property("ClaimValue") 93 | .HasColumnType("nvarchar(max)"); 94 | 95 | b.Property("RoleId") 96 | .IsRequired() 97 | .HasColumnType("nvarchar(450)"); 98 | 99 | b.HasKey("Id"); 100 | 101 | b.HasIndex("RoleId"); 102 | 103 | b.ToTable("AspNetRoleClaims", (string)null); 104 | }); 105 | 106 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUser", b => 107 | { 108 | b.Property("Id") 109 | .HasColumnType("nvarchar(450)"); 110 | 111 | b.Property("AccessFailedCount") 112 | .HasColumnType("int"); 113 | 114 | b.Property("ConcurrencyStamp") 115 | .IsConcurrencyToken() 116 | .HasColumnType("nvarchar(max)"); 117 | 118 | b.Property("Discriminator") 119 | .IsRequired() 120 | .HasMaxLength(21) 121 | .HasColumnType("nvarchar(21)"); 122 | 123 | b.Property("Email") 124 | .HasMaxLength(256) 125 | .HasColumnType("nvarchar(256)"); 126 | 127 | b.Property("EmailConfirmed") 128 | .HasColumnType("bit"); 129 | 130 | b.Property("LockoutEnabled") 131 | .HasColumnType("bit"); 132 | 133 | b.Property("LockoutEnd") 134 | .HasColumnType("datetimeoffset"); 135 | 136 | b.Property("NormalizedEmail") 137 | .HasMaxLength(256) 138 | .HasColumnType("nvarchar(256)"); 139 | 140 | b.Property("NormalizedUserName") 141 | .HasMaxLength(256) 142 | .HasColumnType("nvarchar(256)"); 143 | 144 | b.Property("PasswordHash") 145 | .HasColumnType("nvarchar(max)"); 146 | 147 | b.Property("PhoneNumber") 148 | .HasColumnType("nvarchar(max)"); 149 | 150 | b.Property("PhoneNumberConfirmed") 151 | .HasColumnType("bit"); 152 | 153 | b.Property("SecurityStamp") 154 | .HasColumnType("nvarchar(max)"); 155 | 156 | b.Property("TwoFactorEnabled") 157 | .HasColumnType("bit"); 158 | 159 | b.Property("UserName") 160 | .HasMaxLength(256) 161 | .HasColumnType("nvarchar(256)"); 162 | 163 | b.HasKey("Id"); 164 | 165 | b.HasIndex("NormalizedEmail") 166 | .HasDatabaseName("EmailIndex"); 167 | 168 | b.HasIndex("NormalizedUserName") 169 | .IsUnique() 170 | .HasDatabaseName("UserNameIndex") 171 | .HasFilter("[NormalizedUserName] IS NOT NULL"); 172 | 173 | b.ToTable("AspNetUsers", (string)null); 174 | 175 | b.HasDiscriminator().HasValue("IdentityUser"); 176 | 177 | b.UseTphMappingStrategy(); 178 | }); 179 | 180 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => 181 | { 182 | b.Property("Id") 183 | .ValueGeneratedOnAdd() 184 | .HasColumnType("int"); 185 | 186 | SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); 187 | 188 | b.Property("ClaimType") 189 | .HasColumnType("nvarchar(max)"); 190 | 191 | b.Property("ClaimValue") 192 | .HasColumnType("nvarchar(max)"); 193 | 194 | b.Property("UserId") 195 | .IsRequired() 196 | .HasColumnType("nvarchar(450)"); 197 | 198 | b.HasKey("Id"); 199 | 200 | b.HasIndex("UserId"); 201 | 202 | b.ToTable("AspNetUserClaims", (string)null); 203 | }); 204 | 205 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => 206 | { 207 | b.Property("LoginProvider") 208 | .HasColumnType("nvarchar(450)"); 209 | 210 | b.Property("ProviderKey") 211 | .HasColumnType("nvarchar(450)"); 212 | 213 | b.Property("ProviderDisplayName") 214 | .HasColumnType("nvarchar(max)"); 215 | 216 | b.Property("UserId") 217 | .IsRequired() 218 | .HasColumnType("nvarchar(450)"); 219 | 220 | b.HasKey("LoginProvider", "ProviderKey"); 221 | 222 | b.HasIndex("UserId"); 223 | 224 | b.ToTable("AspNetUserLogins", (string)null); 225 | }); 226 | 227 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => 228 | { 229 | b.Property("UserId") 230 | .HasColumnType("nvarchar(450)"); 231 | 232 | b.Property("RoleId") 233 | .HasColumnType("nvarchar(450)"); 234 | 235 | b.HasKey("UserId", "RoleId"); 236 | 237 | b.HasIndex("RoleId"); 238 | 239 | b.ToTable("AspNetUserRoles", (string)null); 240 | }); 241 | 242 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => 243 | { 244 | b.Property("UserId") 245 | .HasColumnType("nvarchar(450)"); 246 | 247 | b.Property("LoginProvider") 248 | .HasColumnType("nvarchar(450)"); 249 | 250 | b.Property("Name") 251 | .HasColumnType("nvarchar(450)"); 252 | 253 | b.Property("Value") 254 | .HasColumnType("nvarchar(max)"); 255 | 256 | b.HasKey("UserId", "LoginProvider", "Name"); 257 | 258 | b.ToTable("AspNetUserTokens", (string)null); 259 | }); 260 | 261 | modelBuilder.Entity("Models.ApplicationUser", b => 262 | { 263 | b.HasBaseType("Microsoft.AspNetCore.Identity.IdentityUser"); 264 | 265 | b.Property("Name") 266 | .IsRequired() 267 | .HasColumnType("nvarchar(max)"); 268 | 269 | b.HasDiscriminator().HasValue("ApplicationUser"); 270 | }); 271 | 272 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => 273 | { 274 | b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) 275 | .WithMany() 276 | .HasForeignKey("RoleId") 277 | .OnDelete(DeleteBehavior.Cascade) 278 | .IsRequired(); 279 | }); 280 | 281 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => 282 | { 283 | b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) 284 | .WithMany() 285 | .HasForeignKey("UserId") 286 | .OnDelete(DeleteBehavior.Cascade) 287 | .IsRequired(); 288 | }); 289 | 290 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => 291 | { 292 | b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) 293 | .WithMany() 294 | .HasForeignKey("UserId") 295 | .OnDelete(DeleteBehavior.Cascade) 296 | .IsRequired(); 297 | }); 298 | 299 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => 300 | { 301 | b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) 302 | .WithMany() 303 | .HasForeignKey("RoleId") 304 | .OnDelete(DeleteBehavior.Cascade) 305 | .IsRequired(); 306 | 307 | b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) 308 | .WithMany() 309 | .HasForeignKey("UserId") 310 | .OnDelete(DeleteBehavior.Cascade) 311 | .IsRequired(); 312 | }); 313 | 314 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => 315 | { 316 | b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) 317 | .WithMany() 318 | .HasForeignKey("UserId") 319 | .OnDelete(DeleteBehavior.Cascade) 320 | .IsRequired(); 321 | }); 322 | #pragma warning restore 612, 618 323 | } 324 | } 325 | } 326 | -------------------------------------------------------------------------------- /DataAcess/Migrations/20250227215805_seed roles data.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore.Migrations; 2 | 3 | #nullable disable 4 | 5 | #pragma warning disable CA1814 // Prefer jagged arrays over multidimensional 6 | 7 | namespace DataAcess.Migrations 8 | { 9 | /// 10 | public partial class seedrolesdata : Migration 11 | { 12 | /// 13 | protected override void Up(MigrationBuilder migrationBuilder) 14 | { 15 | migrationBuilder.InsertData( 16 | table: "AspNetRoles", 17 | columns: new[] { "Id", "ConcurrencyStamp", "Name", "NormalizedName" }, 18 | values: new object[,] 19 | { 20 | { "43d0590f-2f82-4867-83c4-18f0488f9706", null, "admin", "ADMIN" }, 21 | { "ff715d53-7725-48de-8d74-f064b8b41b45", null, "user", "USER" }, 22 | { "new-role-id-1", null, "manager", "MANAGER" }, 23 | { "new-role-id-2", null, "guest", "GUEST" } 24 | }); 25 | } 26 | 27 | /// 28 | protected override void Down(MigrationBuilder migrationBuilder) 29 | { 30 | migrationBuilder.DeleteData( 31 | table: "AspNetRoles", 32 | keyColumn: "Id", 33 | keyValue: "43d0590f-2f82-4867-83c4-18f0488f9706"); 34 | 35 | migrationBuilder.DeleteData( 36 | table: "AspNetRoles", 37 | keyColumn: "Id", 38 | keyValue: "ff715d53-7725-48de-8d74-f064b8b41b45"); 39 | 40 | migrationBuilder.DeleteData( 41 | table: "AspNetRoles", 42 | keyColumn: "Id", 43 | keyValue: "new-role-id-1"); 44 | 45 | migrationBuilder.DeleteData( 46 | table: "AspNetRoles", 47 | keyColumn: "Id", 48 | keyValue: "new-role-id-2"); 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /DataAcess/Migrations/20250228210101_add imgUrl to user.Designer.cs: -------------------------------------------------------------------------------- 1 | // 2 | using System; 3 | using DataAcess; 4 | using Microsoft.EntityFrameworkCore; 5 | using Microsoft.EntityFrameworkCore.Infrastructure; 6 | using Microsoft.EntityFrameworkCore.Metadata; 7 | using Microsoft.EntityFrameworkCore.Migrations; 8 | using Microsoft.EntityFrameworkCore.Storage.ValueConversion; 9 | 10 | #nullable disable 11 | 12 | namespace DataAcess.Migrations 13 | { 14 | [DbContext(typeof(ApplicationDbContext))] 15 | [Migration("20250228210101_add imgUrl to user")] 16 | partial class addimgUrltouser 17 | { 18 | /// 19 | protected override void BuildTargetModel(ModelBuilder modelBuilder) 20 | { 21 | #pragma warning disable 612, 618 22 | modelBuilder 23 | .HasAnnotation("ProductVersion", "9.0.2") 24 | .HasAnnotation("Relational:MaxIdentifierLength", 128); 25 | 26 | SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); 27 | 28 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => 29 | { 30 | b.Property("Id") 31 | .HasColumnType("nvarchar(450)"); 32 | 33 | b.Property("ConcurrencyStamp") 34 | .IsConcurrencyToken() 35 | .HasColumnType("nvarchar(max)"); 36 | 37 | b.Property("Name") 38 | .HasMaxLength(256) 39 | .HasColumnType("nvarchar(256)"); 40 | 41 | b.Property("NormalizedName") 42 | .HasMaxLength(256) 43 | .HasColumnType("nvarchar(256)"); 44 | 45 | b.HasKey("Id"); 46 | 47 | b.HasIndex("NormalizedName") 48 | .IsUnique() 49 | .HasDatabaseName("RoleNameIndex") 50 | .HasFilter("[NormalizedName] IS NOT NULL"); 51 | 52 | b.ToTable("AspNetRoles", (string)null); 53 | 54 | b.HasData( 55 | new 56 | { 57 | Id = "43d0590f-2f82-4867-83c4-18f0488f9706", 58 | Name = "admin", 59 | NormalizedName = "ADMIN" 60 | }, 61 | new 62 | { 63 | Id = "ff715d53-7725-48de-8d74-f064b8b41b45", 64 | Name = "user", 65 | NormalizedName = "USER" 66 | }, 67 | new 68 | { 69 | Id = "5654533a-52b5-4e1e-b9e5-fd8036ef35ff", 70 | Name = "manager", 71 | NormalizedName = "MANAGER" 72 | }, 73 | new 74 | { 75 | Id = "2b440d41-47fa-4fe5-ae96-b4ae34d223a1", 76 | Name = "guest", 77 | NormalizedName = "GUEST" 78 | }); 79 | }); 80 | 81 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => 82 | { 83 | b.Property("Id") 84 | .ValueGeneratedOnAdd() 85 | .HasColumnType("int"); 86 | 87 | SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); 88 | 89 | b.Property("ClaimType") 90 | .HasColumnType("nvarchar(max)"); 91 | 92 | b.Property("ClaimValue") 93 | .HasColumnType("nvarchar(max)"); 94 | 95 | b.Property("RoleId") 96 | .IsRequired() 97 | .HasColumnType("nvarchar(450)"); 98 | 99 | b.HasKey("Id"); 100 | 101 | b.HasIndex("RoleId"); 102 | 103 | b.ToTable("AspNetRoleClaims", (string)null); 104 | }); 105 | 106 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUser", b => 107 | { 108 | b.Property("Id") 109 | .HasColumnType("nvarchar(450)"); 110 | 111 | b.Property("AccessFailedCount") 112 | .HasColumnType("int"); 113 | 114 | b.Property("ConcurrencyStamp") 115 | .IsConcurrencyToken() 116 | .HasColumnType("nvarchar(max)"); 117 | 118 | b.Property("Discriminator") 119 | .IsRequired() 120 | .HasMaxLength(21) 121 | .HasColumnType("nvarchar(21)"); 122 | 123 | b.Property("Email") 124 | .HasMaxLength(256) 125 | .HasColumnType("nvarchar(256)"); 126 | 127 | b.Property("EmailConfirmed") 128 | .HasColumnType("bit"); 129 | 130 | b.Property("LockoutEnabled") 131 | .HasColumnType("bit"); 132 | 133 | b.Property("LockoutEnd") 134 | .HasColumnType("datetimeoffset"); 135 | 136 | b.Property("NormalizedEmail") 137 | .HasMaxLength(256) 138 | .HasColumnType("nvarchar(256)"); 139 | 140 | b.Property("NormalizedUserName") 141 | .HasMaxLength(256) 142 | .HasColumnType("nvarchar(256)"); 143 | 144 | b.Property("PasswordHash") 145 | .HasColumnType("nvarchar(max)"); 146 | 147 | b.Property("PhoneNumber") 148 | .HasColumnType("nvarchar(max)"); 149 | 150 | b.Property("PhoneNumberConfirmed") 151 | .HasColumnType("bit"); 152 | 153 | b.Property("SecurityStamp") 154 | .HasColumnType("nvarchar(max)"); 155 | 156 | b.Property("TwoFactorEnabled") 157 | .HasColumnType("bit"); 158 | 159 | b.Property("UserName") 160 | .HasMaxLength(256) 161 | .HasColumnType("nvarchar(256)"); 162 | 163 | b.HasKey("Id"); 164 | 165 | b.HasIndex("NormalizedEmail") 166 | .HasDatabaseName("EmailIndex"); 167 | 168 | b.HasIndex("NormalizedUserName") 169 | .IsUnique() 170 | .HasDatabaseName("UserNameIndex") 171 | .HasFilter("[NormalizedUserName] IS NOT NULL"); 172 | 173 | b.ToTable("AspNetUsers", (string)null); 174 | 175 | b.HasDiscriminator().HasValue("IdentityUser"); 176 | 177 | b.UseTphMappingStrategy(); 178 | }); 179 | 180 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => 181 | { 182 | b.Property("Id") 183 | .ValueGeneratedOnAdd() 184 | .HasColumnType("int"); 185 | 186 | SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); 187 | 188 | b.Property("ClaimType") 189 | .HasColumnType("nvarchar(max)"); 190 | 191 | b.Property("ClaimValue") 192 | .HasColumnType("nvarchar(max)"); 193 | 194 | b.Property("UserId") 195 | .IsRequired() 196 | .HasColumnType("nvarchar(450)"); 197 | 198 | b.HasKey("Id"); 199 | 200 | b.HasIndex("UserId"); 201 | 202 | b.ToTable("AspNetUserClaims", (string)null); 203 | }); 204 | 205 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => 206 | { 207 | b.Property("LoginProvider") 208 | .HasColumnType("nvarchar(450)"); 209 | 210 | b.Property("ProviderKey") 211 | .HasColumnType("nvarchar(450)"); 212 | 213 | b.Property("ProviderDisplayName") 214 | .HasColumnType("nvarchar(max)"); 215 | 216 | b.Property("UserId") 217 | .IsRequired() 218 | .HasColumnType("nvarchar(450)"); 219 | 220 | b.HasKey("LoginProvider", "ProviderKey"); 221 | 222 | b.HasIndex("UserId"); 223 | 224 | b.ToTable("AspNetUserLogins", (string)null); 225 | }); 226 | 227 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => 228 | { 229 | b.Property("UserId") 230 | .HasColumnType("nvarchar(450)"); 231 | 232 | b.Property("RoleId") 233 | .HasColumnType("nvarchar(450)"); 234 | 235 | b.HasKey("UserId", "RoleId"); 236 | 237 | b.HasIndex("RoleId"); 238 | 239 | b.ToTable("AspNetUserRoles", (string)null); 240 | }); 241 | 242 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => 243 | { 244 | b.Property("UserId") 245 | .HasColumnType("nvarchar(450)"); 246 | 247 | b.Property("LoginProvider") 248 | .HasColumnType("nvarchar(450)"); 249 | 250 | b.Property("Name") 251 | .HasColumnType("nvarchar(450)"); 252 | 253 | b.Property("Value") 254 | .HasColumnType("nvarchar(max)"); 255 | 256 | b.HasKey("UserId", "LoginProvider", "Name"); 257 | 258 | b.ToTable("AspNetUserTokens", (string)null); 259 | }); 260 | 261 | modelBuilder.Entity("Models.Domain.ApplicationUser", b => 262 | { 263 | b.HasBaseType("Microsoft.AspNetCore.Identity.IdentityUser"); 264 | 265 | b.Property("ImageUrl") 266 | .IsRequired() 267 | .HasColumnType("nvarchar(max)"); 268 | 269 | b.Property("Name") 270 | .IsRequired() 271 | .HasColumnType("nvarchar(max)"); 272 | 273 | b.HasDiscriminator().HasValue("ApplicationUser"); 274 | }); 275 | 276 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => 277 | { 278 | b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) 279 | .WithMany() 280 | .HasForeignKey("RoleId") 281 | .OnDelete(DeleteBehavior.Cascade) 282 | .IsRequired(); 283 | }); 284 | 285 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => 286 | { 287 | b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) 288 | .WithMany() 289 | .HasForeignKey("UserId") 290 | .OnDelete(DeleteBehavior.Cascade) 291 | .IsRequired(); 292 | }); 293 | 294 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => 295 | { 296 | b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) 297 | .WithMany() 298 | .HasForeignKey("UserId") 299 | .OnDelete(DeleteBehavior.Cascade) 300 | .IsRequired(); 301 | }); 302 | 303 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => 304 | { 305 | b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) 306 | .WithMany() 307 | .HasForeignKey("RoleId") 308 | .OnDelete(DeleteBehavior.Cascade) 309 | .IsRequired(); 310 | 311 | b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) 312 | .WithMany() 313 | .HasForeignKey("UserId") 314 | .OnDelete(DeleteBehavior.Cascade) 315 | .IsRequired(); 316 | }); 317 | 318 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => 319 | { 320 | b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) 321 | .WithMany() 322 | .HasForeignKey("UserId") 323 | .OnDelete(DeleteBehavior.Cascade) 324 | .IsRequired(); 325 | }); 326 | #pragma warning restore 612, 618 327 | } 328 | } 329 | } 330 | -------------------------------------------------------------------------------- /DataAcess/Migrations/20250228210101_add imgUrl to user.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore.Migrations; 2 | 3 | #nullable disable 4 | 5 | #pragma warning disable CA1814 // Prefer jagged arrays over multidimensional 6 | 7 | namespace DataAcess.Migrations 8 | { 9 | /// 10 | public partial class addimgUrltouser : Migration 11 | { 12 | /// 13 | protected override void Up(MigrationBuilder migrationBuilder) 14 | { 15 | migrationBuilder.DeleteData( 16 | table: "AspNetRoles", 17 | keyColumn: "Id", 18 | keyValue: "new-role-id-1"); 19 | 20 | migrationBuilder.DeleteData( 21 | table: "AspNetRoles", 22 | keyColumn: "Id", 23 | keyValue: "new-role-id-2"); 24 | 25 | migrationBuilder.AddColumn( 26 | name: "ImageUrl", 27 | table: "AspNetUsers", 28 | type: "nvarchar(max)", 29 | nullable: true); 30 | 31 | migrationBuilder.InsertData( 32 | table: "AspNetRoles", 33 | columns: new[] { "Id", "ConcurrencyStamp", "Name", "NormalizedName" }, 34 | values: new object[,] 35 | { 36 | { "2b440d41-47fa-4fe5-ae96-b4ae34d223a1", null, "guest", "GUEST" }, 37 | { "5654533a-52b5-4e1e-b9e5-fd8036ef35ff", null, "manager", "MANAGER" } 38 | }); 39 | } 40 | 41 | /// 42 | protected override void Down(MigrationBuilder migrationBuilder) 43 | { 44 | migrationBuilder.DeleteData( 45 | table: "AspNetRoles", 46 | keyColumn: "Id", 47 | keyValue: "2b440d41-47fa-4fe5-ae96-b4ae34d223a1"); 48 | 49 | migrationBuilder.DeleteData( 50 | table: "AspNetRoles", 51 | keyColumn: "Id", 52 | keyValue: "5654533a-52b5-4e1e-b9e5-fd8036ef35ff"); 53 | 54 | migrationBuilder.DropColumn( 55 | name: "ImageUrl", 56 | table: "AspNetUsers"); 57 | 58 | migrationBuilder.InsertData( 59 | table: "AspNetRoles", 60 | columns: new[] { "Id", "ConcurrencyStamp", "Name", "NormalizedName" }, 61 | values: new object[,] 62 | { 63 | { "new-role-id-1", null, "manager", "MANAGER" }, 64 | { "new-role-id-2", null, "guest", "GUEST" } 65 | }); 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /DataAcess/Migrations/20250228220841_add image tbl and make fk to it In AppUsersTbl.Designer.cs: -------------------------------------------------------------------------------- 1 | // 2 | using System; 3 | using DataAcess; 4 | using Microsoft.EntityFrameworkCore; 5 | using Microsoft.EntityFrameworkCore.Infrastructure; 6 | using Microsoft.EntityFrameworkCore.Metadata; 7 | using Microsoft.EntityFrameworkCore.Migrations; 8 | using Microsoft.EntityFrameworkCore.Storage.ValueConversion; 9 | 10 | #nullable disable 11 | 12 | namespace DataAcess.Migrations 13 | { 14 | [DbContext(typeof(ApplicationDbContext))] 15 | [Migration("20250228220841_add image tbl and make fk to it In AppUsersTbl")] 16 | partial class addimagetblandmakefktoitInAppUsersTbl 17 | { 18 | /// 19 | protected override void BuildTargetModel(ModelBuilder modelBuilder) 20 | { 21 | #pragma warning disable 612, 618 22 | modelBuilder 23 | .HasAnnotation("ProductVersion", "9.0.2") 24 | .HasAnnotation("Relational:MaxIdentifierLength", 128); 25 | 26 | SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); 27 | 28 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => 29 | { 30 | b.Property("Id") 31 | .HasColumnType("nvarchar(450)"); 32 | 33 | b.Property("ConcurrencyStamp") 34 | .IsConcurrencyToken() 35 | .HasColumnType("nvarchar(max)"); 36 | 37 | b.Property("Name") 38 | .HasMaxLength(256) 39 | .HasColumnType("nvarchar(256)"); 40 | 41 | b.Property("NormalizedName") 42 | .HasMaxLength(256) 43 | .HasColumnType("nvarchar(256)"); 44 | 45 | b.HasKey("Id"); 46 | 47 | b.HasIndex("NormalizedName") 48 | .IsUnique() 49 | .HasDatabaseName("RoleNameIndex") 50 | .HasFilter("[NormalizedName] IS NOT NULL"); 51 | 52 | b.ToTable("AspNetRoles", (string)null); 53 | 54 | b.HasData( 55 | new 56 | { 57 | Id = "43d0590f-2f82-4867-83c4-18f0488f9706", 58 | Name = "admin", 59 | NormalizedName = "ADMIN" 60 | }, 61 | new 62 | { 63 | Id = "ff715d53-7725-48de-8d74-f064b8b41b45", 64 | Name = "user", 65 | NormalizedName = "USER" 66 | }, 67 | new 68 | { 69 | Id = "5654533a-52b5-4e1e-b9e5-fd8036ef35ff", 70 | Name = "manager", 71 | NormalizedName = "MANAGER" 72 | }, 73 | new 74 | { 75 | Id = "2b440d41-47fa-4fe5-ae96-b4ae34d223a1", 76 | Name = "guest", 77 | NormalizedName = "GUEST" 78 | }); 79 | }); 80 | 81 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => 82 | { 83 | b.Property("Id") 84 | .ValueGeneratedOnAdd() 85 | .HasColumnType("int"); 86 | 87 | SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); 88 | 89 | b.Property("ClaimType") 90 | .HasColumnType("nvarchar(max)"); 91 | 92 | b.Property("ClaimValue") 93 | .HasColumnType("nvarchar(max)"); 94 | 95 | b.Property("RoleId") 96 | .IsRequired() 97 | .HasColumnType("nvarchar(450)"); 98 | 99 | b.HasKey("Id"); 100 | 101 | b.HasIndex("RoleId"); 102 | 103 | b.ToTable("AspNetRoleClaims", (string)null); 104 | }); 105 | 106 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUser", b => 107 | { 108 | b.Property("Id") 109 | .HasColumnType("nvarchar(450)"); 110 | 111 | b.Property("AccessFailedCount") 112 | .HasColumnType("int"); 113 | 114 | b.Property("ConcurrencyStamp") 115 | .IsConcurrencyToken() 116 | .HasColumnType("nvarchar(max)"); 117 | 118 | b.Property("Discriminator") 119 | .IsRequired() 120 | .HasMaxLength(21) 121 | .HasColumnType("nvarchar(21)"); 122 | 123 | b.Property("Email") 124 | .HasMaxLength(256) 125 | .HasColumnType("nvarchar(256)"); 126 | 127 | b.Property("EmailConfirmed") 128 | .HasColumnType("bit"); 129 | 130 | b.Property("LockoutEnabled") 131 | .HasColumnType("bit"); 132 | 133 | b.Property("LockoutEnd") 134 | .HasColumnType("datetimeoffset"); 135 | 136 | b.Property("NormalizedEmail") 137 | .HasMaxLength(256) 138 | .HasColumnType("nvarchar(256)"); 139 | 140 | b.Property("NormalizedUserName") 141 | .HasMaxLength(256) 142 | .HasColumnType("nvarchar(256)"); 143 | 144 | b.Property("PasswordHash") 145 | .HasColumnType("nvarchar(max)"); 146 | 147 | b.Property("PhoneNumber") 148 | .HasColumnType("nvarchar(max)"); 149 | 150 | b.Property("PhoneNumberConfirmed") 151 | .HasColumnType("bit"); 152 | 153 | b.Property("SecurityStamp") 154 | .HasColumnType("nvarchar(max)"); 155 | 156 | b.Property("TwoFactorEnabled") 157 | .HasColumnType("bit"); 158 | 159 | b.Property("UserName") 160 | .HasMaxLength(256) 161 | .HasColumnType("nvarchar(256)"); 162 | 163 | b.HasKey("Id"); 164 | 165 | b.HasIndex("NormalizedEmail") 166 | .HasDatabaseName("EmailIndex"); 167 | 168 | b.HasIndex("NormalizedUserName") 169 | .IsUnique() 170 | .HasDatabaseName("UserNameIndex") 171 | .HasFilter("[NormalizedUserName] IS NOT NULL"); 172 | 173 | b.ToTable("AspNetUsers", (string)null); 174 | 175 | b.HasDiscriminator().HasValue("IdentityUser"); 176 | 177 | b.UseTphMappingStrategy(); 178 | }); 179 | 180 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => 181 | { 182 | b.Property("Id") 183 | .ValueGeneratedOnAdd() 184 | .HasColumnType("int"); 185 | 186 | SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); 187 | 188 | b.Property("ClaimType") 189 | .HasColumnType("nvarchar(max)"); 190 | 191 | b.Property("ClaimValue") 192 | .HasColumnType("nvarchar(max)"); 193 | 194 | b.Property("UserId") 195 | .IsRequired() 196 | .HasColumnType("nvarchar(450)"); 197 | 198 | b.HasKey("Id"); 199 | 200 | b.HasIndex("UserId"); 201 | 202 | b.ToTable("AspNetUserClaims", (string)null); 203 | }); 204 | 205 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => 206 | { 207 | b.Property("LoginProvider") 208 | .HasColumnType("nvarchar(450)"); 209 | 210 | b.Property("ProviderKey") 211 | .HasColumnType("nvarchar(450)"); 212 | 213 | b.Property("ProviderDisplayName") 214 | .HasColumnType("nvarchar(max)"); 215 | 216 | b.Property("UserId") 217 | .IsRequired() 218 | .HasColumnType("nvarchar(450)"); 219 | 220 | b.HasKey("LoginProvider", "ProviderKey"); 221 | 222 | b.HasIndex("UserId"); 223 | 224 | b.ToTable("AspNetUserLogins", (string)null); 225 | }); 226 | 227 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => 228 | { 229 | b.Property("UserId") 230 | .HasColumnType("nvarchar(450)"); 231 | 232 | b.Property("RoleId") 233 | .HasColumnType("nvarchar(450)"); 234 | 235 | b.HasKey("UserId", "RoleId"); 236 | 237 | b.HasIndex("RoleId"); 238 | 239 | b.ToTable("AspNetUserRoles", (string)null); 240 | }); 241 | 242 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => 243 | { 244 | b.Property("UserId") 245 | .HasColumnType("nvarchar(450)"); 246 | 247 | b.Property("LoginProvider") 248 | .HasColumnType("nvarchar(450)"); 249 | 250 | b.Property("Name") 251 | .HasColumnType("nvarchar(450)"); 252 | 253 | b.Property("Value") 254 | .HasColumnType("nvarchar(max)"); 255 | 256 | b.HasKey("UserId", "LoginProvider", "Name"); 257 | 258 | b.ToTable("AspNetUserTokens", (string)null); 259 | }); 260 | 261 | modelBuilder.Entity("Models.Domain.Image", b => 262 | { 263 | b.Property("Id") 264 | .ValueGeneratedOnAdd() 265 | .HasColumnType("int"); 266 | 267 | SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); 268 | 269 | b.Property("FileExtension") 270 | .IsRequired() 271 | .HasColumnType("nvarchar(max)"); 272 | 273 | b.Property("FileName") 274 | .IsRequired() 275 | .HasColumnType("nvarchar(max)"); 276 | 277 | b.Property("FilePath") 278 | .IsRequired() 279 | .HasColumnType("nvarchar(max)"); 280 | 281 | b.Property("FileSize") 282 | .HasColumnType("bigint"); 283 | 284 | b.HasKey("Id"); 285 | 286 | b.ToTable("Image"); 287 | }); 288 | 289 | modelBuilder.Entity("Models.Domain.ApplicationUser", b => 290 | { 291 | b.HasBaseType("Microsoft.AspNetCore.Identity.IdentityUser"); 292 | 293 | b.Property("ImageId") 294 | .HasColumnType("int"); 295 | 296 | b.Property("Name") 297 | .IsRequired() 298 | .HasColumnType("nvarchar(max)"); 299 | 300 | b.HasIndex("ImageId"); 301 | 302 | b.HasDiscriminator().HasValue("ApplicationUser"); 303 | }); 304 | 305 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => 306 | { 307 | b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) 308 | .WithMany() 309 | .HasForeignKey("RoleId") 310 | .OnDelete(DeleteBehavior.Cascade) 311 | .IsRequired(); 312 | }); 313 | 314 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => 315 | { 316 | b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) 317 | .WithMany() 318 | .HasForeignKey("UserId") 319 | .OnDelete(DeleteBehavior.Cascade) 320 | .IsRequired(); 321 | }); 322 | 323 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => 324 | { 325 | b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) 326 | .WithMany() 327 | .HasForeignKey("UserId") 328 | .OnDelete(DeleteBehavior.Cascade) 329 | .IsRequired(); 330 | }); 331 | 332 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => 333 | { 334 | b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) 335 | .WithMany() 336 | .HasForeignKey("RoleId") 337 | .OnDelete(DeleteBehavior.Cascade) 338 | .IsRequired(); 339 | 340 | b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) 341 | .WithMany() 342 | .HasForeignKey("UserId") 343 | .OnDelete(DeleteBehavior.Cascade) 344 | .IsRequired(); 345 | }); 346 | 347 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => 348 | { 349 | b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) 350 | .WithMany() 351 | .HasForeignKey("UserId") 352 | .OnDelete(DeleteBehavior.Cascade) 353 | .IsRequired(); 354 | }); 355 | 356 | modelBuilder.Entity("Models.Domain.ApplicationUser", b => 357 | { 358 | b.HasOne("Models.Domain.Image", "Image") 359 | .WithMany() 360 | .HasForeignKey("ImageId") 361 | .OnDelete(DeleteBehavior.Cascade) 362 | .IsRequired(); 363 | 364 | b.Navigation("Image"); 365 | }); 366 | #pragma warning restore 612, 618 367 | } 368 | } 369 | } 370 | -------------------------------------------------------------------------------- /DataAcess/Migrations/20250228220841_add image tbl and make fk to it In AppUsersTbl.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore.Migrations; 2 | 3 | #nullable disable 4 | 5 | namespace DataAcess.Migrations 6 | { 7 | /// 8 | public partial class addimagetblandmakefktoitInAppUsersTbl : Migration 9 | { 10 | /// 11 | protected override void Up(MigrationBuilder migrationBuilder) 12 | { 13 | migrationBuilder.DropColumn( 14 | name: "ImageUrl", 15 | table: "AspNetUsers"); 16 | 17 | migrationBuilder.AddColumn( 18 | name: "ImageId", 19 | table: "AspNetUsers", 20 | type: "int", 21 | nullable: true); 22 | 23 | migrationBuilder.CreateTable( 24 | name: "Image", 25 | columns: table => new 26 | { 27 | Id = table.Column(type: "int", nullable: false) 28 | .Annotation("SqlServer:Identity", "1, 1"), 29 | FileName = table.Column(type: "nvarchar(max)", nullable: false), 30 | FileExtension = table.Column(type: "nvarchar(max)", nullable: false), 31 | FileSize = table.Column(type: "bigint", nullable: false), 32 | FilePath = table.Column(type: "nvarchar(max)", nullable: false) 33 | }, 34 | constraints: table => 35 | { 36 | table.PrimaryKey("PK_Image", x => x.Id); 37 | }); 38 | 39 | migrationBuilder.CreateIndex( 40 | name: "IX_AspNetUsers_ImageId", 41 | table: "AspNetUsers", 42 | column: "ImageId"); 43 | 44 | migrationBuilder.AddForeignKey( 45 | name: "FK_AspNetUsers_Image_ImageId", 46 | table: "AspNetUsers", 47 | column: "ImageId", 48 | principalTable: "Image", 49 | principalColumn: "Id", 50 | onDelete: ReferentialAction.Cascade); 51 | } 52 | 53 | /// 54 | protected override void Down(MigrationBuilder migrationBuilder) 55 | { 56 | migrationBuilder.DropForeignKey( 57 | name: "FK_AspNetUsers_Image_ImageId", 58 | table: "AspNetUsers"); 59 | 60 | migrationBuilder.DropTable( 61 | name: "Image"); 62 | 63 | migrationBuilder.DropIndex( 64 | name: "IX_AspNetUsers_ImageId", 65 | table: "AspNetUsers"); 66 | 67 | migrationBuilder.DropColumn( 68 | name: "ImageId", 69 | table: "AspNetUsers"); 70 | 71 | migrationBuilder.AddColumn( 72 | name: "ImageUrl", 73 | table: "AspNetUsers", 74 | type: "nvarchar(max)", 75 | nullable: true); 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /DataAcess/Migrations/20250306171257_FkBtwImgAndUser.Designer.cs: -------------------------------------------------------------------------------- 1 | // 2 | using System; 3 | using DataAcess; 4 | using Microsoft.EntityFrameworkCore; 5 | using Microsoft.EntityFrameworkCore.Infrastructure; 6 | using Microsoft.EntityFrameworkCore.Metadata; 7 | using Microsoft.EntityFrameworkCore.Migrations; 8 | using Microsoft.EntityFrameworkCore.Storage.ValueConversion; 9 | 10 | #nullable disable 11 | 12 | namespace DataAcess.Migrations 13 | { 14 | [DbContext(typeof(ApplicationDbContext))] 15 | [Migration("20250306171257_FkBtwImgAndUser")] 16 | partial class FkBtwImgAndUser 17 | { 18 | /// 19 | protected override void BuildTargetModel(ModelBuilder modelBuilder) 20 | { 21 | #pragma warning disable 612, 618 22 | modelBuilder 23 | .HasAnnotation("ProductVersion", "9.0.2") 24 | .HasAnnotation("Relational:MaxIdentifierLength", 128); 25 | 26 | SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); 27 | 28 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => 29 | { 30 | b.Property("Id") 31 | .HasColumnType("nvarchar(450)"); 32 | 33 | b.Property("ConcurrencyStamp") 34 | .IsConcurrencyToken() 35 | .HasColumnType("nvarchar(max)"); 36 | 37 | b.Property("Name") 38 | .HasMaxLength(256) 39 | .HasColumnType("nvarchar(256)"); 40 | 41 | b.Property("NormalizedName") 42 | .HasMaxLength(256) 43 | .HasColumnType("nvarchar(256)"); 44 | 45 | b.HasKey("Id"); 46 | 47 | b.HasIndex("NormalizedName") 48 | .IsUnique() 49 | .HasDatabaseName("RoleNameIndex") 50 | .HasFilter("[NormalizedName] IS NOT NULL"); 51 | 52 | b.ToTable("AspNetRoles", (string)null); 53 | 54 | b.HasData( 55 | new 56 | { 57 | Id = "43d0590f-2f82-4867-83c4-18f0488f9706", 58 | Name = "admin", 59 | NormalizedName = "ADMIN" 60 | }, 61 | new 62 | { 63 | Id = "ff715d53-7725-48de-8d74-f064b8b41b45", 64 | Name = "user", 65 | NormalizedName = "USER" 66 | }, 67 | new 68 | { 69 | Id = "5654533a-52b5-4e1e-b9e5-fd8036ef35ff", 70 | Name = "manager", 71 | NormalizedName = "MANAGER" 72 | }, 73 | new 74 | { 75 | Id = "2b440d41-47fa-4fe5-ae96-b4ae34d223a1", 76 | Name = "guest", 77 | NormalizedName = "GUEST" 78 | }); 79 | }); 80 | 81 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => 82 | { 83 | b.Property("Id") 84 | .ValueGeneratedOnAdd() 85 | .HasColumnType("int"); 86 | 87 | SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); 88 | 89 | b.Property("ClaimType") 90 | .HasColumnType("nvarchar(max)"); 91 | 92 | b.Property("ClaimValue") 93 | .HasColumnType("nvarchar(max)"); 94 | 95 | b.Property("RoleId") 96 | .IsRequired() 97 | .HasColumnType("nvarchar(450)"); 98 | 99 | b.HasKey("Id"); 100 | 101 | b.HasIndex("RoleId"); 102 | 103 | b.ToTable("AspNetRoleClaims", (string)null); 104 | }); 105 | 106 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUser", b => 107 | { 108 | b.Property("Id") 109 | .HasColumnType("nvarchar(450)"); 110 | 111 | b.Property("AccessFailedCount") 112 | .HasColumnType("int"); 113 | 114 | b.Property("ConcurrencyStamp") 115 | .IsConcurrencyToken() 116 | .HasColumnType("nvarchar(max)"); 117 | 118 | b.Property("Discriminator") 119 | .IsRequired() 120 | .HasMaxLength(21) 121 | .HasColumnType("nvarchar(21)"); 122 | 123 | b.Property("Email") 124 | .HasMaxLength(256) 125 | .HasColumnType("nvarchar(256)"); 126 | 127 | b.Property("EmailConfirmed") 128 | .HasColumnType("bit"); 129 | 130 | b.Property("LockoutEnabled") 131 | .HasColumnType("bit"); 132 | 133 | b.Property("LockoutEnd") 134 | .HasColumnType("datetimeoffset"); 135 | 136 | b.Property("NormalizedEmail") 137 | .HasMaxLength(256) 138 | .HasColumnType("nvarchar(256)"); 139 | 140 | b.Property("NormalizedUserName") 141 | .HasMaxLength(256) 142 | .HasColumnType("nvarchar(256)"); 143 | 144 | b.Property("PasswordHash") 145 | .HasColumnType("nvarchar(max)"); 146 | 147 | b.Property("PhoneNumber") 148 | .HasColumnType("nvarchar(max)"); 149 | 150 | b.Property("PhoneNumberConfirmed") 151 | .HasColumnType("bit"); 152 | 153 | b.Property("SecurityStamp") 154 | .HasColumnType("nvarchar(max)"); 155 | 156 | b.Property("TwoFactorEnabled") 157 | .HasColumnType("bit"); 158 | 159 | b.Property("UserName") 160 | .HasMaxLength(256) 161 | .HasColumnType("nvarchar(256)"); 162 | 163 | b.HasKey("Id"); 164 | 165 | b.HasIndex("NormalizedEmail") 166 | .HasDatabaseName("EmailIndex"); 167 | 168 | b.HasIndex("NormalizedUserName") 169 | .IsUnique() 170 | .HasDatabaseName("UserNameIndex") 171 | .HasFilter("[NormalizedUserName] IS NOT NULL"); 172 | 173 | b.ToTable("AspNetUsers", (string)null); 174 | 175 | b.HasDiscriminator().HasValue("IdentityUser"); 176 | 177 | b.UseTphMappingStrategy(); 178 | }); 179 | 180 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => 181 | { 182 | b.Property("Id") 183 | .ValueGeneratedOnAdd() 184 | .HasColumnType("int"); 185 | 186 | SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); 187 | 188 | b.Property("ClaimType") 189 | .HasColumnType("nvarchar(max)"); 190 | 191 | b.Property("ClaimValue") 192 | .HasColumnType("nvarchar(max)"); 193 | 194 | b.Property("UserId") 195 | .IsRequired() 196 | .HasColumnType("nvarchar(450)"); 197 | 198 | b.HasKey("Id"); 199 | 200 | b.HasIndex("UserId"); 201 | 202 | b.ToTable("AspNetUserClaims", (string)null); 203 | }); 204 | 205 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => 206 | { 207 | b.Property("LoginProvider") 208 | .HasColumnType("nvarchar(450)"); 209 | 210 | b.Property("ProviderKey") 211 | .HasColumnType("nvarchar(450)"); 212 | 213 | b.Property("ProviderDisplayName") 214 | .HasColumnType("nvarchar(max)"); 215 | 216 | b.Property("UserId") 217 | .IsRequired() 218 | .HasColumnType("nvarchar(450)"); 219 | 220 | b.HasKey("LoginProvider", "ProviderKey"); 221 | 222 | b.HasIndex("UserId"); 223 | 224 | b.ToTable("AspNetUserLogins", (string)null); 225 | }); 226 | 227 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => 228 | { 229 | b.Property("UserId") 230 | .HasColumnType("nvarchar(450)"); 231 | 232 | b.Property("RoleId") 233 | .HasColumnType("nvarchar(450)"); 234 | 235 | b.HasKey("UserId", "RoleId"); 236 | 237 | b.HasIndex("RoleId"); 238 | 239 | b.ToTable("AspNetUserRoles", (string)null); 240 | }); 241 | 242 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => 243 | { 244 | b.Property("UserId") 245 | .HasColumnType("nvarchar(450)"); 246 | 247 | b.Property("LoginProvider") 248 | .HasColumnType("nvarchar(450)"); 249 | 250 | b.Property("Name") 251 | .HasColumnType("nvarchar(450)"); 252 | 253 | b.Property("Value") 254 | .HasColumnType("nvarchar(max)"); 255 | 256 | b.HasKey("UserId", "LoginProvider", "Name"); 257 | 258 | b.ToTable("AspNetUserTokens", (string)null); 259 | }); 260 | 261 | modelBuilder.Entity("Models.Domain.Image", b => 262 | { 263 | b.Property("Id") 264 | .ValueGeneratedOnAdd() 265 | .HasColumnType("int"); 266 | 267 | SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); 268 | 269 | b.Property("FileExtension") 270 | .IsRequired() 271 | .HasColumnType("nvarchar(max)"); 272 | 273 | b.Property("FileName") 274 | .IsRequired() 275 | .HasColumnType("nvarchar(max)"); 276 | 277 | b.Property("FilePath") 278 | .IsRequired() 279 | .HasColumnType("nvarchar(max)"); 280 | 281 | b.Property("FileSize") 282 | .HasColumnType("bigint"); 283 | 284 | b.HasKey("Id"); 285 | 286 | b.ToTable("Image"); 287 | }); 288 | 289 | modelBuilder.Entity("Models.Domain.ApplicationUser", b => 290 | { 291 | b.HasBaseType("Microsoft.AspNetCore.Identity.IdentityUser"); 292 | 293 | b.Property("ImageId") 294 | .HasColumnType("int"); 295 | 296 | b.Property("Name") 297 | .IsRequired() 298 | .HasColumnType("nvarchar(max)"); 299 | 300 | b.HasIndex("ImageId") 301 | .IsUnique() 302 | .HasFilter("[ImageId] IS NOT NULL"); 303 | 304 | b.HasDiscriminator().HasValue("ApplicationUser"); 305 | }); 306 | 307 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => 308 | { 309 | b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) 310 | .WithMany() 311 | .HasForeignKey("RoleId") 312 | .OnDelete(DeleteBehavior.Cascade) 313 | .IsRequired(); 314 | }); 315 | 316 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => 317 | { 318 | b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) 319 | .WithMany() 320 | .HasForeignKey("UserId") 321 | .OnDelete(DeleteBehavior.Cascade) 322 | .IsRequired(); 323 | }); 324 | 325 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => 326 | { 327 | b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) 328 | .WithMany() 329 | .HasForeignKey("UserId") 330 | .OnDelete(DeleteBehavior.Cascade) 331 | .IsRequired(); 332 | }); 333 | 334 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => 335 | { 336 | b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) 337 | .WithMany() 338 | .HasForeignKey("RoleId") 339 | .OnDelete(DeleteBehavior.Cascade) 340 | .IsRequired(); 341 | 342 | b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) 343 | .WithMany() 344 | .HasForeignKey("UserId") 345 | .OnDelete(DeleteBehavior.Cascade) 346 | .IsRequired(); 347 | }); 348 | 349 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => 350 | { 351 | b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) 352 | .WithMany() 353 | .HasForeignKey("UserId") 354 | .OnDelete(DeleteBehavior.Cascade) 355 | .IsRequired(); 356 | }); 357 | 358 | modelBuilder.Entity("Models.Domain.ApplicationUser", b => 359 | { 360 | b.HasOne("Models.Domain.Image", "Image") 361 | .WithOne("User") 362 | .HasForeignKey("Models.Domain.ApplicationUser", "ImageId") 363 | .OnDelete(DeleteBehavior.SetNull); 364 | 365 | b.Navigation("Image"); 366 | }); 367 | 368 | modelBuilder.Entity("Models.Domain.Image", b => 369 | { 370 | b.Navigation("User") 371 | .IsRequired(); 372 | }); 373 | #pragma warning restore 612, 618 374 | } 375 | } 376 | } 377 | -------------------------------------------------------------------------------- /DataAcess/Migrations/20250306171257_FkBtwImgAndUser.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore.Migrations; 2 | 3 | #nullable disable 4 | 5 | namespace DataAcess.Migrations 6 | { 7 | /// 8 | public partial class FkBtwImgAndUser : Migration 9 | { 10 | /// 11 | protected override void Up(MigrationBuilder migrationBuilder) 12 | { 13 | migrationBuilder.DropForeignKey( 14 | name: "FK_AspNetUsers_Image_ImageId", 15 | table: "AspNetUsers"); 16 | 17 | migrationBuilder.DropIndex( 18 | name: "IX_AspNetUsers_ImageId", 19 | table: "AspNetUsers"); 20 | 21 | migrationBuilder.CreateIndex( 22 | name: "IX_AspNetUsers_ImageId", 23 | table: "AspNetUsers", 24 | column: "ImageId", 25 | unique: true, 26 | filter: "[ImageId] IS NOT NULL"); 27 | 28 | migrationBuilder.AddForeignKey( 29 | name: "FK_AspNetUsers_Image_ImageId", 30 | table: "AspNetUsers", 31 | column: "ImageId", 32 | principalTable: "Image", 33 | principalColumn: "Id", 34 | onDelete: ReferentialAction.SetNull); 35 | } 36 | 37 | /// 38 | protected override void Down(MigrationBuilder migrationBuilder) 39 | { 40 | migrationBuilder.DropForeignKey( 41 | name: "FK_AspNetUsers_Image_ImageId", 42 | table: "AspNetUsers"); 43 | 44 | migrationBuilder.DropIndex( 45 | name: "IX_AspNetUsers_ImageId", 46 | table: "AspNetUsers"); 47 | 48 | migrationBuilder.CreateIndex( 49 | name: "IX_AspNetUsers_ImageId", 50 | table: "AspNetUsers", 51 | column: "ImageId"); 52 | 53 | migrationBuilder.AddForeignKey( 54 | name: "FK_AspNetUsers_Image_ImageId", 55 | table: "AspNetUsers", 56 | column: "ImageId", 57 | principalTable: "Image", 58 | principalColumn: "Id", 59 | onDelete: ReferentialAction.Cascade); 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /DataAcess/Migrations/20250306173147_FkBtwImgAndUserupdateNoCycle.Designer.cs: -------------------------------------------------------------------------------- 1 | // 2 | using System; 3 | using DataAcess; 4 | using Microsoft.EntityFrameworkCore; 5 | using Microsoft.EntityFrameworkCore.Infrastructure; 6 | using Microsoft.EntityFrameworkCore.Metadata; 7 | using Microsoft.EntityFrameworkCore.Migrations; 8 | using Microsoft.EntityFrameworkCore.Storage.ValueConversion; 9 | 10 | #nullable disable 11 | 12 | namespace DataAcess.Migrations 13 | { 14 | [DbContext(typeof(ApplicationDbContext))] 15 | [Migration("20250306173147_FkBtwImgAndUserupdateNoCycle")] 16 | partial class FkBtwImgAndUserupdateNoCycle 17 | { 18 | /// 19 | protected override void BuildTargetModel(ModelBuilder modelBuilder) 20 | { 21 | #pragma warning disable 612, 618 22 | modelBuilder 23 | .HasAnnotation("ProductVersion", "9.0.2") 24 | .HasAnnotation("Relational:MaxIdentifierLength", 128); 25 | 26 | SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); 27 | 28 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => 29 | { 30 | b.Property("Id") 31 | .HasColumnType("nvarchar(450)"); 32 | 33 | b.Property("ConcurrencyStamp") 34 | .IsConcurrencyToken() 35 | .HasColumnType("nvarchar(max)"); 36 | 37 | b.Property("Name") 38 | .HasMaxLength(256) 39 | .HasColumnType("nvarchar(256)"); 40 | 41 | b.Property("NormalizedName") 42 | .HasMaxLength(256) 43 | .HasColumnType("nvarchar(256)"); 44 | 45 | b.HasKey("Id"); 46 | 47 | b.HasIndex("NormalizedName") 48 | .IsUnique() 49 | .HasDatabaseName("RoleNameIndex") 50 | .HasFilter("[NormalizedName] IS NOT NULL"); 51 | 52 | b.ToTable("AspNetRoles", (string)null); 53 | 54 | b.HasData( 55 | new 56 | { 57 | Id = "43d0590f-2f82-4867-83c4-18f0488f9706", 58 | Name = "admin", 59 | NormalizedName = "ADMIN" 60 | }, 61 | new 62 | { 63 | Id = "ff715d53-7725-48de-8d74-f064b8b41b45", 64 | Name = "user", 65 | NormalizedName = "USER" 66 | }, 67 | new 68 | { 69 | Id = "5654533a-52b5-4e1e-b9e5-fd8036ef35ff", 70 | Name = "manager", 71 | NormalizedName = "MANAGER" 72 | }, 73 | new 74 | { 75 | Id = "2b440d41-47fa-4fe5-ae96-b4ae34d223a1", 76 | Name = "guest", 77 | NormalizedName = "GUEST" 78 | }); 79 | }); 80 | 81 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => 82 | { 83 | b.Property("Id") 84 | .ValueGeneratedOnAdd() 85 | .HasColumnType("int"); 86 | 87 | SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); 88 | 89 | b.Property("ClaimType") 90 | .HasColumnType("nvarchar(max)"); 91 | 92 | b.Property("ClaimValue") 93 | .HasColumnType("nvarchar(max)"); 94 | 95 | b.Property("RoleId") 96 | .IsRequired() 97 | .HasColumnType("nvarchar(450)"); 98 | 99 | b.HasKey("Id"); 100 | 101 | b.HasIndex("RoleId"); 102 | 103 | b.ToTable("AspNetRoleClaims", (string)null); 104 | }); 105 | 106 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUser", b => 107 | { 108 | b.Property("Id") 109 | .HasColumnType("nvarchar(450)"); 110 | 111 | b.Property("AccessFailedCount") 112 | .HasColumnType("int"); 113 | 114 | b.Property("ConcurrencyStamp") 115 | .IsConcurrencyToken() 116 | .HasColumnType("nvarchar(max)"); 117 | 118 | b.Property("Discriminator") 119 | .IsRequired() 120 | .HasMaxLength(21) 121 | .HasColumnType("nvarchar(21)"); 122 | 123 | b.Property("Email") 124 | .HasMaxLength(256) 125 | .HasColumnType("nvarchar(256)"); 126 | 127 | b.Property("EmailConfirmed") 128 | .HasColumnType("bit"); 129 | 130 | b.Property("LockoutEnabled") 131 | .HasColumnType("bit"); 132 | 133 | b.Property("LockoutEnd") 134 | .HasColumnType("datetimeoffset"); 135 | 136 | b.Property("NormalizedEmail") 137 | .HasMaxLength(256) 138 | .HasColumnType("nvarchar(256)"); 139 | 140 | b.Property("NormalizedUserName") 141 | .HasMaxLength(256) 142 | .HasColumnType("nvarchar(256)"); 143 | 144 | b.Property("PasswordHash") 145 | .HasColumnType("nvarchar(max)"); 146 | 147 | b.Property("PhoneNumber") 148 | .HasColumnType("nvarchar(max)"); 149 | 150 | b.Property("PhoneNumberConfirmed") 151 | .HasColumnType("bit"); 152 | 153 | b.Property("SecurityStamp") 154 | .HasColumnType("nvarchar(max)"); 155 | 156 | b.Property("TwoFactorEnabled") 157 | .HasColumnType("bit"); 158 | 159 | b.Property("UserName") 160 | .HasMaxLength(256) 161 | .HasColumnType("nvarchar(256)"); 162 | 163 | b.HasKey("Id"); 164 | 165 | b.HasIndex("NormalizedEmail") 166 | .HasDatabaseName("EmailIndex"); 167 | 168 | b.HasIndex("NormalizedUserName") 169 | .IsUnique() 170 | .HasDatabaseName("UserNameIndex") 171 | .HasFilter("[NormalizedUserName] IS NOT NULL"); 172 | 173 | b.ToTable("AspNetUsers", (string)null); 174 | 175 | b.HasDiscriminator().HasValue("IdentityUser"); 176 | 177 | b.UseTphMappingStrategy(); 178 | }); 179 | 180 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => 181 | { 182 | b.Property("Id") 183 | .ValueGeneratedOnAdd() 184 | .HasColumnType("int"); 185 | 186 | SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); 187 | 188 | b.Property("ClaimType") 189 | .HasColumnType("nvarchar(max)"); 190 | 191 | b.Property("ClaimValue") 192 | .HasColumnType("nvarchar(max)"); 193 | 194 | b.Property("UserId") 195 | .IsRequired() 196 | .HasColumnType("nvarchar(450)"); 197 | 198 | b.HasKey("Id"); 199 | 200 | b.HasIndex("UserId"); 201 | 202 | b.ToTable("AspNetUserClaims", (string)null); 203 | }); 204 | 205 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => 206 | { 207 | b.Property("LoginProvider") 208 | .HasColumnType("nvarchar(450)"); 209 | 210 | b.Property("ProviderKey") 211 | .HasColumnType("nvarchar(450)"); 212 | 213 | b.Property("ProviderDisplayName") 214 | .HasColumnType("nvarchar(max)"); 215 | 216 | b.Property("UserId") 217 | .IsRequired() 218 | .HasColumnType("nvarchar(450)"); 219 | 220 | b.HasKey("LoginProvider", "ProviderKey"); 221 | 222 | b.HasIndex("UserId"); 223 | 224 | b.ToTable("AspNetUserLogins", (string)null); 225 | }); 226 | 227 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => 228 | { 229 | b.Property("UserId") 230 | .HasColumnType("nvarchar(450)"); 231 | 232 | b.Property("RoleId") 233 | .HasColumnType("nvarchar(450)"); 234 | 235 | b.HasKey("UserId", "RoleId"); 236 | 237 | b.HasIndex("RoleId"); 238 | 239 | b.ToTable("AspNetUserRoles", (string)null); 240 | }); 241 | 242 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => 243 | { 244 | b.Property("UserId") 245 | .HasColumnType("nvarchar(450)"); 246 | 247 | b.Property("LoginProvider") 248 | .HasColumnType("nvarchar(450)"); 249 | 250 | b.Property("Name") 251 | .HasColumnType("nvarchar(450)"); 252 | 253 | b.Property("Value") 254 | .HasColumnType("nvarchar(max)"); 255 | 256 | b.HasKey("UserId", "LoginProvider", "Name"); 257 | 258 | b.ToTable("AspNetUserTokens", (string)null); 259 | }); 260 | 261 | modelBuilder.Entity("Models.Domain.Image", b => 262 | { 263 | b.Property("Id") 264 | .ValueGeneratedOnAdd() 265 | .HasColumnType("int"); 266 | 267 | SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); 268 | 269 | b.Property("FileExtension") 270 | .IsRequired() 271 | .HasColumnType("nvarchar(max)"); 272 | 273 | b.Property("FileName") 274 | .IsRequired() 275 | .HasColumnType("nvarchar(max)"); 276 | 277 | b.Property("FilePath") 278 | .IsRequired() 279 | .HasColumnType("nvarchar(max)"); 280 | 281 | b.Property("FileSize") 282 | .HasColumnType("bigint"); 283 | 284 | b.HasKey("Id"); 285 | 286 | b.ToTable("Image"); 287 | }); 288 | 289 | modelBuilder.Entity("Models.Domain.ApplicationUser", b => 290 | { 291 | b.HasBaseType("Microsoft.AspNetCore.Identity.IdentityUser"); 292 | 293 | b.Property("ImageId") 294 | .HasColumnType("int"); 295 | 296 | b.Property("Name") 297 | .IsRequired() 298 | .HasColumnType("nvarchar(max)"); 299 | 300 | b.HasIndex("ImageId"); 301 | 302 | b.HasDiscriminator().HasValue("ApplicationUser"); 303 | }); 304 | 305 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => 306 | { 307 | b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) 308 | .WithMany() 309 | .HasForeignKey("RoleId") 310 | .OnDelete(DeleteBehavior.Cascade) 311 | .IsRequired(); 312 | }); 313 | 314 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => 315 | { 316 | b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) 317 | .WithMany() 318 | .HasForeignKey("UserId") 319 | .OnDelete(DeleteBehavior.Cascade) 320 | .IsRequired(); 321 | }); 322 | 323 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => 324 | { 325 | b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) 326 | .WithMany() 327 | .HasForeignKey("UserId") 328 | .OnDelete(DeleteBehavior.Cascade) 329 | .IsRequired(); 330 | }); 331 | 332 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => 333 | { 334 | b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) 335 | .WithMany() 336 | .HasForeignKey("RoleId") 337 | .OnDelete(DeleteBehavior.Cascade) 338 | .IsRequired(); 339 | 340 | b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) 341 | .WithMany() 342 | .HasForeignKey("UserId") 343 | .OnDelete(DeleteBehavior.Cascade) 344 | .IsRequired(); 345 | }); 346 | 347 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => 348 | { 349 | b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) 350 | .WithMany() 351 | .HasForeignKey("UserId") 352 | .OnDelete(DeleteBehavior.Cascade) 353 | .IsRequired(); 354 | }); 355 | 356 | modelBuilder.Entity("Models.Domain.ApplicationUser", b => 357 | { 358 | b.HasOne("Models.Domain.Image", "Image") 359 | .WithMany() 360 | .HasForeignKey("ImageId"); 361 | 362 | b.Navigation("Image"); 363 | }); 364 | #pragma warning restore 612, 618 365 | } 366 | } 367 | } 368 | -------------------------------------------------------------------------------- /DataAcess/Migrations/20250306173147_FkBtwImgAndUserupdateNoCycle.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore.Migrations; 2 | 3 | #nullable disable 4 | 5 | namespace DataAcess.Migrations 6 | { 7 | /// 8 | public partial class FkBtwImgAndUserupdateNoCycle : Migration 9 | { 10 | /// 11 | protected override void Up(MigrationBuilder migrationBuilder) 12 | { 13 | migrationBuilder.DropForeignKey( 14 | name: "FK_AspNetUsers_Image_ImageId", 15 | table: "AspNetUsers"); 16 | 17 | migrationBuilder.DropIndex( 18 | name: "IX_AspNetUsers_ImageId", 19 | table: "AspNetUsers"); 20 | 21 | migrationBuilder.CreateIndex( 22 | name: "IX_AspNetUsers_ImageId", 23 | table: "AspNetUsers", 24 | column: "ImageId"); 25 | 26 | migrationBuilder.AddForeignKey( 27 | name: "FK_AspNetUsers_Image_ImageId", 28 | table: "AspNetUsers", 29 | column: "ImageId", 30 | principalTable: "Image", 31 | principalColumn: "Id"); 32 | } 33 | 34 | /// 35 | protected override void Down(MigrationBuilder migrationBuilder) 36 | { 37 | migrationBuilder.DropForeignKey( 38 | name: "FK_AspNetUsers_Image_ImageId", 39 | table: "AspNetUsers"); 40 | 41 | migrationBuilder.DropIndex( 42 | name: "IX_AspNetUsers_ImageId", 43 | table: "AspNetUsers"); 44 | 45 | migrationBuilder.CreateIndex( 46 | name: "IX_AspNetUsers_ImageId", 47 | table: "AspNetUsers", 48 | column: "ImageId", 49 | unique: true, 50 | filter: "[ImageId] IS NOT NULL"); 51 | 52 | migrationBuilder.AddForeignKey( 53 | name: "FK_AspNetUsers_Image_ImageId", 54 | table: "AspNetUsers", 55 | column: "ImageId", 56 | principalTable: "Image", 57 | principalColumn: "Id", 58 | onDelete: ReferentialAction.SetNull); 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /DataAcess/Migrations/ApplicationDbContextModelSnapshot.cs: -------------------------------------------------------------------------------- 1 | // 2 | using System; 3 | using DataAcess; 4 | using Microsoft.EntityFrameworkCore; 5 | using Microsoft.EntityFrameworkCore.Infrastructure; 6 | using Microsoft.EntityFrameworkCore.Metadata; 7 | using Microsoft.EntityFrameworkCore.Storage.ValueConversion; 8 | 9 | #nullable disable 10 | 11 | namespace DataAcess.Migrations 12 | { 13 | [DbContext(typeof(ApplicationDbContext))] 14 | partial class ApplicationDbContextModelSnapshot : ModelSnapshot 15 | { 16 | protected override void BuildModel(ModelBuilder modelBuilder) 17 | { 18 | #pragma warning disable 612, 618 19 | modelBuilder 20 | .HasAnnotation("ProductVersion", "9.0.2") 21 | .HasAnnotation("Relational:MaxIdentifierLength", 128); 22 | 23 | SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); 24 | 25 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => 26 | { 27 | b.Property("Id") 28 | .HasColumnType("nvarchar(450)"); 29 | 30 | b.Property("ConcurrencyStamp") 31 | .IsConcurrencyToken() 32 | .HasColumnType("nvarchar(max)"); 33 | 34 | b.Property("Name") 35 | .HasMaxLength(256) 36 | .HasColumnType("nvarchar(256)"); 37 | 38 | b.Property("NormalizedName") 39 | .HasMaxLength(256) 40 | .HasColumnType("nvarchar(256)"); 41 | 42 | b.HasKey("Id"); 43 | 44 | b.HasIndex("NormalizedName") 45 | .IsUnique() 46 | .HasDatabaseName("RoleNameIndex") 47 | .HasFilter("[NormalizedName] IS NOT NULL"); 48 | 49 | b.ToTable("AspNetRoles", (string)null); 50 | 51 | b.HasData( 52 | new 53 | { 54 | Id = "43d0590f-2f82-4867-83c4-18f0488f9706", 55 | Name = "admin", 56 | NormalizedName = "ADMIN" 57 | }, 58 | new 59 | { 60 | Id = "ff715d53-7725-48de-8d74-f064b8b41b45", 61 | Name = "user", 62 | NormalizedName = "USER" 63 | }, 64 | new 65 | { 66 | Id = "5654533a-52b5-4e1e-b9e5-fd8036ef35ff", 67 | Name = "manager", 68 | NormalizedName = "MANAGER" 69 | }, 70 | new 71 | { 72 | Id = "2b440d41-47fa-4fe5-ae96-b4ae34d223a1", 73 | Name = "guest", 74 | NormalizedName = "GUEST" 75 | }); 76 | }); 77 | 78 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => 79 | { 80 | b.Property("Id") 81 | .ValueGeneratedOnAdd() 82 | .HasColumnType("int"); 83 | 84 | SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); 85 | 86 | b.Property("ClaimType") 87 | .HasColumnType("nvarchar(max)"); 88 | 89 | b.Property("ClaimValue") 90 | .HasColumnType("nvarchar(max)"); 91 | 92 | b.Property("RoleId") 93 | .IsRequired() 94 | .HasColumnType("nvarchar(450)"); 95 | 96 | b.HasKey("Id"); 97 | 98 | b.HasIndex("RoleId"); 99 | 100 | b.ToTable("AspNetRoleClaims", (string)null); 101 | }); 102 | 103 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUser", b => 104 | { 105 | b.Property("Id") 106 | .HasColumnType("nvarchar(450)"); 107 | 108 | b.Property("AccessFailedCount") 109 | .HasColumnType("int"); 110 | 111 | b.Property("ConcurrencyStamp") 112 | .IsConcurrencyToken() 113 | .HasColumnType("nvarchar(max)"); 114 | 115 | b.Property("Discriminator") 116 | .IsRequired() 117 | .HasMaxLength(21) 118 | .HasColumnType("nvarchar(21)"); 119 | 120 | b.Property("Email") 121 | .HasMaxLength(256) 122 | .HasColumnType("nvarchar(256)"); 123 | 124 | b.Property("EmailConfirmed") 125 | .HasColumnType("bit"); 126 | 127 | b.Property("LockoutEnabled") 128 | .HasColumnType("bit"); 129 | 130 | b.Property("LockoutEnd") 131 | .HasColumnType("datetimeoffset"); 132 | 133 | b.Property("NormalizedEmail") 134 | .HasMaxLength(256) 135 | .HasColumnType("nvarchar(256)"); 136 | 137 | b.Property("NormalizedUserName") 138 | .HasMaxLength(256) 139 | .HasColumnType("nvarchar(256)"); 140 | 141 | b.Property("PasswordHash") 142 | .HasColumnType("nvarchar(max)"); 143 | 144 | b.Property("PhoneNumber") 145 | .HasColumnType("nvarchar(max)"); 146 | 147 | b.Property("PhoneNumberConfirmed") 148 | .HasColumnType("bit"); 149 | 150 | b.Property("SecurityStamp") 151 | .HasColumnType("nvarchar(max)"); 152 | 153 | b.Property("TwoFactorEnabled") 154 | .HasColumnType("bit"); 155 | 156 | b.Property("UserName") 157 | .HasMaxLength(256) 158 | .HasColumnType("nvarchar(256)"); 159 | 160 | b.HasKey("Id"); 161 | 162 | b.HasIndex("NormalizedEmail") 163 | .HasDatabaseName("EmailIndex"); 164 | 165 | b.HasIndex("NormalizedUserName") 166 | .IsUnique() 167 | .HasDatabaseName("UserNameIndex") 168 | .HasFilter("[NormalizedUserName] IS NOT NULL"); 169 | 170 | b.ToTable("AspNetUsers", (string)null); 171 | 172 | b.HasDiscriminator().HasValue("IdentityUser"); 173 | 174 | b.UseTphMappingStrategy(); 175 | }); 176 | 177 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => 178 | { 179 | b.Property("Id") 180 | .ValueGeneratedOnAdd() 181 | .HasColumnType("int"); 182 | 183 | SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); 184 | 185 | b.Property("ClaimType") 186 | .HasColumnType("nvarchar(max)"); 187 | 188 | b.Property("ClaimValue") 189 | .HasColumnType("nvarchar(max)"); 190 | 191 | b.Property("UserId") 192 | .IsRequired() 193 | .HasColumnType("nvarchar(450)"); 194 | 195 | b.HasKey("Id"); 196 | 197 | b.HasIndex("UserId"); 198 | 199 | b.ToTable("AspNetUserClaims", (string)null); 200 | }); 201 | 202 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => 203 | { 204 | b.Property("LoginProvider") 205 | .HasColumnType("nvarchar(450)"); 206 | 207 | b.Property("ProviderKey") 208 | .HasColumnType("nvarchar(450)"); 209 | 210 | b.Property("ProviderDisplayName") 211 | .HasColumnType("nvarchar(max)"); 212 | 213 | b.Property("UserId") 214 | .IsRequired() 215 | .HasColumnType("nvarchar(450)"); 216 | 217 | b.HasKey("LoginProvider", "ProviderKey"); 218 | 219 | b.HasIndex("UserId"); 220 | 221 | b.ToTable("AspNetUserLogins", (string)null); 222 | }); 223 | 224 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => 225 | { 226 | b.Property("UserId") 227 | .HasColumnType("nvarchar(450)"); 228 | 229 | b.Property("RoleId") 230 | .HasColumnType("nvarchar(450)"); 231 | 232 | b.HasKey("UserId", "RoleId"); 233 | 234 | b.HasIndex("RoleId"); 235 | 236 | b.ToTable("AspNetUserRoles", (string)null); 237 | }); 238 | 239 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => 240 | { 241 | b.Property("UserId") 242 | .HasColumnType("nvarchar(450)"); 243 | 244 | b.Property("LoginProvider") 245 | .HasColumnType("nvarchar(450)"); 246 | 247 | b.Property("Name") 248 | .HasColumnType("nvarchar(450)"); 249 | 250 | b.Property("Value") 251 | .HasColumnType("nvarchar(max)"); 252 | 253 | b.HasKey("UserId", "LoginProvider", "Name"); 254 | 255 | b.ToTable("AspNetUserTokens", (string)null); 256 | }); 257 | 258 | modelBuilder.Entity("Models.Domain.Image", b => 259 | { 260 | b.Property("Id") 261 | .ValueGeneratedOnAdd() 262 | .HasColumnType("int"); 263 | 264 | SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); 265 | 266 | b.Property("FileExtension") 267 | .IsRequired() 268 | .HasColumnType("nvarchar(max)"); 269 | 270 | b.Property("FileName") 271 | .IsRequired() 272 | .HasColumnType("nvarchar(max)"); 273 | 274 | b.Property("FilePath") 275 | .IsRequired() 276 | .HasColumnType("nvarchar(max)"); 277 | 278 | b.Property("FileSize") 279 | .HasColumnType("bigint"); 280 | 281 | b.HasKey("Id"); 282 | 283 | b.ToTable("Image"); 284 | }); 285 | 286 | modelBuilder.Entity("Models.Domain.ApplicationUser", b => 287 | { 288 | b.HasBaseType("Microsoft.AspNetCore.Identity.IdentityUser"); 289 | 290 | b.Property("ImageId") 291 | .HasColumnType("int"); 292 | 293 | b.Property("Name") 294 | .IsRequired() 295 | .HasColumnType("nvarchar(max)"); 296 | 297 | b.HasIndex("ImageId"); 298 | 299 | b.HasDiscriminator().HasValue("ApplicationUser"); 300 | }); 301 | 302 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => 303 | { 304 | b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) 305 | .WithMany() 306 | .HasForeignKey("RoleId") 307 | .OnDelete(DeleteBehavior.Cascade) 308 | .IsRequired(); 309 | }); 310 | 311 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => 312 | { 313 | b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) 314 | .WithMany() 315 | .HasForeignKey("UserId") 316 | .OnDelete(DeleteBehavior.Cascade) 317 | .IsRequired(); 318 | }); 319 | 320 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => 321 | { 322 | b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) 323 | .WithMany() 324 | .HasForeignKey("UserId") 325 | .OnDelete(DeleteBehavior.Cascade) 326 | .IsRequired(); 327 | }); 328 | 329 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => 330 | { 331 | b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) 332 | .WithMany() 333 | .HasForeignKey("RoleId") 334 | .OnDelete(DeleteBehavior.Cascade) 335 | .IsRequired(); 336 | 337 | b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) 338 | .WithMany() 339 | .HasForeignKey("UserId") 340 | .OnDelete(DeleteBehavior.Cascade) 341 | .IsRequired(); 342 | }); 343 | 344 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => 345 | { 346 | b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) 347 | .WithMany() 348 | .HasForeignKey("UserId") 349 | .OnDelete(DeleteBehavior.Cascade) 350 | .IsRequired(); 351 | }); 352 | 353 | modelBuilder.Entity("Models.Domain.ApplicationUser", b => 354 | { 355 | b.HasOne("Models.Domain.Image", "Image") 356 | .WithMany() 357 | .HasForeignKey("ImageId"); 358 | 359 | b.Navigation("Image"); 360 | }); 361 | #pragma warning restore 612, 618 362 | } 363 | } 364 | } 365 | -------------------------------------------------------------------------------- /DataAcess/Repos/IRepos/IImageRepository.cs: -------------------------------------------------------------------------------- 1 | using Models.Domain; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace DataAcess.Repos.IRepos 9 | { 10 | public interface IImageRepository 11 | { 12 | Task Upload(Image image); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /DataAcess/Repos/IRepos/IRepository.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Linq.Expressions; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace DataAcess.Repos.IRepos 9 | { 10 | public interface IRepository where T : class 11 | { 12 | 13 | Task GetAsync(Expression> filter = null, string? includes = null); 14 | Task> GetAllAsync(Expression> filter = null, string? includes = null, int pageSize = 0, int pageNumber = 1); 15 | Task AddAsync(T entity); 16 | Task DeleteAsync(T entity); 17 | 18 | 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /DataAcess/Repos/IRepos/IUserRepository.cs: -------------------------------------------------------------------------------- 1 | using Models.Domain; 2 | using Models.DTOs.Auth; 3 | using Models.DTOs.User; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | 10 | namespace DataAcess.Repos.IRepos 11 | { 12 | public interface IUserRepository : IRepository 13 | { 14 | Task IsUniqueUserName(string username); 15 | Task Login(LoginRequestDTO loginRequestDTO); 16 | Task Register(RegisterRequestDTO registerRequestDTO); 17 | Task GetUserByID(string userID); 18 | Task UpdateAsync(ApplicationUser user); 19 | 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /DataAcess/Repos/ImageRepository.cs: -------------------------------------------------------------------------------- 1 | using DataAcess.Repos.IRepos; 2 | using Microsoft.AspNetCore.Hosting; 3 | using Microsoft.AspNetCore.Http; 4 | using Models.Domain; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Linq; 8 | using System.Text; 9 | using System.Threading.Tasks; 10 | 11 | namespace DataAcess.Repos 12 | { 13 | public class ImageRepository : IImageRepository 14 | { 15 | private readonly ApplicationDbContext db; 16 | private readonly IWebHostEnvironment webHostEnvironment; 17 | private readonly IHttpContextAccessor contextAccessor; 18 | 19 | public ImageRepository(ApplicationDbContext db, IWebHostEnvironment webHostEnvironment ,IHttpContextAccessor contextAccessor) 20 | { 21 | this.db = db; 22 | this.webHostEnvironment = webHostEnvironment; 23 | this.contextAccessor = contextAccessor; 24 | } 25 | 26 | public async Task Upload(Image image) 27 | { 28 | if (image.File == null || image.File.Length == 0) 29 | { 30 | throw new ArgumentException("Uploaded file is empty or null."); 31 | } 32 | 33 | var folderPath = Path.Combine(webHostEnvironment.ContentRootPath, "Images"); 34 | if (!Directory.Exists(folderPath)) 35 | { 36 | Directory.CreateDirectory(folderPath); 37 | } 38 | 39 | var localFilepath = Path.Combine(folderPath, $"{image.FileName}{image.FileExtension}"); 40 | 41 | Console.WriteLine($"Saving to: {localFilepath}"); 42 | Console.WriteLine($"File Size: {image.File.Length} bytes"); 43 | 44 | using (var fileStream = new FileStream(localFilepath, FileMode.CreateNew)) 45 | { 46 | await image.File.CopyToAsync(fileStream); 47 | } 48 | 49 | var urlFilepath = $"{contextAccessor.HttpContext.Request.Scheme}://{contextAccessor.HttpContext.Request.Host}" + 50 | $"{contextAccessor.HttpContext.Request.PathBase}/Images/{image.FileName}{image.FileExtension}"; 51 | 52 | image.FilePath = urlFilepath; 53 | await db.Image.AddAsync(image); 54 | await db.SaveChangesAsync(); 55 | 56 | return image; 57 | } 58 | 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /DataAcess/Repos/Repository.cs: -------------------------------------------------------------------------------- 1 | using DataAcess.Repos.IRepos; 2 | using Microsoft.EntityFrameworkCore; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Linq.Expressions; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | 10 | namespace DataAcess.Repos 11 | { 12 | public class Repository : IRepository where T : class 13 | { 14 | private readonly ApplicationDbContext _db; 15 | internal DbSet DbSet; 16 | 17 | public Repository(ApplicationDbContext db) 18 | { 19 | _db = db; 20 | this.DbSet = _db.Set(); 21 | } 22 | 23 | public async Task AddAsync(T entity) 24 | { 25 | await DbSet.AddAsync(entity); 26 | } 27 | 28 | public async Task DeleteAsync(T entity) 29 | { 30 | DbSet.Remove(entity); 31 | } 32 | 33 | public async Task GetAsync(Expression> filter = null, string? includes = null) 34 | { 35 | IQueryable query = DbSet; 36 | 37 | if (filter != null) 38 | { 39 | query = query.Where(filter); 40 | } 41 | 42 | if (includes != null) 43 | { 44 | foreach (var include in includes.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries)) 45 | { 46 | query = query.Include(include); 47 | } 48 | } 49 | 50 | return await query.FirstOrDefaultAsync(); 51 | } 52 | 53 | public async Task> GetAllAsync(Expression> filter = null, string? includes = null, int pageSize = 0, int pageNumber = 1) 54 | { 55 | IQueryable query = DbSet; 56 | 57 | if (filter != null) 58 | { 59 | query = query.Where(filter); 60 | } 61 | 62 | if (includes != null) 63 | { 64 | foreach (var include in includes.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries)) 65 | { 66 | query = query.Include(include); 67 | } 68 | } 69 | 70 | if (pageSize > 0) 71 | { 72 | if (pageSize > 100) 73 | { 74 | pageSize = 100; 75 | } 76 | query = query.Skip(pageSize * (pageNumber - 1)).Take(pageSize); 77 | } 78 | 79 | return await query.ToListAsync(); 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /DataAcess/Repos/UserRepository.cs: -------------------------------------------------------------------------------- 1 | using DataAcess.Repos.IRepos; 2 | using Microsoft.AspNetCore.Identity; 3 | using Microsoft.Extensions.Configuration; 4 | using Microsoft.IdentityModel.Tokens; 5 | using Models.DTOs.Auth; 6 | using Models.DTOs.User; 7 | using System; 8 | using System.Collections.Generic; 9 | using System.IdentityModel.Tokens.Jwt; 10 | using System.Linq; 11 | using System.Security.Claims; 12 | using System.Text; 13 | using System.Threading.Tasks; 14 | using AutoMapper; 15 | using Models.Domain; 16 | 17 | 18 | namespace DataAcess.Repos 19 | { 20 | public class UserRepository : Repository, IUserRepository 21 | { 22 | private readonly ApplicationDbContext db; 23 | private readonly IMapper mapper; 24 | private readonly UserManager userManager; 25 | private readonly RoleManager roleManager; 26 | private readonly IConfiguration configuration; 27 | private string securityKey; 28 | 29 | public UserRepository(ApplicationDbContext db, IConfiguration configuration, UserManager userManager, IMapper mapper, RoleManager roleManager) : base(db) 30 | { 31 | this.db = db; 32 | this.configuration = configuration; 33 | this.userManager = userManager; 34 | this.mapper = mapper; 35 | this.roleManager = roleManager; 36 | //Just install `Microsoft.Extensions.Configuration.Binder` and the method `GetValue` will be available 37 | securityKey = configuration.GetValue("ApiSettings:Secret") ?? throw new InvalidOperationException("ApiSettings:Secret is not configured."); 38 | } 39 | 40 | public async Task GetUserByID(string userID) 41 | { 42 | var user = await db.ApplicationUser.FindAsync(userID); 43 | return user ?? throw new InvalidOperationException("User not found."); 44 | } 45 | 46 | public async Task IsUniqueUserName(string username) 47 | { 48 | var matchUsername = await userManager.FindByNameAsync(username); 49 | return matchUsername == null; 50 | } 51 | 52 | public async Task Login(LoginRequestDTO loginRequestDTO) 53 | { 54 | var user = await userManager.FindByNameAsync(loginRequestDTO.UserName); 55 | if (user == null || !await userManager.CheckPasswordAsync(user, loginRequestDTO.Password)) 56 | { 57 | return new LoginResponseDTO() 58 | { 59 | Token = "", 60 | User = null, 61 | }; 62 | } 63 | var userRoles = await userManager.GetRolesAsync(user); 64 | 65 | var claims = new List 66 | { 67 | new Claim(ClaimTypes.NameIdentifier, user.Id), 68 | new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()), 69 | new Claim(ClaimTypes.Name, user.UserName) 70 | }; 71 | claims.AddRange(userRoles.Select(r => new Claim(ClaimTypes.Role, r))); 72 | 73 | var key = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(securityKey)); 74 | var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256); 75 | 76 | var token = new JwtSecurityToken( 77 | claims: claims, 78 | expires: DateTime.UtcNow.AddDays(7), 79 | signingCredentials: creds); 80 | 81 | return new LoginResponseDTO() 82 | { 83 | Token = new JwtSecurityTokenHandler().WriteToken(token), 84 | User = mapper.Map(user), 85 | }; 86 | } 87 | 88 | public async Task Register(RegisterRequestDTO registerRequestDTO) 89 | { 90 | var user = new ApplicationUser 91 | { 92 | UserName = registerRequestDTO.UserName, 93 | Name = registerRequestDTO.Name, 94 | Email = registerRequestDTO.Email, 95 | NormalizedEmail = registerRequestDTO.Email.ToUpper() 96 | }; 97 | 98 | var userDTO = new UserDTO(); 99 | 100 | try 101 | { 102 | var result = await userManager.CreateAsync(user, registerRequestDTO.Password); 103 | if (result.Succeeded) 104 | { 105 | 106 | if (registerRequestDTO.Roles != null && registerRequestDTO.Roles.Any()) // any() is a LINQ method that returns true if there are any elements in the collection 107 | { 108 | foreach (var role in registerRequestDTO.Roles) 109 | { 110 | if (!await roleManager.RoleExistsAsync(role)) 111 | { 112 | await roleManager.CreateAsync(new IdentityRole(role)); 113 | } 114 | await userManager.AddToRoleAsync(user, role); 115 | } 116 | } 117 | 118 | userDTO = mapper.Map(user); 119 | } 120 | else 121 | { 122 | userDTO.ErrorMessages = result.Errors.Select(e => e.Description).ToList(); 123 | } 124 | } 125 | catch (Exception) 126 | { 127 | userDTO.ErrorMessages = new List { "An unexpected error occurred while registering the user." }; 128 | } 129 | 130 | return userDTO; 131 | } 132 | 133 | public async Task UpdateAsync(ApplicationUser user) 134 | { 135 | var existingUser = await db.ApplicationUser.FindAsync(user.Id); 136 | if (existingUser == null) 137 | { 138 | return false; 139 | } 140 | 141 | if (user.ImageId != 0 || user.ImageId != null) 142 | { 143 | existingUser.ImageId = user.ImageId; 144 | } 145 | 146 | var result = await db.SaveChangesAsync(); 147 | return result > 0; 148 | } 149 | 150 | } 151 | } -------------------------------------------------------------------------------- /IdentityManager.Services/ControllerService/AuthService.cs: -------------------------------------------------------------------------------- 1 | using DataAcess.Repos.IRepos; 2 | using IdentityManager.Services.ControllerService.IControllerService; 3 | using Models.DTOs.Auth; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.ComponentModel.DataAnnotations; 7 | using System.Linq; 8 | using System.Text; 9 | using System.Threading.Tasks; 10 | 11 | namespace IdentityManager.Services.ControllerService 12 | { 13 | public class AuthService : IAuthService 14 | { 15 | private readonly IUserRepository _userRepository; 16 | 17 | public AuthService(IUserRepository userRepository) 18 | { 19 | _userRepository = userRepository; 20 | } 21 | 22 | public async Task LoginAsync(LoginRequestDTO loginRequestDTO) 23 | { 24 | return await _userRepository.Login(loginRequestDTO); 25 | } 26 | 27 | public async Task RegisterAsync(RegisterRequestDTO registerRequestDTO) 28 | { 29 | var emailExist = await _userRepository.GetAsync(user => user.Email == registerRequestDTO.Email); 30 | if (emailExist != null) 31 | { 32 | throw new ValidationException("Email Already exists"); 33 | } 34 | 35 | return await _userRepository.Register(registerRequestDTO); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /IdentityManager.Services/ControllerService/IControllerService/IAuthService.cs: -------------------------------------------------------------------------------- 1 | using Models.DTOs.Auth; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace IdentityManager.Services.ControllerService.IControllerService 9 | { 10 | public interface IAuthService 11 | { 12 | Task LoginAsync(LoginRequestDTO loginRequestDTO); 13 | Task RegisterAsync(RegisterRequestDTO registerRequestDTO); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /IdentityManager.Services/ControllerService/IControllerService/IUserService.cs: -------------------------------------------------------------------------------- 1 | using Models.DTOs.image; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace IdentityManager.Services.ControllerService.IControllerService 9 | { 10 | public interface IUserService 11 | { 12 | Task UploadUserImageAsync(string userId, ImageUploadRequestDto request); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /IdentityManager.Services/ControllerService/UserService.cs: -------------------------------------------------------------------------------- 1 | using DataAcess.Repos.IRepos; 2 | using IdentityManager.Services.ControllerService.IControllerService; 3 | using Models.Domain; 4 | using Models.DTOs.image; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Linq; 8 | using System.Text; 9 | using System.Threading.Tasks; 10 | 11 | namespace IdentityManager.Services.ControllerService 12 | { 13 | public class UserService : IUserService 14 | { 15 | private readonly IImageRepository _imageRepo; 16 | private readonly IUserRepository _userRepo; 17 | 18 | public UserService(IImageRepository imageRepo, IUserRepository userRepo) 19 | { 20 | _imageRepo = imageRepo; 21 | _userRepo = userRepo; 22 | } 23 | 24 | public async Task UploadUserImageAsync(string userId, ImageUploadRequestDto request) 25 | { 26 | if (string.IsNullOrEmpty(userId)) 27 | { 28 | throw new Exception("User not found"); 29 | } 30 | 31 | var user = await _userRepo.GetUserByID(userId); 32 | ValidateFileUpload(request); 33 | 34 | var image = new Image 35 | { 36 | File = request.File, 37 | FileName = DateTime.Now.ToString("yyyyMMddHHmmssfff"), 38 | FileExtension = Path.GetExtension(request.File.FileName), 39 | FileSize = request.File.Length 40 | }; 41 | 42 | await _imageRepo.Upload(image); 43 | user.ImageId = image.Id; 44 | await _userRepo.UpdateAsync(user); 45 | 46 | return user; 47 | } 48 | 49 | private void ValidateFileUpload(ImageUploadRequestDto request) 50 | { 51 | if (request.File == null) 52 | { 53 | throw new Exception("File is required"); 54 | } 55 | if (request.File.Length == 0) 56 | { 57 | throw new Exception("File is empty"); 58 | } 59 | if (request.File.Length > 10 * 1024 * 1024) 60 | { 61 | throw new Exception("File is too large"); 62 | } 63 | if (request.File.ContentType != "image/jpeg" && request.File.ContentType != "image/png") 64 | { 65 | throw new Exception("File is not an image"); 66 | } 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /IdentityManager.Services/IdentityManager.Services.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net9.0 5 | enable 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /IdentityManagerAPI.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net9.0 5 | enable 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /IdentityManagerAPI.http: -------------------------------------------------------------------------------- 1 | @IdentityManagerAPI_HostAddress = http://localhost:5057 2 | 3 | GET {{IdentityManagerAPI_HostAddress}}/weatherforecast/ 4 | Accept: application/json 5 | 6 | ### 7 | -------------------------------------------------------------------------------- /IdentityManagerAPI.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.12.35707.178 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IdentityManagerAPI", "IdentityManagerAPI\IdentityManagerAPI.csproj", "{2748F6A5-B78D-4782-A185-F5DC1B4944B4}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DataAcess", "DataAcess\DataAcess.csproj", "{27AFB5C8-5876-48D6-B8E1-0BCA2FA09D71}" 9 | EndProject 10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Models", "Models\Models.csproj", "{A89FB4DF-A248-4F18-9E85-4C84EE4752E6}" 11 | EndProject 12 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IdentityManager.Services", "IdentityManager.Services\IdentityManager.Services.csproj", "{5A47FBD8-62E3-4CFB-81F6-6BB7041EFB60}" 13 | EndProject 14 | Global 15 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 16 | Debug|Any CPU = Debug|Any CPU 17 | Release|Any CPU = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 20 | {2748F6A5-B78D-4782-A185-F5DC1B4944B4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 21 | {2748F6A5-B78D-4782-A185-F5DC1B4944B4}.Debug|Any CPU.Build.0 = Debug|Any CPU 22 | {2748F6A5-B78D-4782-A185-F5DC1B4944B4}.Release|Any CPU.ActiveCfg = Release|Any CPU 23 | {2748F6A5-B78D-4782-A185-F5DC1B4944B4}.Release|Any CPU.Build.0 = Release|Any CPU 24 | {27AFB5C8-5876-48D6-B8E1-0BCA2FA09D71}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 25 | {27AFB5C8-5876-48D6-B8E1-0BCA2FA09D71}.Debug|Any CPU.Build.0 = Debug|Any CPU 26 | {27AFB5C8-5876-48D6-B8E1-0BCA2FA09D71}.Release|Any CPU.ActiveCfg = Release|Any CPU 27 | {27AFB5C8-5876-48D6-B8E1-0BCA2FA09D71}.Release|Any CPU.Build.0 = Release|Any CPU 28 | {A89FB4DF-A248-4F18-9E85-4C84EE4752E6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 29 | {A89FB4DF-A248-4F18-9E85-4C84EE4752E6}.Debug|Any CPU.Build.0 = Debug|Any CPU 30 | {A89FB4DF-A248-4F18-9E85-4C84EE4752E6}.Release|Any CPU.ActiveCfg = Release|Any CPU 31 | {A89FB4DF-A248-4F18-9E85-4C84EE4752E6}.Release|Any CPU.Build.0 = Release|Any CPU 32 | {5A47FBD8-62E3-4CFB-81F6-6BB7041EFB60}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 33 | {5A47FBD8-62E3-4CFB-81F6-6BB7041EFB60}.Debug|Any CPU.Build.0 = Debug|Any CPU 34 | {5A47FBD8-62E3-4CFB-81F6-6BB7041EFB60}.Release|Any CPU.ActiveCfg = Release|Any CPU 35 | {5A47FBD8-62E3-4CFB-81F6-6BB7041EFB60}.Release|Any CPU.Build.0 = Release|Any CPU 36 | EndGlobalSection 37 | GlobalSection(SolutionProperties) = preSolution 38 | HideSolutionNode = FALSE 39 | EndGlobalSection 40 | EndGlobal 41 | -------------------------------------------------------------------------------- /IdentityManagerAPI/BearerSecuritySchemeTransformer.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Authentication; 2 | using Microsoft.AspNetCore.OpenApi; 3 | using Microsoft.OpenApi.Models; 4 | 5 | // sealed = no inhertance 6 | public sealed class BearerSecuritySchemeTransformer : IOpenApiDocumentTransformer 7 | { 8 | private readonly IAuthenticationSchemeProvider _authenticationSchemeProvider; 9 | 10 | public BearerSecuritySchemeTransformer(IAuthenticationSchemeProvider authenticationSchemeProvider) 11 | { 12 | _authenticationSchemeProvider = authenticationSchemeProvider; 13 | } 14 | 15 | public async Task TransformAsync(OpenApiDocument document, OpenApiDocumentTransformerContext context, CancellationToken cancellationToken) 16 | { 17 | var authenticationSchemes = await _authenticationSchemeProvider.GetAllSchemesAsync(); 18 | if (authenticationSchemes.Any(authScheme => authScheme.Name == "Bearer")) 19 | { 20 | var requirements = new Dictionary 21 | { 22 | ["Bearer"] = new OpenApiSecurityScheme 23 | { 24 | Type = SecuritySchemeType.Http, 25 | Scheme = "bearer", 26 | In = ParameterLocation.Header, 27 | BearerFormat = "JWT" 28 | } 29 | }; 30 | 31 | document.Components ??= new OpenApiComponents(); 32 | document.Components.SecuritySchemes = requirements; 33 | 34 | foreach (var operation in document.Paths.Values.SelectMany(path => path.Operations)) 35 | { 36 | operation.Value.Security.Add(new OpenApiSecurityRequirement 37 | { 38 | [new OpenApiSecurityScheme { Reference = new OpenApiReference { Id = "Bearer", Type = ReferenceType.SecurityScheme } }] = Array.Empty() 39 | }); 40 | } 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /IdentityManagerAPI/Controllers/AuthUserController.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using Microsoft.AspNetCore.Http; 3 | using Microsoft.AspNetCore.Identity; 4 | using Microsoft.AspNetCore.Mvc; 5 | using Models.DTOs.Auth; 6 | using Models; 7 | using System.Net; 8 | using DataAcess.Repos.IRepos; 9 | using Models.Domain; 10 | using IdentityManager.Services.ControllerService.IControllerService; 11 | 12 | namespace IdentityManagerAPI.Controllers 13 | { 14 | [Route("api/[controller]")] 15 | [ApiController] 16 | public class AuthUserController : ControllerBase 17 | { 18 | private readonly IAuthService _authService; 19 | public AuthUserController(IAuthService authService) 20 | { 21 | _authService = authService; 22 | } 23 | [HttpPost("login")] 24 | public async Task Login([FromBody] LoginRequestDTO loginRequestDTO) 25 | { 26 | var result = await _authService.LoginAsync(loginRequestDTO); 27 | return Ok(result); 28 | } 29 | [HttpPost("register")] 30 | public async Task Register([FromBody] RegisterRequestDTO registerRequestDTO) 31 | { 32 | var result = await _authService.RegisterAsync(registerRequestDTO); 33 | return Ok(result); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /IdentityManagerAPI/Controllers/UserController.cs: -------------------------------------------------------------------------------- 1 | using DataAcess.Repos.IRepos; 2 | using IdentityManager.Services.ControllerService.IControllerService; 3 | using Microsoft.AspNetCore.Authorization; 4 | using Microsoft.AspNetCore.Http; 5 | using Microsoft.AspNetCore.Mvc; 6 | using Models.Domain; 7 | using Models.DTOs.image; 8 | using System.Security.Claims; 9 | 10 | namespace IdentityManagerAPI.Controllers 11 | { 12 | [Route("api/[controller]")] 13 | [ApiController] 14 | public class UserController : ControllerBase 15 | { 16 | 17 | private readonly IUserService userService; 18 | 19 | public UserController(IUserService userService) 20 | { 21 | this.userService = userService; 22 | } 23 | 24 | public IUserRepository UserRepo { get; } 25 | 26 | [HttpPost] 27 | [Authorize] 28 | [Route("uploadUserImage")] 29 | public async Task UploadUserImage([FromForm] ImageUploadRequestDto request) 30 | { 31 | var userId = User.FindFirstValue(ClaimTypes.NameIdentifier); 32 | var result = await userService.UploadUserImageAsync(userId, request); 33 | return Ok(result); 34 | } 35 | 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /IdentityManagerAPI/IdentityManagerAPI.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net9.0 5 | enable 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | all 20 | runtime; build; native; contentfiles; analyzers; buildtransitive 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /IdentityManagerAPI/IdentityManagerAPI.http: -------------------------------------------------------------------------------- 1 | @IdentityManagerAPI_HostAddress = http://localhost:5025 2 | 3 | GET {{IdentityManagerAPI_HostAddress}}/weatherforecast/ 4 | Accept: application/json 5 | 6 | ### 7 | -------------------------------------------------------------------------------- /IdentityManagerAPI/Images/asd..jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mrXrobot26/IdentityManagerAPI/3b1829ecd7dc5ac1629f5fb0093e01ca473f77ec/IdentityManagerAPI/Images/asd..jpg -------------------------------------------------------------------------------- /IdentityManagerAPI/Middlewares/GlobalExceptionHandler.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Diagnostics; 2 | using Microsoft.AspNetCore.Mvc; 3 | using System.ComponentModel.DataAnnotations; 4 | 5 | namespace IdentityManagerAPI.Middlewares 6 | { 7 | public class GlobalExceptionHandler : IExceptionHandler 8 | { 9 | public async ValueTask TryHandleAsync(HttpContext httpContext, Exception exception, CancellationToken cancellationToken) 10 | { 11 | var problemDetails = new ProblemDetails 12 | { 13 | Title = "An error occurred", 14 | Status = StatusCodes.Status400BadRequest, 15 | Detail = exception.Message 16 | }; 17 | 18 | httpContext.Response.StatusCode = problemDetails.Status.Value; 19 | 20 | await httpContext.Response.WriteAsJsonAsync(problemDetails, cancellationToken); 21 | 22 | return true; 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /IdentityManagerAPI/Program.cs: -------------------------------------------------------------------------------- 1 | using DataAcess; 2 | using Microsoft.AspNetCore.Identity; 3 | using Microsoft.EntityFrameworkCore; 4 | using Scalar.AspNetCore; 5 | using Models.DTOs.Mapper; 6 | using Microsoft.AspNetCore.Authentication.JwtBearer; 7 | using Microsoft.IdentityModel.Tokens; 8 | using System.Text; 9 | using Microsoft.AspNetCore.OpenApi; 10 | using Microsoft.OpenApi.Models; 11 | using DataAcess.Repos; 12 | using DataAcess.Repos.IRepos; 13 | using Models.Domain; 14 | using Microsoft.Extensions.FileProviders; 15 | using IdentityManagerAPI.Middlewares; 16 | using IdentityManager.Services.ControllerService.IControllerService; 17 | using IdentityManager.Services.ControllerService; 18 | 19 | var builder = WebApplication.CreateBuilder(args); 20 | 21 | 22 | 23 | // Add services to the container. 24 | builder.Services.AddControllers(); 25 | builder.Services.AddHttpContextAccessor(); 26 | 27 | // Add database context 28 | builder.Services.AddDbContext(options => 29 | options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection"))); 30 | 31 | // Configure Identity 32 | builder.Services.AddIdentity() 33 | .AddEntityFrameworkStores() 34 | .AddDefaultTokenProviders(); 35 | 36 | 37 | // Add AutoMapper 38 | builder.Services.AddAutoMapper(typeof(MappingConfig)); 39 | 40 | 41 | builder.Services.AddScoped>(); 42 | builder.Services.AddScoped>(); 43 | builder.Services.AddScoped>(); 44 | 45 | // Add Services 46 | builder.Services.AddScoped(); 47 | builder.Services.AddScoped(); 48 | 49 | 50 | // Add Repositories 51 | builder.Services.AddScoped(); 52 | builder.Services.AddScoped(); 53 | 54 | // Add OpenAPI with Bearer Authentication Support 55 | builder.Services.AddOpenApi("v1", options => 56 | { 57 | options.AddDocumentTransformer(); 58 | }); 59 | 60 | 61 | 62 | // Configure JWT Authentication insted of cookies 63 | var key = Encoding.ASCII.GetBytes(builder.Configuration["ApiSettings:Secret"]); 64 | builder.Services.AddAuthentication(options => 65 | { 66 | options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; 67 | options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; 68 | }) 69 | .AddJwtBearer(options => 70 | { 71 | options.TokenValidationParameters = new TokenValidationParameters 72 | { 73 | ValidateIssuerSigningKey = true, 74 | IssuerSigningKey = new SymmetricSecurityKey(key), 75 | ValidateIssuer = false, 76 | ValidateAudience = false, 77 | ClockSkew = TimeSpan.FromDays(7) 78 | }; 79 | }); 80 | 81 | 82 | // Register the global exception handler 83 | builder.Services.AddExceptionHandler(); 84 | builder.Services.AddProblemDetails(); 85 | 86 | var app = builder.Build(); 87 | 88 | // Configure the HTTP request pipeline. 89 | if (app.Environment.IsDevelopment()) 90 | { 91 | app.MapOpenApi(); 92 | app.MapScalarApiReference(); 93 | } 94 | 95 | // Use the global exception handler 96 | app.UseExceptionHandler(); 97 | 98 | 99 | app.UseHttpsRedirection(); 100 | app.UseAuthentication(); 101 | app.UseAuthorization(); 102 | 103 | app.UseStaticFiles(new StaticFileOptions 104 | { 105 | FileProvider = new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(), "Images")), 106 | RequestPath = "/Images" 107 | }); 108 | 109 | app.MapControllers(); 110 | 111 | app.Run(); 112 | -------------------------------------------------------------------------------- /IdentityManagerAPI/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/launchsettings.json", 3 | "profiles": { 4 | "http": { 5 | "commandName": "Project", 6 | "dotnetRunMessages": true, 7 | "launchBrowser": true, 8 | "launchUrl": "scalar/v1", 9 | "applicationUrl": "http://localhost:5025", 10 | "environmentVariables": { 11 | "ASPNETCORE_ENVIRONMENT": "Development" 12 | } 13 | }, 14 | "https": { 15 | "commandName": "Project", 16 | "dotnetRunMessages": true, 17 | "launchBrowser": true, 18 | "launchUrl": "scalar/v1", 19 | "applicationUrl": "https://localhost:7047;http://localhost:5025", 20 | "environmentVariables": { 21 | "ASPNETCORE_ENVIRONMENT": "Development" 22 | } 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /IdentityManagerAPI/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /IdentityManagerAPI/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | }, 8 | "ConnectionStrings": { 9 | "DefaultConnection": "Server=GATES;Database=IdentityManager;Trusted_Connection=true;TrustServerCertificate=true" 10 | }, 11 | "AllowedHosts": "*", 12 | "ApiSettings": { 13 | "Secret": "THIS IS USED TO SIGN AND VERIFY JWT TOKENS, REPLACE IT WITH YOUR OWN SECRET" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Models/DTOs/Auth/LoginRequestDTO.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Models.DTOs.Auth 9 | { 10 | public class LoginRequestDTO 11 | { 12 | [Required] 13 | public string UserName { get; set; } 14 | [Required] 15 | public string Password { get; set; } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Models/DTOs/Auth/LoginResponseDTO.cs: -------------------------------------------------------------------------------- 1 | using Models.DTOs.User; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Models.DTOs.Auth 9 | { 10 | public class LoginResponseDTO 11 | { 12 | public UserDTO User { get; set; } 13 | public string Token { get; set; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Models/DTOs/Auth/RegisterRequestDTO.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Models.DTOs.Auth 9 | { 10 | public class RegisterRequestDTO 11 | { 12 | [Required] 13 | public string UserName { get; set; } 14 | [Required] 15 | public string Name { get; set; } 16 | [Required] 17 | [EmailAddress] 18 | public string Email { get; set; } 19 | [Required] 20 | public string Password { get; set; } 21 | [Required] 22 | public List Roles { get; set; } = new List(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Models/DTOs/Mapper/MappingConfig.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using Models.Domain; 3 | using Models.DTOs.User; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | 10 | namespace Models.DTOs.Mapper 11 | { 12 | public class MappingConfig : Profile 13 | { 14 | public MappingConfig() 15 | { 16 | CreateMap().ReverseMap(); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Models/DTOs/User/UserDTO.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Models.DTOs.User 8 | { 9 | public class UserDTO 10 | { 11 | public string UserName { get; set; } 12 | public string Name { get; set; } 13 | public string Email { get; set; } 14 | public List ErrorMessages { get; set; } = new List(); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Models/DTOs/image/ImageUploadRequestDto.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Http; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.ComponentModel.DataAnnotations; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace Models.DTOs.image 10 | { 11 | public class ImageUploadRequestDto 12 | { 13 | [Required] 14 | public IFormFile File { get; set; } 15 | 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Models/Domain/ApplicationUser.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Identity; 2 | using System.ComponentModel.DataAnnotations; 3 | using System.ComponentModel.DataAnnotations.Schema; 4 | 5 | namespace Models.Domain 6 | { 7 | public class ApplicationUser : IdentityUser 8 | { 9 | [Required] 10 | public string Name { get; set; } 11 | public int? ImageId { get; set; } 12 | 13 | // Navigation property 14 | [ForeignKey("ImageId")] 15 | public Image Image { get; set; } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Models/Domain/Image.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Http; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.ComponentModel.DataAnnotations.Schema; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace Models.Domain 10 | { 11 | public class Image 12 | { 13 | public int Id { get; set; } 14 | [NotMapped] 15 | public IFormFile File { get; set; } 16 | public string FileName { get; set; } 17 | public string FileExtension { get; set; } 18 | public long FileSize { get; set; } 19 | public string FilePath { get; set; } 20 | 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Models/Models.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net9.0 5 | enable 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /Program.cs: -------------------------------------------------------------------------------- 1 | var builder = WebApplication.CreateBuilder(args); 2 | 3 | // Add services to the container. 4 | // Learn more about configuring OpenAPI at https://aka.ms/aspnet/openapi 5 | builder.Services.AddOpenApi(); 6 | 7 | var app = builder.Build(); 8 | 9 | // Configure the HTTP request pipeline. 10 | if (app.Environment.IsDevelopment()) 11 | { 12 | app.MapOpenApi(); 13 | } 14 | 15 | app.UseHttpsRedirection(); 16 | 17 | var summaries = new[] 18 | { 19 | "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" 20 | }; 21 | 22 | app.MapGet("/weatherforecast", () => 23 | { 24 | var forecast = Enumerable.Range(1, 5).Select(index => 25 | new WeatherForecast 26 | ( 27 | DateOnly.FromDateTime(DateTime.Now.AddDays(index)), 28 | Random.Shared.Next(-20, 55), 29 | summaries[Random.Shared.Next(summaries.Length)] 30 | )) 31 | .ToArray(); 32 | return forecast; 33 | }) 34 | .WithName("GetWeatherForecast"); 35 | 36 | app.Run(); 37 | 38 | record WeatherForecast(DateOnly Date, int TemperatureC, string? Summary) 39 | { 40 | public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); 41 | } 42 | -------------------------------------------------------------------------------- /Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/launchsettings.json", 3 | "profiles": { 4 | "http": { 5 | "commandName": "Project", 6 | "dotnetRunMessages": true, 7 | "launchBrowser": false, 8 | "applicationUrl": "http://localhost:5057", 9 | "environmentVariables": { 10 | "ASPNETCORE_ENVIRONMENT": "Development" 11 | } 12 | }, 13 | "https": { 14 | "commandName": "Project", 15 | "dotnetRunMessages": true, 16 | "launchBrowser": false, 17 | "applicationUrl": "https://localhost:7164;http://localhost:5057", 18 | "environmentVariables": { 19 | "ASPNETCORE_ENVIRONMENT": "Development" 20 | } 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # .NET Clean Architecture (Onion Architecture) Starter Template 2 | 3 | Welcome to the **.NET Clean Architecture Starter Template**! 4 | This repository serves as a well-structured **boilerplate** for building scalable .NET applications following clean architecture principles. 5 | 6 | ## 📌 Overview 7 | 8 | This template provides: 9 | - A **modular and scalable** project structure. 10 | - **Clean Architecture** principles (Domain-Driven Design). 11 | - **Entity Framework Core** setup for database management. 12 | - **Repository & Service pattern** for better code maintainability. 13 | - **ASP.NET Identity** for authentication & role-based authorization. 14 | - **AutoMapper** for DTO mapping. 15 | - **Middleware setup** for security & request handling. 16 | - **Dependency Injection** for better code organization. 17 | - **Exception Handling Middleware (`IHandlerException`)** to manage errors efficiently. 18 | - **Scalar API documentation integration** for improved OpenAPI documentation. 19 | 20 | 21 | ## 📂 Project Structure 22 | ```md 23 | 24 | IdentityManagerAPI/ 25 | │── .gitignore 26 | │── README.md 27 | │── appsettings.json 28 | │── Program.cs 29 | │── IdentityManagerAPI.http 30 | ├── Controllers/ 31 | │ ├── AuthUserController.cs 32 | │ ├── UserController.cs 33 | ├── Middlewares/ 34 | │ ├── GlobalExceptionHandler.cs 35 | │──BearerSecuritySchemeTransformer.cs 36 | │ 37 | ├── DataAcess/ 38 | │ ├── Configuration/ 39 | │ │ ├── ApplicationUserConfiguration.cs 40 | │ │ ├── RoleConfiguration.cs 41 | │ ├── Migrations/ 42 | │ ├── Repos/ 43 | │ │ ├── IRepos/ 44 | │ │ │ ├── IImageRepository.cs 45 | │ │ │ ├── IRepository.cs 46 | │ │ │ ├── IUserRepository.cs 47 | │ │ ├── ImageRepository.cs 48 | │ │ ├── Repository.cs 49 | │ │ ├── UserRepository.cs 50 | │ ├── ApplicationDbContext.cs 51 | │ 52 | ├── IdentityManager.Services/ 53 | │ ├── ControllerService/ 54 | │ │ ├── IControllerService/ 55 | │ │ │ ├── IAuthService.cs 56 | │ │ │ ├── IUserService.cs 57 | │ │ ├── AuthService.cs 58 | │ │ ├── UserService.cs 59 | │ 60 | │ 61 | ├── Models/ 62 | │ ├── Domain/ 63 | │ │ ├── ApplicationUser.cs 64 | │ │ ├── Image.cs 65 | │ ├── DTOs/ 66 | │ │ ├── Auth/ 67 | │ │ │ ├── LoginRequestDTO.cs 68 | │ │ │ ├── LoginResponseDTO.cs 69 | │ │ │ ├── RegisterRequestDTO.cs 70 | │ │ ├── Image/ 71 | │ │ │ ├── ImageUploadRequestDto.cs 72 | │ │ ├── Mapper/ 73 | │ │ │ ├── MappingConfig.cs 74 | │ │ ├── User/ 75 | │ │ │ ├── UserDTO.cs 76 | ├── 77 | ``` 78 | --- 79 | 80 | ## 🚀 Getting Started 81 | 82 | ### 1️⃣ Clone the Repository 83 | ```bash 84 | git clone https://github.com/mrXrobot26/IdentityManagerAPI.git 85 | cd IdentityManagerAPI 86 | ``` 87 | 88 | ### **2️⃣ Setup Database & Migrations** 89 | 1. **Update Connection String** in `appsettings.json`: 90 | ```json 91 | "ConnectionStrings": { 92 | "DefaultConnection": "your_database_connection_string_here" 93 | } 94 | ``` 95 | 2. **Apply Migrations:** 96 | 97 | ```sh 98 | dotnet ef database update 99 | ``` 100 | 101 | --- 102 | 103 | ## 🔧 Project Configuration 104 | 105 | ### **Authentication & Identity** 106 | - Uses **ASP.NET Core Identity** for user authentication & role management. 107 | - Default roles: `Admin`, `User`. 108 | 109 | ### **Middleware** 110 | - `BearerSecuritySchemeTransformer.cs` for authentication. 111 | - Custom middleware can be added for logging, security, etc. 112 | 113 | ### **DTOs & AutoMapper** 114 | - Uses **DTOs** for API request/response models. 115 | - **AutoMapper** is configured in `MappingConfig.cs` to handle model transformations. 116 | 117 | --- 118 | 119 | ## 🏗️ Built With 120 | 121 | | Technology | Description | 122 | |-----------------|------------| 123 | | **.NET Core** | Framework for building APIs | 124 | | **Entity Framework Core** | ORM for database management | 125 | | **ASP.NET Identity** | Authentication & Authorization | 126 | | **AutoMapper** | Object-to-object mapping | 127 | | **Scalar** | API documentation | 128 | | **Middleware** | Custom request handlers | 129 | | **Dependency Injection** | Loosely coupled architecture | 130 | 131 | --- 132 | 133 | ## 📖 API Documentation (Scalar) 134 | Once the application is running, access **Scalar UI** at: 135 | ``` 136 | http://localhost:5025/scalar/v1 137 | ``` 138 | 139 | --- 140 | 141 | ## 🛠️ Development & Contribution 142 | 143 | ### **Running Locally** 144 | 1. Ensure you have `.NET 9 SDK` installed. 145 | 2. Run: 146 | ```sh 147 | dotnet run 148 | ``` 149 | 150 | ### **Contributing** 151 | 1. Fork the repo. 152 | 2. Create a new branch (`feature-branch`). 153 | 3. Commit your changes. 154 | 4. Push to your fork and create a **Pull Request**. 155 | --- 156 | ### 🔥 **Star the Repo & Contribute!** 157 | This template is open-source and constantly evolving. 158 | If you find it useful, **give it a star ⭐ and contribute!** 🚀 159 | 160 | --- 161 | -------------------------------------------------------------------------------- /appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | }, 8 | "AllowedHosts": "*" 9 | } 10 | --------------------------------------------------------------------------------