├── Views
├── _ViewStart.cshtml
├── _ViewImports.cshtml
├── Account
│ ├── ForgotPassword.cshtml
│ ├── ResetPassword.cshtml
│ ├── Register.cshtml
│ └── Login.cshtml
├── Shared
│ └── _Layout.cshtml
└── Home
│ └── Index.cshtml
├── IMessageService.cs
├── Dockerfile
├── Properties
└── launchSettings.json
├── README.md
├── .vscode
├── tasks.json
└── launch.json
├── FileMessageService.cs
├── web.config
├── Controllers
├── HomeController.cs
└── AccountController.cs
├── Program.cs
├── Startup.cs
├── project.json
├── .gitignore
└── Migrations
├── IdentityDbContextModelSnapshot.cs
├── 20161117120550_Initial.Designer.cs
└── 20161117120550_Initial.cs
/Views/_ViewStart.cshtml:
--------------------------------------------------------------------------------
1 | @{
2 | Layout = "_Layout";
3 | }
--------------------------------------------------------------------------------
/Views/_ViewImports.cshtml:
--------------------------------------------------------------------------------
1 | @addTagHelper "*, Microsoft.AspNetCore.Mvc.TagHelpers"
--------------------------------------------------------------------------------
/Views/Account/ForgotPassword.cshtml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
--------------------------------------------------------------------------------
/IMessageService.cs:
--------------------------------------------------------------------------------
1 | using System.Threading.Tasks;
2 |
3 | namespace AspNetIdentityFromScratch
4 | {
5 | public interface IMessageService
6 | {
7 | Task Send(string email, string subject, string message);
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM microsoft/dotnet:latest
2 |
3 | COPY . /app
4 |
5 | WORKDIR /app
6 |
7 | RUN ["dotnet", "restore"]
8 |
9 | RUN ["dotnet", "build"]
10 |
11 | EXPOSE 5000/tcp
12 |
13 | CMD ["dotnet", "run", "--server.urls", "http://*:5000"]
14 |
--------------------------------------------------------------------------------
/Properties/launchSettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "profiles": {
3 | "AspNetIdentityFromScratch": {
4 | "commandName": "Project",
5 | "launchBrowser": true,
6 | "launchUrl": "http://localhost:5000",
7 | "environmentVariables": {
8 | "ASPNETCORE_ENVIRONMENT": "Development"
9 | }
10 | }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ASP.NET Identity Core from Scratch
2 |
3 | This is an example ASP.NET Core (1.0.1) application with ASP.NET Identity Core built from scratch.
4 |
5 | A step by step guide on how to build this application (with user registration, email confirmation and password reset) is available here: [ASP.NET From Scratch](http://www.blinkingcaret.com/2016/11/30/asp-net-identity-core-from-scratch/)
6 |
7 |
--------------------------------------------------------------------------------
/Views/Shared/_Layout.cshtml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | @RenderBody()
12 |
13 |
14 |
--------------------------------------------------------------------------------
/.vscode/tasks.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": "0.1.0",
3 | "command": "dotnet",
4 | "isShellCommand": true,
5 | "args": [],
6 | "tasks": [
7 | {
8 | "taskName": "build",
9 | "args": [
10 | "${workspaceRoot}/project.json"
11 | ],
12 | "isBuildCommand": true,
13 | "problemMatcher": "$msCompile"
14 | }
15 | ]
16 | }
--------------------------------------------------------------------------------
/Views/Account/ResetPassword.cshtml:
--------------------------------------------------------------------------------
1 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/Views/Home/Index.cshtml:
--------------------------------------------------------------------------------
1 | Home
2 |
3 | @if (User.Identity.IsAuthenticated)
4 | {
5 | User @User.Identity.Name is signed in. Logout
6 |
7 | }
8 | else
9 | {
10 | No user is signed in.
11 | }
12 |
15 |
18 |
21 |
--------------------------------------------------------------------------------
/Views/Account/Register.cshtml:
--------------------------------------------------------------------------------
1 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/FileMessageService.cs:
--------------------------------------------------------------------------------
1 | using System.IO;
2 | using System.Threading.Tasks;
3 |
4 | namespace AspNetIdentityFromScratch
5 | {
6 | public class FileMessageService : IMessageService
7 | {
8 | Task IMessageService.Send(string email, string subject, string message)
9 | {
10 | var emailMessage = $"To: {email}\nSubject: {subject}\nMessage: {message}\n\n";
11 |
12 | File.AppendAllText("emails.txt", emailMessage);
13 |
14 | return Task.FromResult(0);
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/Views/Account/Login.cshtml:
--------------------------------------------------------------------------------
1 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/web.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/Controllers/HomeController.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Authorization;
2 | using Microsoft.AspNetCore.Mvc;
3 |
4 | // For more information on enabling MVC for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860
5 |
6 | namespace AspNetIdentityFromScratch.Controllers
7 | {
8 | public class HomeController : Controller
9 | {
10 | // GET: //
11 | public IActionResult Index()
12 | {
13 | return View();
14 | }
15 |
16 | [Authorize(Roles="Administrator")]
17 | public IActionResult RequiresAdmin()
18 | {
19 | return Content("OK");
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/Program.cs:
--------------------------------------------------------------------------------
1 | using System.IO;
2 | using Microsoft.AspNetCore.Hosting;
3 | using Microsoft.Extensions.Configuration;
4 |
5 | namespace AspNetIdentityFromScratch
6 | {
7 | public class Program
8 | {
9 | public static void Main(string[] args)
10 | {
11 | var config = new ConfigurationBuilder()
12 | .AddCommandLine(args)
13 | .AddEnvironmentVariables(prefix: "ASPNETCORE_")
14 | .Build();
15 |
16 | var host = new WebHostBuilder()
17 | .UseConfiguration(config)
18 | .UseKestrel()
19 | .UseContentRoot(Directory.GetCurrentDirectory())
20 | .UseIISIntegration()
21 | .UseStartup()
22 | .Build();
23 |
24 | host.Run();
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": "0.2.0",
3 | "configurations": [
4 | {
5 | "name": ".NET Core Launch (web)",
6 | "type": "coreclr",
7 | "request": "launch",
8 | "preLaunchTask": "build",
9 | "program": "${workspaceRoot}/bin/Debug/netcoreapp1.0/AspNetIdentityFromScratch.dll",
10 | "args": [],
11 | "cwd": "${workspaceRoot}",
12 | "stopAtEntry": false,
13 | "internalConsoleOptions": "openOnSessionStart",
14 | "launchBrowser": {
15 | "enabled": true,
16 | "args": "${auto-detect-url}",
17 | "windows": {
18 | "command": "cmd.exe",
19 | "args": "/C start ${auto-detect-url}"
20 | },
21 | "osx": {
22 | "command": "open"
23 | },
24 | "linux": {
25 | "command": "xdg-open"
26 | }
27 | },
28 | "env": {
29 | "ASPNETCORE_ENVIRONMENT": "Development"
30 | },
31 | "sourceFileMap": {
32 | "/Views": "${workspaceRoot}/Views"
33 | }
34 | },
35 | {
36 | "name": ".NET Core Attach",
37 | "type": "coreclr",
38 | "request": "attach",
39 | "processId": "${command.pickProcess}"
40 | }
41 | ]
42 | }
--------------------------------------------------------------------------------
/Startup.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Builder;
2 | using Microsoft.AspNetCore.Hosting;
3 | using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
4 | using Microsoft.Extensions.DependencyInjection;
5 | using Microsoft.Extensions.Logging;
6 | using Microsoft.EntityFrameworkCore;
7 |
8 | namespace AspNetIdentityFromScratch
9 | {
10 | public class Startup
11 | {
12 | public void ConfigureServices(IServiceCollection services)
13 | {
14 | services.AddMvc();
15 |
16 | services.AddDbContext(options =>
17 | options.UseSqlite("Data Source=users.sqlite",
18 | optionsBuilder => optionsBuilder.MigrationsAssembly("AspNetIdentityFromScratch")));
19 | services.AddIdentity()
20 | .AddEntityFrameworkStores()
21 | .AddDefaultTokenProviders();
22 |
23 | services.AddTransient();
24 | }
25 |
26 | public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, IdentityDbContext dbContext)
27 | {
28 | loggerFactory.AddConsole();
29 |
30 | if (env.IsDevelopment())
31 | {
32 | app.UseDeveloperExceptionPage();
33 | dbContext.Database.Migrate();
34 | }
35 |
36 | app.UseIdentity();
37 | app.UseStaticFiles();
38 | app.UseMvcWithDefaultRoute();
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/project.json:
--------------------------------------------------------------------------------
1 | {
2 | "dependencies": {
3 | "Microsoft.NETCore.App": {
4 | "version": "1.0.0",
5 | "type": "platform"
6 | },
7 | "Microsoft.AspNetCore.Diagnostics": "1.0.0",
8 | "Microsoft.AspNetCore.Server.IISIntegration": "1.0.0",
9 | "Microsoft.AspNetCore.Server.Kestrel": "1.0.1",
10 | "Microsoft.Extensions.Logging.Console": "1.0.0",
11 | "Microsoft.Extensions.Configuration.EnvironmentVariables": "1.0.0",
12 | "Microsoft.Extensions.Configuration.FileExtensions": "1.0.0",
13 | "Microsoft.Extensions.Configuration.Json": "1.0.0",
14 | "Microsoft.Extensions.Configuration.CommandLine": "1.0.0",
15 | "Microsoft.AspNetCore.Mvc": "1.0.1",
16 | "Microsoft.AspNetCore.StaticFiles": "1.1.0",
17 | "Microsoft.AspNetCore.Identity": "1.1.0",
18 | "Microsoft.AspNetCore.Identity.EntityFrameworkCore": "1.1.0",
19 | "Microsoft.EntityFrameworkCore.Sqlite": "1.1.0",
20 | "Microsoft.EntityFrameworkCore.Tools": "1.0.0-preview2-final"
21 | },
22 |
23 | "tools": {
24 | "Microsoft.AspNetCore.Server.IISIntegration.Tools": "1.0.0-preview2-final",
25 | "Microsoft.EntityFrameworkCore.Tools": "1.0.0-preview2-final"
26 | },
27 |
28 | "frameworks": {
29 | "netcoreapp1.0": {
30 | "imports": [
31 | "dotnet5.6",
32 | "portable-net45+win8"
33 | ]
34 | }
35 | },
36 |
37 | "buildOptions": {
38 | "emitEntryPoint": true,
39 | "preserveCompilationContext": true
40 | },
41 |
42 | "runtimeOptions": {
43 | "configProperties": {
44 | "System.GC.Server": true
45 | }
46 | },
47 |
48 | "publishOptions": {
49 | "include": [
50 | "wwwroot",
51 | "web.config"
52 | ]
53 | },
54 |
55 | "scripts": {
56 | "postpublish": [ "dotnet publish-iis --publish-folder %publish:OutputPath% --framework %publish:FullTargetFramework%" ]
57 | },
58 |
59 | "tooling": {
60 | "defaultNamespace": "AspNetIdentityFromScratch"
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 |
4 | # User-specific files
5 | *.suo
6 | *.user
7 | *.userosscache
8 | *.sln.docstates
9 |
10 | # User-specific files (MonoDevelop/Xamarin Studio)
11 | *.userprefs
12 |
13 | # Build results
14 | [Dd]ebug/
15 | [Dd]ebugPublic/
16 | [Rr]elease/
17 | [Rr]eleases/
18 | x64/
19 | x86/
20 | build/
21 | bld/
22 | [Bb]in/
23 | [Oo]bj/
24 |
25 | # Visual Studio 2015 cache/options directory
26 | .vs/
27 | # Uncomment if you have tasks that create the project's static files in wwwroot
28 | #wwwroot/
29 |
30 | # MSTest test Results
31 | [Tt]est[Rr]esult*/
32 | [Bb]uild[Ll]og.*
33 |
34 | # NUNIT
35 | *.VisualState.xml
36 | TestResult.xml
37 |
38 | # Build Results of an ATL Project
39 | [Dd]ebugPS/
40 | [Rr]eleasePS/
41 | dlldata.c
42 |
43 | # DNX
44 | project.lock.json
45 | artifacts/
46 |
47 | *_i.c
48 | *_p.c
49 | *_i.h
50 | *.ilk
51 | *.meta
52 | *.obj
53 | *.pch
54 | *.pdb
55 | *.pgc
56 | *.pgd
57 | *.rsp
58 | *.sbr
59 | *.tlb
60 | *.tli
61 | *.tlh
62 | *.tmp
63 | *.tmp_proj
64 | *.log
65 | *.vspscc
66 | *.vssscc
67 | .builds
68 | *.pidb
69 | *.svclog
70 | *.scc
71 |
72 | # Chutzpah Test files
73 | _Chutzpah*
74 |
75 | # Visual C++ cache files
76 | ipch/
77 | *.aps
78 | *.ncb
79 | *.opendb
80 | *.opensdf
81 | *.sdf
82 | *.cachefile
83 |
84 | # Visual Studio profiler
85 | *.psess
86 | *.vsp
87 | *.vspx
88 | *.sap
89 |
90 | # TFS 2012 Local Workspace
91 | $tf/
92 |
93 | # Guidance Automation Toolkit
94 | *.gpState
95 |
96 | # ReSharper is a .NET coding add-in
97 | _ReSharper*/
98 | *.[Rr]e[Ss]harper
99 | *.DotSettings.user
100 |
101 | # JustCode is a .NET coding add-in
102 | .JustCode
103 |
104 | # TeamCity is a build add-in
105 | _TeamCity*
106 |
107 | # DotCover is a Code Coverage Tool
108 | *.dotCover
109 |
110 | # NCrunch
111 | _NCrunch_*
112 | .*crunch*.local.xml
113 | nCrunchTemp_*
114 |
115 | # MightyMoose
116 | *.mm.*
117 | AutoTest.Net/
118 |
119 | # Web workbench (sass)
120 | .sass-cache/
121 |
122 | # Installshield output folder
123 | [Ee]xpress/
124 |
125 | # DocProject is a documentation generator add-in
126 | DocProject/buildhelp/
127 | DocProject/Help/*.HxT
128 | DocProject/Help/*.HxC
129 | DocProject/Help/*.hhc
130 | DocProject/Help/*.hhk
131 | DocProject/Help/*.hhp
132 | DocProject/Help/Html2
133 | DocProject/Help/html
134 |
135 | # Click-Once directory
136 | publish/
137 |
138 | # Publish Web Output
139 | *.[Pp]ublish.xml
140 | *.azurePubxml
141 | # TODO: Comment the next line if you want to checkin your web deploy settings
142 | # but database connection strings (with potential passwords) will be unencrypted
143 | *.pubxml
144 | *.publishproj
145 |
146 | # NuGet Packages
147 | *.nupkg
148 | # The packages folder can be ignored because of Package Restore
149 | **/packages/*
150 | # except build/, which is used as an MSBuild target.
151 | !**/packages/build/
152 | # Uncomment if necessary however generally it will be regenerated when needed
153 | #!**/packages/repositories.config
154 |
155 | # Microsoft Azure Build Output
156 | csx/
157 | *.build.csdef
158 |
159 | # Microsoft Azure Emulator
160 | ecf/
161 | rcf/
162 |
163 | # Microsoft Azure ApplicationInsights config file
164 | ApplicationInsights.config
165 |
166 | # Windows Store app package directory
167 | AppPackages/
168 | BundleArtifacts/
169 |
170 | # Visual Studio cache files
171 | # files ending in .cache can be ignored
172 | *.[Cc]ache
173 | # but keep track of directories ending in .cache
174 | !*.[Cc]ache/
175 |
176 | # Others
177 | ClientBin/
178 | ~$*
179 | *~
180 | *.dbmdl
181 | *.dbproj.schemaview
182 | *.pfx
183 | *.publishsettings
184 | node_modules/
185 | orleans.codegen.cs
186 |
187 | # RIA/Silverlight projects
188 | Generated_Code/
189 |
190 | # Backup & report files from converting an old project file
191 | # to a newer Visual Studio version. Backup files are not needed,
192 | # because we have git ;-)
193 | _UpgradeReport_Files/
194 | Backup*/
195 | UpgradeLog*.XML
196 | UpgradeLog*.htm
197 |
198 | # SQL Server files
199 | *.mdf
200 | *.ldf
201 |
202 | # Business Intelligence projects
203 | *.rdl.data
204 | *.bim.layout
205 | *.bim_*.settings
206 |
207 | # Microsoft Fakes
208 | FakesAssemblies/
209 |
210 | # GhostDoc plugin setting file
211 | *.GhostDoc.xml
212 |
213 | # Node.js Tools for Visual Studio
214 | .ntvs_analysis.dat
215 |
216 | # Visual Studio 6 build log
217 | *.plg
218 |
219 | # Visual Studio 6 workspace options file
220 | *.opt
221 |
222 | # Visual Studio LightSwitch build output
223 | **/*.HTMLClient/GeneratedArtifacts
224 | **/*.DesktopClient/GeneratedArtifacts
225 | **/*.DesktopClient/ModelManifest.xml
226 | **/*.Server/GeneratedArtifacts
227 | **/*.Server/ModelManifest.xml
228 | _Pvt_Extensions
229 |
230 | # Paket dependency manager
231 | .paket/paket.exe
232 |
233 | # FAKE - F# Make
234 | .fake/
235 |
--------------------------------------------------------------------------------
/Controllers/AccountController.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Linq;
3 | using System.Security.Claims;
4 | using System.Threading.Tasks;
5 | using Microsoft.AspNetCore.Identity;
6 | using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
7 | using Microsoft.AspNetCore.Mvc;
8 |
9 | namespace AspNetIdentityFromScratch.Controllers
10 | {
11 | public class AccountController : Controller
12 | {
13 | private readonly UserManager _userManager;
14 | private readonly SignInManager _signInManager;
15 | private readonly IMessageService _messageService;
16 | public AccountController(UserManager userManager, SignInManager signInManager, IMessageService messageService)
17 | {
18 | this._userManager = userManager;
19 | this._signInManager = signInManager;
20 | this._messageService = messageService;
21 | }
22 |
23 | public IActionResult Register()
24 | {
25 | return View();
26 | }
27 |
28 | [HttpPost]
29 |
30 | public async Task Register(string email, string password, string repassword)
31 | {
32 | if (password != repassword)
33 | {
34 | ModelState.AddModelError(string.Empty, "Password don't match");
35 | return View();
36 | }
37 |
38 | var newUser = new IdentityUser
39 | {
40 | UserName = email,
41 | Email = email
42 | };
43 |
44 | var userCreationResult = await _userManager.CreateAsync(newUser, password);
45 | if (!userCreationResult.Succeeded)
46 | {
47 | foreach(var error in userCreationResult.Errors)
48 | ModelState.AddModelError(string.Empty, error.Description);
49 | return View();
50 | }
51 |
52 | await _userManager.AddClaimAsync(newUser, new Claim(ClaimTypes.Role, "Administrator"));
53 |
54 |
55 | var emailConfirmationToken = await _userManager.GenerateEmailConfirmationTokenAsync(newUser);
56 | var tokenVerificationUrl = Url.Action("VerifyEmail", "Account", new {id = newUser.Id, token = emailConfirmationToken}, Request.Scheme);
57 |
58 | await _messageService.Send(email, "Verify your email", $"Click here to verify your email");
59 |
60 | return Content("Check your email for a verification link");
61 | }
62 |
63 |
64 | public async Task VerifyEmail(string id, string token)
65 | {
66 | var user = await _userManager.FindByIdAsync(id);
67 | if(user == null)
68 | throw new InvalidOperationException();
69 |
70 | var emailConfirmationResult = await _userManager.ConfirmEmailAsync(user, token);
71 | if (!emailConfirmationResult.Succeeded)
72 | return Content(emailConfirmationResult.Errors.Select(error => error.Description).Aggregate((allErrors, error) => allErrors += ", " + error));
73 |
74 | return Content("Email confirmed, you can now log in");
75 | }
76 |
77 | public IActionResult Login()
78 | {
79 | return View();
80 | }
81 |
82 | [HttpPost]
83 | public async Task Login(string email, string password, bool rememberMe)
84 | {
85 | var user = await _userManager.FindByEmailAsync(email);
86 | if (user == null)
87 | {
88 | ModelState.AddModelError(string.Empty, "Invalid login");
89 | return View();
90 | }
91 | if (!user.EmailConfirmed)
92 | {
93 | ModelState.AddModelError(string.Empty, "Confirm your email first");
94 | return View();
95 | }
96 |
97 | var passwordSignInResult = await _signInManager.PasswordSignInAsync(user, password, isPersistent: rememberMe, lockoutOnFailure: false);
98 |
99 | if (!passwordSignInResult.Succeeded)
100 | {
101 | await _userManager.AccessFailedAsync(user);
102 | ModelState.AddModelError(string.Empty, "Invalid login");
103 | return View();
104 | }
105 |
106 | return Redirect("~/");
107 | }
108 |
109 | public IActionResult ForgotPassword()
110 | {
111 | return View();
112 | }
113 |
114 | [HttpPost]
115 | public async Task ForgotPassword(string email)
116 | {
117 | var user = await _userManager.FindByEmailAsync(email);
118 | if (user == null)
119 | return Content("Check your email for a password reset link");
120 |
121 | var passwordResetToken = await _userManager.GeneratePasswordResetTokenAsync(user);
122 | var passwordResetUrl = Url.Action("ResetPassword", "Account", new {id = user.Id, token = passwordResetToken}, Request.Scheme);
123 |
124 | await _messageService.Send(email, "Password reset", $"Click here to reset your password");
125 |
126 | return Content("Check your email for a password reset link");
127 | }
128 |
129 | public IActionResult ResetPassword(string id, string token)
130 | {
131 | return View();
132 | }
133 |
134 | [HttpPost]
135 | public async Task ResetPassword(string id, string token, string password, string repassword)
136 | {
137 | var user = await _userManager.FindByIdAsync(id);
138 | if (user == null)
139 | throw new InvalidOperationException();
140 |
141 | if (password != repassword)
142 | {
143 | ModelState.AddModelError(string.Empty, "Passwords do not match");
144 | return View();
145 | }
146 |
147 | var resetPasswordResult = await _userManager.ResetPasswordAsync(user, token, password);
148 | if (!resetPasswordResult.Succeeded)
149 | {
150 | foreach(var error in resetPasswordResult.Errors)
151 | ModelState.AddModelError(string.Empty, error.Description);
152 | return View();
153 | }
154 |
155 | return Content("Password updated");
156 | }
157 | public async Task Logout()
158 | {
159 | await _signInManager.SignOutAsync();
160 | return Redirect("~/");
161 | }
162 | }
163 | }
164 |
--------------------------------------------------------------------------------
/Migrations/IdentityDbContextModelSnapshot.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Microsoft.EntityFrameworkCore;
3 | using Microsoft.EntityFrameworkCore.Infrastructure;
4 | using Microsoft.EntityFrameworkCore.Metadata;
5 | using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
6 |
7 | namespace AspNetIdentityFromScratch.Migrations
8 | {
9 | [DbContext(typeof(IdentityDbContext))]
10 | partial class IdentityDbContextModelSnapshot : ModelSnapshot
11 | {
12 | protected override void BuildModel(ModelBuilder modelBuilder)
13 | {
14 | modelBuilder
15 | .HasAnnotation("ProductVersion", "1.1.0-rtm-22752");
16 |
17 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityRole", b =>
18 | {
19 | b.Property("Id")
20 | .ValueGeneratedOnAdd();
21 |
22 | b.Property("ConcurrencyStamp")
23 | .IsConcurrencyToken();
24 |
25 | b.Property("Name")
26 | .HasAnnotation("MaxLength", 256);
27 |
28 | b.Property("NormalizedName")
29 | .HasAnnotation("MaxLength", 256);
30 |
31 | b.HasKey("Id");
32 |
33 | b.HasIndex("NormalizedName")
34 | .IsUnique()
35 | .HasName("RoleNameIndex");
36 |
37 | b.ToTable("AspNetRoles");
38 | });
39 |
40 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityRoleClaim", b =>
41 | {
42 | b.Property("Id")
43 | .ValueGeneratedOnAdd();
44 |
45 | b.Property("ClaimType");
46 |
47 | b.Property("ClaimValue");
48 |
49 | b.Property("RoleId")
50 | .IsRequired();
51 |
52 | b.HasKey("Id");
53 |
54 | b.HasIndex("RoleId");
55 |
56 | b.ToTable("AspNetRoleClaims");
57 | });
58 |
59 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUser", b =>
60 | {
61 | b.Property("Id")
62 | .ValueGeneratedOnAdd();
63 |
64 | b.Property("AccessFailedCount");
65 |
66 | b.Property("ConcurrencyStamp")
67 | .IsConcurrencyToken();
68 |
69 | b.Property("Email")
70 | .HasAnnotation("MaxLength", 256);
71 |
72 | b.Property("EmailConfirmed");
73 |
74 | b.Property("LockoutEnabled");
75 |
76 | b.Property("LockoutEnd");
77 |
78 | b.Property("NormalizedEmail")
79 | .HasAnnotation("MaxLength", 256);
80 |
81 | b.Property("NormalizedUserName")
82 | .HasAnnotation("MaxLength", 256);
83 |
84 | b.Property("PasswordHash");
85 |
86 | b.Property("PhoneNumber");
87 |
88 | b.Property("PhoneNumberConfirmed");
89 |
90 | b.Property("SecurityStamp");
91 |
92 | b.Property("TwoFactorEnabled");
93 |
94 | b.Property("UserName")
95 | .HasAnnotation("MaxLength", 256);
96 |
97 | b.HasKey("Id");
98 |
99 | b.HasIndex("NormalizedEmail")
100 | .HasName("EmailIndex");
101 |
102 | b.HasIndex("NormalizedUserName")
103 | .IsUnique()
104 | .HasName("UserNameIndex");
105 |
106 | b.ToTable("AspNetUsers");
107 | });
108 |
109 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserClaim", b =>
110 | {
111 | b.Property("Id")
112 | .ValueGeneratedOnAdd();
113 |
114 | b.Property("ClaimType");
115 |
116 | b.Property("ClaimValue");
117 |
118 | b.Property("UserId")
119 | .IsRequired();
120 |
121 | b.HasKey("Id");
122 |
123 | b.HasIndex("UserId");
124 |
125 | b.ToTable("AspNetUserClaims");
126 | });
127 |
128 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserLogin", b =>
129 | {
130 | b.Property("LoginProvider");
131 |
132 | b.Property("ProviderKey");
133 |
134 | b.Property("ProviderDisplayName");
135 |
136 | b.Property("UserId")
137 | .IsRequired();
138 |
139 | b.HasKey("LoginProvider", "ProviderKey");
140 |
141 | b.HasIndex("UserId");
142 |
143 | b.ToTable("AspNetUserLogins");
144 | });
145 |
146 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserRole", b =>
147 | {
148 | b.Property("UserId");
149 |
150 | b.Property("RoleId");
151 |
152 | b.HasKey("UserId", "RoleId");
153 |
154 | b.HasIndex("RoleId");
155 |
156 | b.ToTable("AspNetUserRoles");
157 | });
158 |
159 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserToken", b =>
160 | {
161 | b.Property("UserId");
162 |
163 | b.Property("LoginProvider");
164 |
165 | b.Property("Name");
166 |
167 | b.Property("Value");
168 |
169 | b.HasKey("UserId", "LoginProvider", "Name");
170 |
171 | b.ToTable("AspNetUserTokens");
172 | });
173 |
174 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityRoleClaim", b =>
175 | {
176 | b.HasOne("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityRole")
177 | .WithMany("Claims")
178 | .HasForeignKey("RoleId")
179 | .OnDelete(DeleteBehavior.Cascade);
180 | });
181 |
182 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserClaim", b =>
183 | {
184 | b.HasOne("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUser")
185 | .WithMany("Claims")
186 | .HasForeignKey("UserId")
187 | .OnDelete(DeleteBehavior.Cascade);
188 | });
189 |
190 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserLogin", b =>
191 | {
192 | b.HasOne("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUser")
193 | .WithMany("Logins")
194 | .HasForeignKey("UserId")
195 | .OnDelete(DeleteBehavior.Cascade);
196 | });
197 |
198 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserRole", b =>
199 | {
200 | b.HasOne("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityRole")
201 | .WithMany("Users")
202 | .HasForeignKey("RoleId")
203 | .OnDelete(DeleteBehavior.Cascade);
204 |
205 | b.HasOne("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUser")
206 | .WithMany("Roles")
207 | .HasForeignKey("UserId")
208 | .OnDelete(DeleteBehavior.Cascade);
209 | });
210 | }
211 | }
212 | }
213 |
--------------------------------------------------------------------------------
/Migrations/20161117120550_Initial.Designer.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Microsoft.EntityFrameworkCore;
3 | using Microsoft.EntityFrameworkCore.Infrastructure;
4 | using Microsoft.EntityFrameworkCore.Metadata;
5 | using Microsoft.EntityFrameworkCore.Migrations;
6 | using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
7 |
8 | namespace AspNetIdentityFromScratch.Migrations
9 | {
10 | [DbContext(typeof(IdentityDbContext))]
11 | [Migration("20161117120550_Initial")]
12 | partial class Initial
13 | {
14 | protected override void BuildTargetModel(ModelBuilder modelBuilder)
15 | {
16 | modelBuilder
17 | .HasAnnotation("ProductVersion", "1.1.0-rtm-22752");
18 |
19 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityRole", b =>
20 | {
21 | b.Property("Id")
22 | .ValueGeneratedOnAdd();
23 |
24 | b.Property("ConcurrencyStamp")
25 | .IsConcurrencyToken();
26 |
27 | b.Property("Name")
28 | .HasAnnotation("MaxLength", 256);
29 |
30 | b.Property("NormalizedName")
31 | .HasAnnotation("MaxLength", 256);
32 |
33 | b.HasKey("Id");
34 |
35 | b.HasIndex("NormalizedName")
36 | .IsUnique()
37 | .HasName("RoleNameIndex");
38 |
39 | b.ToTable("AspNetRoles");
40 | });
41 |
42 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityRoleClaim", b =>
43 | {
44 | b.Property("Id")
45 | .ValueGeneratedOnAdd();
46 |
47 | b.Property("ClaimType");
48 |
49 | b.Property("ClaimValue");
50 |
51 | b.Property("RoleId")
52 | .IsRequired();
53 |
54 | b.HasKey("Id");
55 |
56 | b.HasIndex("RoleId");
57 |
58 | b.ToTable("AspNetRoleClaims");
59 | });
60 |
61 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUser", b =>
62 | {
63 | b.Property("Id")
64 | .ValueGeneratedOnAdd();
65 |
66 | b.Property("AccessFailedCount");
67 |
68 | b.Property("ConcurrencyStamp")
69 | .IsConcurrencyToken();
70 |
71 | b.Property("Email")
72 | .HasAnnotation("MaxLength", 256);
73 |
74 | b.Property("EmailConfirmed");
75 |
76 | b.Property("LockoutEnabled");
77 |
78 | b.Property("LockoutEnd");
79 |
80 | b.Property("NormalizedEmail")
81 | .HasAnnotation("MaxLength", 256);
82 |
83 | b.Property("NormalizedUserName")
84 | .HasAnnotation("MaxLength", 256);
85 |
86 | b.Property("PasswordHash");
87 |
88 | b.Property("PhoneNumber");
89 |
90 | b.Property("PhoneNumberConfirmed");
91 |
92 | b.Property("SecurityStamp");
93 |
94 | b.Property("TwoFactorEnabled");
95 |
96 | b.Property("UserName")
97 | .HasAnnotation("MaxLength", 256);
98 |
99 | b.HasKey("Id");
100 |
101 | b.HasIndex("NormalizedEmail")
102 | .HasName("EmailIndex");
103 |
104 | b.HasIndex("NormalizedUserName")
105 | .IsUnique()
106 | .HasName("UserNameIndex");
107 |
108 | b.ToTable("AspNetUsers");
109 | });
110 |
111 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserClaim", b =>
112 | {
113 | b.Property("Id")
114 | .ValueGeneratedOnAdd();
115 |
116 | b.Property("ClaimType");
117 |
118 | b.Property("ClaimValue");
119 |
120 | b.Property("UserId")
121 | .IsRequired();
122 |
123 | b.HasKey("Id");
124 |
125 | b.HasIndex("UserId");
126 |
127 | b.ToTable("AspNetUserClaims");
128 | });
129 |
130 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserLogin", b =>
131 | {
132 | b.Property("LoginProvider");
133 |
134 | b.Property("ProviderKey");
135 |
136 | b.Property("ProviderDisplayName");
137 |
138 | b.Property("UserId")
139 | .IsRequired();
140 |
141 | b.HasKey("LoginProvider", "ProviderKey");
142 |
143 | b.HasIndex("UserId");
144 |
145 | b.ToTable("AspNetUserLogins");
146 | });
147 |
148 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserRole", b =>
149 | {
150 | b.Property("UserId");
151 |
152 | b.Property("RoleId");
153 |
154 | b.HasKey("UserId", "RoleId");
155 |
156 | b.HasIndex("RoleId");
157 |
158 | b.ToTable("AspNetUserRoles");
159 | });
160 |
161 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserToken", b =>
162 | {
163 | b.Property("UserId");
164 |
165 | b.Property("LoginProvider");
166 |
167 | b.Property("Name");
168 |
169 | b.Property("Value");
170 |
171 | b.HasKey("UserId", "LoginProvider", "Name");
172 |
173 | b.ToTable("AspNetUserTokens");
174 | });
175 |
176 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityRoleClaim", b =>
177 | {
178 | b.HasOne("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityRole")
179 | .WithMany("Claims")
180 | .HasForeignKey("RoleId")
181 | .OnDelete(DeleteBehavior.Cascade);
182 | });
183 |
184 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserClaim", b =>
185 | {
186 | b.HasOne("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUser")
187 | .WithMany("Claims")
188 | .HasForeignKey("UserId")
189 | .OnDelete(DeleteBehavior.Cascade);
190 | });
191 |
192 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserLogin", b =>
193 | {
194 | b.HasOne("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUser")
195 | .WithMany("Logins")
196 | .HasForeignKey("UserId")
197 | .OnDelete(DeleteBehavior.Cascade);
198 | });
199 |
200 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserRole", b =>
201 | {
202 | b.HasOne("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityRole")
203 | .WithMany("Users")
204 | .HasForeignKey("RoleId")
205 | .OnDelete(DeleteBehavior.Cascade);
206 |
207 | b.HasOne("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUser")
208 | .WithMany("Roles")
209 | .HasForeignKey("UserId")
210 | .OnDelete(DeleteBehavior.Cascade);
211 | });
212 | }
213 | }
214 | }
215 |
--------------------------------------------------------------------------------
/Migrations/20161117120550_Initial.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Microsoft.EntityFrameworkCore.Migrations;
3 |
4 | namespace AspNetIdentityFromScratch.Migrations
5 | {
6 | public partial class Initial : Migration
7 | {
8 | protected override void Up(MigrationBuilder migrationBuilder)
9 | {
10 | migrationBuilder.CreateTable(
11 | name: "AspNetRoles",
12 | columns: table => new
13 | {
14 | Id = table.Column(nullable: false),
15 | ConcurrencyStamp = table.Column(nullable: true),
16 | Name = table.Column(maxLength: 256, nullable: true),
17 | NormalizedName = table.Column(maxLength: 256, nullable: true)
18 | },
19 | constraints: table =>
20 | {
21 | table.PrimaryKey("PK_AspNetRoles", x => x.Id);
22 | });
23 |
24 | migrationBuilder.CreateTable(
25 | name: "AspNetUsers",
26 | columns: table => new
27 | {
28 | Id = table.Column(nullable: false),
29 | AccessFailedCount = table.Column(nullable: false),
30 | ConcurrencyStamp = table.Column(nullable: true),
31 | Email = table.Column(maxLength: 256, nullable: true),
32 | EmailConfirmed = table.Column(nullable: false),
33 | LockoutEnabled = table.Column(nullable: false),
34 | LockoutEnd = table.Column(nullable: true),
35 | NormalizedEmail = table.Column(maxLength: 256, nullable: true),
36 | NormalizedUserName = table.Column(maxLength: 256, nullable: true),
37 | PasswordHash = table.Column(nullable: true),
38 | PhoneNumber = table.Column(nullable: true),
39 | PhoneNumberConfirmed = table.Column(nullable: false),
40 | SecurityStamp = table.Column(nullable: true),
41 | TwoFactorEnabled = table.Column(nullable: false),
42 | UserName = table.Column(maxLength: 256, nullable: true)
43 | },
44 | constraints: table =>
45 | {
46 | table.PrimaryKey("PK_AspNetUsers", x => x.Id);
47 | });
48 |
49 | migrationBuilder.CreateTable(
50 | name: "AspNetUserTokens",
51 | columns: table => new
52 | {
53 | UserId = table.Column(nullable: false),
54 | LoginProvider = table.Column(nullable: false),
55 | Name = table.Column(nullable: false),
56 | Value = table.Column(nullable: true)
57 | },
58 | constraints: table =>
59 | {
60 | table.PrimaryKey("PK_AspNetUserTokens", x => new { x.UserId, x.LoginProvider, x.Name });
61 | });
62 |
63 | migrationBuilder.CreateTable(
64 | name: "AspNetRoleClaims",
65 | columns: table => new
66 | {
67 | Id = table.Column(nullable: false)
68 | .Annotation("Sqlite:Autoincrement", true),
69 | ClaimType = table.Column(nullable: true),
70 | ClaimValue = table.Column(nullable: true),
71 | RoleId = table.Column(nullable: false)
72 | },
73 | constraints: table =>
74 | {
75 | table.PrimaryKey("PK_AspNetRoleClaims", x => x.Id);
76 | table.ForeignKey(
77 | name: "FK_AspNetRoleClaims_AspNetRoles_RoleId",
78 | column: x => x.RoleId,
79 | principalTable: "AspNetRoles",
80 | principalColumn: "Id",
81 | onDelete: ReferentialAction.Cascade);
82 | });
83 |
84 | migrationBuilder.CreateTable(
85 | name: "AspNetUserClaims",
86 | columns: table => new
87 | {
88 | Id = table.Column(nullable: false)
89 | .Annotation("Sqlite:Autoincrement", true),
90 | ClaimType = table.Column(nullable: true),
91 | ClaimValue = table.Column(nullable: true),
92 | UserId = table.Column(nullable: false)
93 | },
94 | constraints: table =>
95 | {
96 | table.PrimaryKey("PK_AspNetUserClaims", x => x.Id);
97 | table.ForeignKey(
98 | name: "FK_AspNetUserClaims_AspNetUsers_UserId",
99 | column: x => x.UserId,
100 | principalTable: "AspNetUsers",
101 | principalColumn: "Id",
102 | onDelete: ReferentialAction.Cascade);
103 | });
104 |
105 | migrationBuilder.CreateTable(
106 | name: "AspNetUserLogins",
107 | columns: table => new
108 | {
109 | LoginProvider = table.Column(nullable: false),
110 | ProviderKey = table.Column(nullable: false),
111 | ProviderDisplayName = table.Column(nullable: true),
112 | UserId = table.Column(nullable: false)
113 | },
114 | constraints: table =>
115 | {
116 | table.PrimaryKey("PK_AspNetUserLogins", x => new { x.LoginProvider, x.ProviderKey });
117 | table.ForeignKey(
118 | name: "FK_AspNetUserLogins_AspNetUsers_UserId",
119 | column: x => x.UserId,
120 | principalTable: "AspNetUsers",
121 | principalColumn: "Id",
122 | onDelete: ReferentialAction.Cascade);
123 | });
124 |
125 | migrationBuilder.CreateTable(
126 | name: "AspNetUserRoles",
127 | columns: table => new
128 | {
129 | UserId = table.Column(nullable: false),
130 | RoleId = table.Column(nullable: false)
131 | },
132 | constraints: table =>
133 | {
134 | table.PrimaryKey("PK_AspNetUserRoles", x => new { x.UserId, x.RoleId });
135 | table.ForeignKey(
136 | name: "FK_AspNetUserRoles_AspNetRoles_RoleId",
137 | column: x => x.RoleId,
138 | principalTable: "AspNetRoles",
139 | principalColumn: "Id",
140 | onDelete: ReferentialAction.Cascade);
141 | table.ForeignKey(
142 | name: "FK_AspNetUserRoles_AspNetUsers_UserId",
143 | column: x => x.UserId,
144 | principalTable: "AspNetUsers",
145 | principalColumn: "Id",
146 | onDelete: ReferentialAction.Cascade);
147 | });
148 |
149 | migrationBuilder.CreateIndex(
150 | name: "RoleNameIndex",
151 | table: "AspNetRoles",
152 | column: "NormalizedName",
153 | unique: true);
154 |
155 | migrationBuilder.CreateIndex(
156 | name: "IX_AspNetRoleClaims_RoleId",
157 | table: "AspNetRoleClaims",
158 | column: "RoleId");
159 |
160 | migrationBuilder.CreateIndex(
161 | name: "EmailIndex",
162 | table: "AspNetUsers",
163 | column: "NormalizedEmail");
164 |
165 | migrationBuilder.CreateIndex(
166 | name: "UserNameIndex",
167 | table: "AspNetUsers",
168 | column: "NormalizedUserName",
169 | unique: true);
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 |
187 | protected override void Down(MigrationBuilder migrationBuilder)
188 | {
189 | migrationBuilder.DropTable(
190 | name: "AspNetRoleClaims");
191 |
192 | migrationBuilder.DropTable(
193 | name: "AspNetUserClaims");
194 |
195 | migrationBuilder.DropTable(
196 | name: "AspNetUserLogins");
197 |
198 | migrationBuilder.DropTable(
199 | name: "AspNetUserRoles");
200 |
201 | migrationBuilder.DropTable(
202 | name: "AspNetUserTokens");
203 |
204 | migrationBuilder.DropTable(
205 | name: "AspNetRoles");
206 |
207 | migrationBuilder.DropTable(
208 | name: "AspNetUsers");
209 | }
210 | }
211 | }
212 |
--------------------------------------------------------------------------------