├── README.md
├── DosFactores
├── wwwroot
│ ├── js
│ │ ├── site.min.js
│ │ └── site.js
│ ├── favicon.ico
│ ├── lib
│ │ ├── bootstrap
│ │ │ ├── dist
│ │ │ │ ├── fonts
│ │ │ │ │ ├── glyphicons-halflings-regular.eot
│ │ │ │ │ ├── glyphicons-halflings-regular.ttf
│ │ │ │ │ ├── glyphicons-halflings-regular.woff
│ │ │ │ │ └── glyphicons-halflings-regular.woff2
│ │ │ │ └── js
│ │ │ │ │ └── npm.js
│ │ │ ├── .bower.json
│ │ │ └── LICENSE
│ │ ├── jquery
│ │ │ ├── .bower.json
│ │ │ └── LICENSE.txt
│ │ ├── jquery-validation
│ │ │ ├── .bower.json
│ │ │ ├── LICENSE.md
│ │ │ └── dist
│ │ │ │ └── additional-methods.min.js
│ │ └── jquery-validation-unobtrusive
│ │ │ ├── .bower.json
│ │ │ └── jquery.validate.unobtrusive.min.js
│ ├── css
│ │ ├── site.min.css
│ │ └── site.css
│ └── images
│ │ ├── banner2.svg
│ │ ├── banner1.svg
│ │ ├── banner3.svg
│ │ └── banner4.svg
├── .bowerrc
├── Views
│ ├── _ViewStart.cshtml
│ ├── Home
│ │ ├── About.cshtml
│ │ ├── Contact.cshtml
│ │ └── Index.cshtml
│ ├── Account
│ │ ├── ForgotPasswordConfirmation.cshtml
│ │ ├── ExternalLoginFailure.cshtml
│ │ ├── AccessDenied.cshtml
│ │ ├── Lockout.cshtml
│ │ ├── ResetPasswordConfirmation.cshtml
│ │ ├── ConfirmEmail.cshtml
│ │ ├── SendCode.cshtml
│ │ ├── ForgotPassword.cshtml
│ │ ├── ExternalLoginConfirmation.cshtml
│ │ ├── VerifyCode.cshtml
│ │ ├── Register.cshtml
│ │ ├── ResetPassword.cshtml
│ │ └── Login.cshtml
│ ├── _ViewImports.cshtml
│ ├── Shared
│ │ ├── Error.cshtml
│ │ ├── _LoginPartial.cshtml
│ │ ├── _ValidationScriptsPartial.cshtml
│ │ └── _Layout.cshtml
│ └── Manage
│ │ ├── AddPhoneNumber.cshtml
│ │ ├── VerifyPhoneNumber.cshtml
│ │ ├── SetPassword.cshtml
│ │ ├── ChangePassword.cshtml
│ │ ├── ManageLogins.cshtml
│ │ └── Index.cshtml
├── appsettings.Development.json
├── bower.json
├── Services
│ ├── ISmsSender.cs
│ ├── IEmailSender.cs
│ └── MessageServices.cs
├── Models
│ ├── ManageViewModels
│ │ ├── FactorViewModel.cs
│ │ ├── RemoveLoginViewModel.cs
│ │ ├── AddPhoneNumberViewModel.cs
│ │ ├── ConfigureTwoFactorViewModel.cs
│ │ ├── ManageLoginsViewModel.cs
│ │ ├── VerifyPhoneNumberViewModel.cs
│ │ ├── IndexViewModel.cs
│ │ ├── SetPasswordViewModel.cs
│ │ └── ChangePasswordViewModel.cs
│ ├── AccountViewModels
│ │ ├── ForgotPasswordViewModel.cs
│ │ ├── ExternalLoginConfirmationViewModel.cs
│ │ ├── SendCodeViewModel.cs
│ │ ├── LoginViewModel.cs
│ │ ├── VerifyCodeViewModel.cs
│ │ ├── ResetPasswordViewModel.cs
│ │ └── RegisterViewModel.cs
│ └── ApplicationUser.cs
├── appsettings.json
├── Program.cs
├── bundleconfig.json
├── Controllers
│ ├── HomeController.cs
│ └── ManageController.cs
├── Data
│ ├── ApplicationDbContext.cs
│ └── Migrations
│ │ ├── ApplicationDbContextModelSnapshot.cs
│ │ ├── 00000000000000_CreateIdentitySchema.Designer.cs
│ │ └── 00000000000000_CreateIdentitySchema.cs
├── GoogleAuthenticatorProvider.cs
├── DosFactores.csproj
└── Startup.cs
├── Google.Authenticator
├── Google.Authenticator.csproj
├── SetupCode.cs
└── TwoFactorAuthenticator.cs
├── DosFactores.sln
└── .gitignore
/README.md:
--------------------------------------------------------------------------------
1 | # DosFactores
--------------------------------------------------------------------------------
/DosFactores/wwwroot/js/site.min.js:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/DosFactores/.bowerrc:
--------------------------------------------------------------------------------
1 | {
2 | "directory": "wwwroot/lib"
3 | }
4 |
--------------------------------------------------------------------------------
/DosFactores/wwwroot/js/site.js:
--------------------------------------------------------------------------------
1 | // Write your Javascript code.
2 |
--------------------------------------------------------------------------------
/DosFactores/Views/_ViewStart.cshtml:
--------------------------------------------------------------------------------
1 | @{
2 | Layout = "_Layout";
3 | }
4 |
--------------------------------------------------------------------------------
/DosFactores/wwwroot/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thatcsharpguy/Dos_Factores/master/DosFactores/wwwroot/favicon.ico
--------------------------------------------------------------------------------
/Google.Authenticator/Google.Authenticator.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp1.1
5 |
6 |
7 |
--------------------------------------------------------------------------------
/DosFactores/Views/Home/About.cshtml:
--------------------------------------------------------------------------------
1 | @{
2 | ViewData["Title"] = "About";
3 | }
4 |
@ViewData["Title"].
5 | @ViewData["Message"]
6 |
7 | Use this area to provide additional information.
8 |
--------------------------------------------------------------------------------
/DosFactores/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thatcsharpguy/Dos_Factores/master/DosFactores/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.eot
--------------------------------------------------------------------------------
/DosFactores/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thatcsharpguy/Dos_Factores/master/DosFactores/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.ttf
--------------------------------------------------------------------------------
/DosFactores/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thatcsharpguy/Dos_Factores/master/DosFactores/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.woff
--------------------------------------------------------------------------------
/DosFactores/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thatcsharpguy/Dos_Factores/master/DosFactores/wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.woff2
--------------------------------------------------------------------------------
/DosFactores/Views/Account/ForgotPasswordConfirmation.cshtml:
--------------------------------------------------------------------------------
1 | @{
2 | ViewData["Title"] = "Forgot Password Confirmation";
3 | }
4 |
5 | @ViewData["Title"].
6 |
7 | Please check your email to reset your password.
8 |
9 |
--------------------------------------------------------------------------------
/DosFactores/Views/Account/ExternalLoginFailure.cshtml:
--------------------------------------------------------------------------------
1 | @{
2 | ViewData["Title"] = "Login Failure";
3 | }
4 |
5 |
9 |
--------------------------------------------------------------------------------
/DosFactores/appsettings.Development.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "IncludeScopes": false,
4 | "LogLevel": {
5 | "Default": "Debug",
6 | "System": "Information",
7 | "Microsoft": "Information"
8 | }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/DosFactores/Views/Account/AccessDenied.cshtml:
--------------------------------------------------------------------------------
1 | @{
2 | ViewData["Title"] = "Access Denied";
3 | }
4 |
5 |
9 |
--------------------------------------------------------------------------------
/DosFactores/Views/Account/Lockout.cshtml:
--------------------------------------------------------------------------------
1 | @{
2 | ViewData["Title"] = "Locked out";
3 | }
4 |
5 |
9 |
--------------------------------------------------------------------------------
/DosFactores/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "asp.net",
3 | "private": true,
4 | "dependencies": {
5 | "bootstrap": "3.3.7",
6 | "jquery": "2.2.0",
7 | "jquery-validation": "1.14.0",
8 | "jquery-validation-unobtrusive": "3.2.6"
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/DosFactores/Views/_ViewImports.cshtml:
--------------------------------------------------------------------------------
1 | @using DosFactores
2 | @using DosFactores.Models
3 | @using DosFactores.Models.AccountViewModels
4 | @using DosFactores.Models.ManageViewModels
5 | @using Microsoft.AspNetCore.Identity
6 | @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
7 |
--------------------------------------------------------------------------------
/DosFactores/Views/Account/ResetPasswordConfirmation.cshtml:
--------------------------------------------------------------------------------
1 | @{
2 | ViewData["Title"] = "Reset password confirmation";
3 | }
4 |
5 | @ViewData["Title"].
6 |
7 | Your password has been reset. Please Click here to log in.
8 |
9 |
--------------------------------------------------------------------------------
/DosFactores/Views/Account/ConfirmEmail.cshtml:
--------------------------------------------------------------------------------
1 | @{
2 | ViewData["Title"] = "Confirm Email";
3 | }
4 |
5 | @ViewData["Title"].
6 |
11 |
--------------------------------------------------------------------------------
/DosFactores/Services/ISmsSender.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 |
6 | namespace DosFactores.Services
7 | {
8 | public interface ISmsSender
9 | {
10 | Task SendSmsAsync(string number, string message);
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/DosFactores/Models/ManageViewModels/FactorViewModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 |
6 | namespace DosFactores.Models.ManageViewModels
7 | {
8 | public class FactorViewModel
9 | {
10 | public string Purpose { get; set; }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/DosFactores/Services/IEmailSender.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 |
6 | namespace DosFactores.Services
7 | {
8 | public interface IEmailSender
9 | {
10 | Task SendEmailAsync(string email, string subject, string message);
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/DosFactores/appsettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "ConnectionStrings": {
3 | "DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=aspnet-DosFactores-c2604328-7fd4-4ec1-bfad-0807bbc87745;Trusted_Connection=True;MultipleActiveResultSets=true"
4 | },
5 | "Logging": {
6 | "IncludeScopes": false,
7 | "LogLevel": {
8 | "Default": "Warning"
9 | }
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/DosFactores/Models/AccountViewModels/ForgotPasswordViewModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel.DataAnnotations;
4 | using System.Linq;
5 | using System.Threading.Tasks;
6 |
7 | namespace DosFactores.Models.AccountViewModels
8 | {
9 | public class ForgotPasswordViewModel
10 | {
11 | [Required]
12 | [EmailAddress]
13 | public string Email { get; set; }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/DosFactores/Models/ManageViewModels/RemoveLoginViewModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel.DataAnnotations;
4 | using System.Linq;
5 | using System.Threading.Tasks;
6 |
7 | namespace DosFactores.Models.ManageViewModels
8 | {
9 | public class RemoveLoginViewModel
10 | {
11 | public string LoginProvider { get; set; }
12 | public string ProviderKey { get; set; }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/DosFactores/wwwroot/css/site.min.css:
--------------------------------------------------------------------------------
1 | body{padding-top:50px;padding-bottom:20px}.body-content{padding-left:15px;padding-right:15px}input,select,textarea{max-width:280px}.carousel-caption p{font-size:20px;line-height:1.4}.btn-bracketed::before{display:inline-block;content:"[";padding-right:.5em}.btn-bracketed::after{display:inline-block;content:"]";padding-left:.5em}.carousel-inner .item img[src$=".svg"]{width:100%}@media screen and (max-width:767px){.carousel-caption{display:none}}
--------------------------------------------------------------------------------
/Google.Authenticator/SetupCode.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 |
5 | namespace Google.Authenticator
6 | {
7 | public class SetupCode
8 | {
9 | public string Account { get; internal set; }
10 | public string AccountSecretKey { get; internal set; }
11 | public string ManualEntryKey { get; internal set; }
12 | public string QrCodeSetupImageUrl { get; internal set; }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/DosFactores/Models/AccountViewModels/ExternalLoginConfirmationViewModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel.DataAnnotations;
4 | using System.Linq;
5 | using System.Threading.Tasks;
6 |
7 | namespace DosFactores.Models.AccountViewModels
8 | {
9 | public class ExternalLoginConfirmationViewModel
10 | {
11 | [Required]
12 | [EmailAddress]
13 | public string Email { get; set; }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/DosFactores/Models/ApplicationUser.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 | using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
6 |
7 | namespace DosFactores.Models
8 | {
9 | // Add profile data for application users by adding properties to the ApplicationUser class
10 | public class ApplicationUser : IdentityUser
11 | {
12 | public virtual string TfaKey { get; set; }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/DosFactores/Models/ManageViewModels/AddPhoneNumberViewModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel.DataAnnotations;
4 | using System.Linq;
5 | using System.Threading.Tasks;
6 |
7 | namespace DosFactores.Models.ManageViewModels
8 | {
9 | public class AddPhoneNumberViewModel
10 | {
11 | [Required]
12 | [Phone]
13 | [Display(Name = "Phone number")]
14 | public string PhoneNumber { get; set; }
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/DosFactores/Models/ManageViewModels/ConfigureTwoFactorViewModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 | using Microsoft.AspNetCore.Mvc.Rendering;
6 |
7 | namespace DosFactores.Models.ManageViewModels
8 | {
9 | public class ConfigureTwoFactorViewModel
10 | {
11 | public string SelectedProvider { get; set; }
12 |
13 | public ICollection Providers { get; set; }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/DosFactores/Models/ManageViewModels/ManageLoginsViewModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 | using Microsoft.AspNetCore.Http.Authentication;
6 | using Microsoft.AspNetCore.Identity;
7 |
8 | namespace DosFactores.Models.ManageViewModels
9 | {
10 | public class ManageLoginsViewModel
11 | {
12 | public IList CurrentLogins { get; set; }
13 |
14 | public IList OtherLogins { get; set; }
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/DosFactores/Views/Home/Contact.cshtml:
--------------------------------------------------------------------------------
1 | @{
2 | ViewData["Title"] = "Contact";
3 | }
4 | @ViewData["Title"].
5 | @ViewData["Message"]
6 |
7 |
8 | One Microsoft Way
9 | Redmond, WA 98052-6399
10 | P:
11 | 425.555.0100
12 |
13 |
14 |
15 | Support: Support@example.com
16 | Marketing: Marketing@example.com
17 |
18 |
--------------------------------------------------------------------------------
/DosFactores/wwwroot/lib/bootstrap/dist/js/npm.js:
--------------------------------------------------------------------------------
1 | // This file is autogenerated via the `commonjs` Grunt task. You can require() this file in a CommonJS environment.
2 | require('../../js/transition.js')
3 | require('../../js/alert.js')
4 | require('../../js/button.js')
5 | require('../../js/carousel.js')
6 | require('../../js/collapse.js')
7 | require('../../js/dropdown.js')
8 | require('../../js/modal.js')
9 | require('../../js/tooltip.js')
10 | require('../../js/popover.js')
11 | require('../../js/scrollspy.js')
12 | require('../../js/tab.js')
13 | require('../../js/affix.js')
--------------------------------------------------------------------------------
/DosFactores/Models/ManageViewModels/VerifyPhoneNumberViewModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel.DataAnnotations;
4 | using System.Linq;
5 | using System.Threading.Tasks;
6 |
7 | namespace DosFactores.Models.ManageViewModels
8 | {
9 | public class VerifyPhoneNumberViewModel
10 | {
11 | [Required]
12 | public string Code { get; set; }
13 |
14 | [Required]
15 | [Phone]
16 | [Display(Name = "Phone number")]
17 | public string PhoneNumber { get; set; }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/DosFactores/Models/AccountViewModels/SendCodeViewModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 | using Microsoft.AspNetCore.Mvc.Rendering;
6 |
7 | namespace DosFactores.Models.AccountViewModels
8 | {
9 | public class SendCodeViewModel
10 | {
11 | public string SelectedProvider { get; set; }
12 |
13 | public ICollection Providers { get; set; }
14 |
15 | public string ReturnUrl { get; set; }
16 |
17 | public bool RememberMe { get; set; }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/DosFactores/Models/AccountViewModels/LoginViewModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel.DataAnnotations;
4 | using System.Linq;
5 | using System.Threading.Tasks;
6 |
7 | namespace DosFactores.Models.AccountViewModels
8 | {
9 | public class LoginViewModel
10 | {
11 | [Required]
12 | [EmailAddress]
13 | public string Email { get; set; }
14 |
15 | [Required]
16 | [DataType(DataType.Password)]
17 | public string Password { get; set; }
18 |
19 | [Display(Name = "Remember me?")]
20 | public bool RememberMe { get; set; }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/DosFactores/wwwroot/lib/jquery/.bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "jquery",
3 | "main": "dist/jquery.js",
4 | "license": "MIT",
5 | "ignore": [
6 | "package.json"
7 | ],
8 | "keywords": [
9 | "jquery",
10 | "javascript",
11 | "browser",
12 | "library"
13 | ],
14 | "homepage": "https://github.com/jquery/jquery-dist",
15 | "version": "2.2.0",
16 | "_release": "2.2.0",
17 | "_resolution": {
18 | "type": "version",
19 | "tag": "2.2.0",
20 | "commit": "6fc01e29bdad0964f62ef56d01297039cdcadbe5"
21 | },
22 | "_source": "git://github.com/jquery/jquery-dist.git",
23 | "_target": "2.2.0",
24 | "_originalSource": "jquery"
25 | }
--------------------------------------------------------------------------------
/DosFactores/Models/ManageViewModels/IndexViewModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 | using Microsoft.AspNetCore.Identity;
6 |
7 | namespace DosFactores.Models.ManageViewModels
8 | {
9 | public class IndexViewModel
10 | {
11 | public bool HasPassword { get; set; }
12 |
13 | public IList Logins { get; set; }
14 |
15 | public string PhoneNumber { get; set; }
16 |
17 | public string TwoFactorAuthenticatorQrCode { get; set; }
18 |
19 | public bool TwoFactor { get; set; }
20 |
21 | public bool BrowserRemembered { get; set; }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/DosFactores/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Threading.Tasks;
6 | using Microsoft.AspNetCore.Hosting;
7 |
8 | namespace DosFactores
9 | {
10 | public class Program
11 | {
12 | public static void Main(string[] args)
13 | {
14 | var host = new WebHostBuilder()
15 | .UseKestrel()
16 | .UseContentRoot(Directory.GetCurrentDirectory())
17 | .UseIISIntegration()
18 | .UseStartup()
19 | .UseApplicationInsights()
20 | .Build();
21 |
22 | host.Run();
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/DosFactores/bundleconfig.json:
--------------------------------------------------------------------------------
1 | // Configure bundling and minification for the project.
2 | // More info at https://go.microsoft.com/fwlink/?LinkId=808241
3 | [
4 | {
5 | "outputFileName": "wwwroot/css/site.min.css",
6 | // An array of relative input file paths. Globbing patterns supported
7 | "inputFiles": [
8 | "wwwroot/css/site.css"
9 | ]
10 | },
11 | {
12 | "outputFileName": "wwwroot/js/site.min.js",
13 | "inputFiles": [
14 | "wwwroot/js/site.js"
15 | ],
16 | // Optionally specify minification options
17 | "minify": {
18 | "enabled": true,
19 | "renameLocals": true
20 | },
21 | // Optionally generate .map file
22 | "sourceMap": false
23 | }
24 | ]
25 |
--------------------------------------------------------------------------------
/DosFactores/Models/AccountViewModels/VerifyCodeViewModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel.DataAnnotations;
4 | using System.Linq;
5 | using System.Threading.Tasks;
6 |
7 | namespace DosFactores.Models.AccountViewModels
8 | {
9 | public class VerifyCodeViewModel
10 | {
11 | [Required]
12 | public string Provider { get; set; }
13 |
14 | [Required]
15 | public string Code { get; set; }
16 |
17 | public string ReturnUrl { get; set; }
18 |
19 | [Display(Name = "Remember this browser?")]
20 | public bool RememberBrowser { get; set; }
21 |
22 | [Display(Name = "Remember me?")]
23 | public bool RememberMe { get; set; }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/DosFactores/Views/Shared/Error.cshtml:
--------------------------------------------------------------------------------
1 | @{
2 | ViewData["Title"] = "Error";
3 | }
4 |
5 | Error.
6 | An error occurred while processing your request.
7 |
8 | Development Mode
9 |
10 | Swapping to Development environment will display more detailed information about the error that occurred.
11 |
12 |
13 | Development environment should not be enabled in deployed applications, as it can result in sensitive information from exceptions being displayed to end users. For local debugging, development environment can be enabled by setting the ASPNETCORE_ENVIRONMENT environment variable to Development, and restarting the application.
14 |
15 |
--------------------------------------------------------------------------------
/DosFactores/Views/Account/SendCode.cshtml:
--------------------------------------------------------------------------------
1 | @model SendCodeViewModel
2 | @{
3 | ViewData["Title"] = "Send Verification Code";
4 | }
5 |
6 | @ViewData["Title"].
7 |
8 |
18 |
19 | @section Scripts {
20 | @{await Html.RenderPartialAsync("_ValidationScriptsPartial"); }
21 | }
22 |
--------------------------------------------------------------------------------
/DosFactores/Controllers/HomeController.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 | using Microsoft.AspNetCore.Mvc;
6 |
7 | namespace DosFactores.Controllers
8 | {
9 | public class HomeController : Controller
10 | {
11 | public IActionResult Index()
12 | {
13 | return View();
14 | }
15 |
16 | public IActionResult About()
17 | {
18 | ViewData["Message"] = "Your application description page.";
19 |
20 | return View();
21 | }
22 |
23 | public IActionResult Contact()
24 | {
25 | ViewData["Message"] = "Your contact page.";
26 |
27 | return View();
28 | }
29 |
30 | public IActionResult Error()
31 | {
32 | return View();
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/DosFactores/Models/ManageViewModels/SetPasswordViewModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel.DataAnnotations;
4 | using System.Linq;
5 | using System.Threading.Tasks;
6 |
7 | namespace DosFactores.Models.ManageViewModels
8 | {
9 | public class SetPasswordViewModel
10 | {
11 | [Required]
12 | [StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)]
13 | [DataType(DataType.Password)]
14 | [Display(Name = "New password")]
15 | public string NewPassword { get; set; }
16 |
17 | [DataType(DataType.Password)]
18 | [Display(Name = "Confirm new password")]
19 | [Compare("NewPassword", ErrorMessage = "The new password and confirmation password do not match.")]
20 | public string ConfirmPassword { get; set; }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/DosFactores/Services/MessageServices.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 |
6 | namespace DosFactores.Services
7 | {
8 | // This class is used by the application to send Email and SMS
9 | // when you turn on two-factor authentication in ASP.NET Identity.
10 | // For more details see this link https://go.microsoft.com/fwlink/?LinkID=532713
11 | public class AuthMessageSender : IEmailSender, ISmsSender
12 | {
13 | public Task SendEmailAsync(string email, string subject, string message)
14 | {
15 | // Plug in your email service here to send an email.
16 | return Task.FromResult(0);
17 | }
18 |
19 | public Task SendSmsAsync(string number, string message)
20 | {
21 | // Plug in your SMS service here to send a text message.
22 | return Task.FromResult(0);
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/DosFactores/Data/ApplicationDbContext.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 | using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
6 | using Microsoft.EntityFrameworkCore;
7 | using DosFactores.Models;
8 |
9 | namespace DosFactores.Data
10 | {
11 | public class ApplicationDbContext : IdentityDbContext
12 | {
13 | public ApplicationDbContext(DbContextOptions options)
14 | : base(options)
15 | {
16 | }
17 |
18 | protected override void OnModelCreating(ModelBuilder builder)
19 | {
20 | base.OnModelCreating(builder);
21 | // Customize the ASP.NET Identity model and override the defaults if needed.
22 | // For example, you can rename the ASP.NET Identity table names and more.
23 | // Add your customizations after calling base.OnModelCreating(builder);
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/DosFactores/Models/AccountViewModels/ResetPasswordViewModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel.DataAnnotations;
4 | using System.Linq;
5 | using System.Threading.Tasks;
6 |
7 | namespace DosFactores.Models.AccountViewModels
8 | {
9 | public class ResetPasswordViewModel
10 | {
11 | [Required]
12 | [EmailAddress]
13 | public string Email { get; set; }
14 |
15 | [Required]
16 | [StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)]
17 | [DataType(DataType.Password)]
18 | public string Password { get; set; }
19 |
20 | [DataType(DataType.Password)]
21 | [Display(Name = "Confirm password")]
22 | [Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
23 | public string ConfirmPassword { get; set; }
24 |
25 | public string Code { get; set; }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/DosFactores/Models/AccountViewModels/RegisterViewModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel.DataAnnotations;
4 | using System.Linq;
5 | using System.Threading.Tasks;
6 |
7 | namespace DosFactores.Models.AccountViewModels
8 | {
9 | public class RegisterViewModel
10 | {
11 | [Required]
12 | [EmailAddress]
13 | [Display(Name = "Email")]
14 | public string Email { get; set; }
15 |
16 | [Required]
17 | [StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)]
18 | [DataType(DataType.Password)]
19 | [Display(Name = "Password")]
20 | public string Password { get; set; }
21 |
22 | [DataType(DataType.Password)]
23 | [Display(Name = "Confirm password")]
24 | [Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
25 | public string ConfirmPassword { get; set; }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/DosFactores/Views/Manage/AddPhoneNumber.cshtml:
--------------------------------------------------------------------------------
1 | @model AddPhoneNumberViewModel
2 | @{
3 | ViewData["Title"] = "Add Phone Number";
4 | }
5 |
6 | @ViewData["Title"].
7 |
24 |
25 | @section Scripts {
26 | @{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); }
27 | }
28 |
--------------------------------------------------------------------------------
/DosFactores/Models/ManageViewModels/ChangePasswordViewModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel.DataAnnotations;
4 | using System.Linq;
5 | using System.Threading.Tasks;
6 |
7 | namespace DosFactores.Models.ManageViewModels
8 | {
9 | public class ChangePasswordViewModel
10 | {
11 | [Required]
12 | [DataType(DataType.Password)]
13 | [Display(Name = "Current password")]
14 | public string OldPassword { get; set; }
15 |
16 | [Required]
17 | [StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)]
18 | [DataType(DataType.Password)]
19 | [Display(Name = "New password")]
20 | public string NewPassword { get; set; }
21 |
22 | [DataType(DataType.Password)]
23 | [Display(Name = "Confirm new password")]
24 | [Compare("NewPassword", ErrorMessage = "The new password and confirmation password do not match.")]
25 | public string ConfirmPassword { get; set; }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/DosFactores/Views/Shared/_LoginPartial.cshtml:
--------------------------------------------------------------------------------
1 | @using Microsoft.AspNetCore.Identity
2 | @using DosFactores.Models
3 |
4 | @inject SignInManager SignInManager
5 | @inject UserManager UserManager
6 |
7 | @if (SignInManager.IsSignedIn(User))
8 | {
9 |
19 | }
20 | else
21 | {
22 |
26 | }
27 |
--------------------------------------------------------------------------------
/DosFactores/wwwroot/lib/jquery-validation/.bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "jquery-validation",
3 | "homepage": "http://jqueryvalidation.org/",
4 | "repository": {
5 | "type": "git",
6 | "url": "git://github.com/jzaefferer/jquery-validation.git"
7 | },
8 | "authors": [
9 | "Jörn Zaefferer "
10 | ],
11 | "description": "Form validation made easy",
12 | "main": "dist/jquery.validate.js",
13 | "keywords": [
14 | "forms",
15 | "validation",
16 | "validate"
17 | ],
18 | "license": "MIT",
19 | "ignore": [
20 | "**/.*",
21 | "node_modules",
22 | "bower_components",
23 | "test",
24 | "demo",
25 | "lib"
26 | ],
27 | "dependencies": {
28 | "jquery": ">= 1.7.2"
29 | },
30 | "version": "1.14.0",
31 | "_release": "1.14.0",
32 | "_resolution": {
33 | "type": "version",
34 | "tag": "1.14.0",
35 | "commit": "c1343fb9823392aa9acbe1c3ffd337b8c92fed48"
36 | },
37 | "_source": "git://github.com/jzaefferer/jquery-validation.git",
38 | "_target": ">=1.8",
39 | "_originalSource": "jquery-validation"
40 | }
--------------------------------------------------------------------------------
/DosFactores/wwwroot/lib/bootstrap/.bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "bootstrap",
3 | "description": "The most popular front-end framework for developing responsive, mobile first projects on the web.",
4 | "keywords": [
5 | "css",
6 | "js",
7 | "less",
8 | "mobile-first",
9 | "responsive",
10 | "front-end",
11 | "framework",
12 | "web"
13 | ],
14 | "homepage": "http://getbootstrap.com",
15 | "license": "MIT",
16 | "moduleType": "globals",
17 | "main": [
18 | "less/bootstrap.less",
19 | "dist/js/bootstrap.js"
20 | ],
21 | "ignore": [
22 | "/.*",
23 | "_config.yml",
24 | "CNAME",
25 | "composer.json",
26 | "CONTRIBUTING.md",
27 | "docs",
28 | "js/tests",
29 | "test-infra"
30 | ],
31 | "dependencies": {
32 | "jquery": "1.9.1 - 3"
33 | },
34 | "version": "3.3.7",
35 | "_release": "3.3.7",
36 | "_resolution": {
37 | "type": "version",
38 | "tag": "v3.3.7",
39 | "commit": "0b9c4a4007c44201dce9a6cc1a38407005c26c86"
40 | },
41 | "_source": "https://github.com/twbs/bootstrap.git",
42 | "_target": "v3.3.7",
43 | "_originalSource": "bootstrap",
44 | "_direct": true
45 | }
--------------------------------------------------------------------------------
/DosFactores/Views/Manage/VerifyPhoneNumber.cshtml:
--------------------------------------------------------------------------------
1 | @model VerifyPhoneNumberViewModel
2 | @{
3 | ViewData["Title"] = "Verify Phone Number";
4 | }
5 |
6 | @ViewData["Title"].
7 |
8 |
27 |
28 | @section Scripts {
29 | @{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); }
30 | }
31 |
--------------------------------------------------------------------------------
/DosFactores/wwwroot/lib/bootstrap/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2011-2016 Twitter, Inc.
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
22 |
--------------------------------------------------------------------------------
/DosFactores/Views/Account/ForgotPassword.cshtml:
--------------------------------------------------------------------------------
1 | @model ForgotPasswordViewModel
2 | @{
3 | ViewData["Title"] = "Forgot your password?";
4 | }
5 |
6 | @ViewData["Title"]
7 |
8 | For more information on how to enable reset password please see this article.
9 |
10 |
11 | @**@
28 |
29 | @section Scripts {
30 | @{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); }
31 | }
32 |
--------------------------------------------------------------------------------
/DosFactores/wwwroot/css/site.css:
--------------------------------------------------------------------------------
1 | body {
2 | padding-top: 50px;
3 | padding-bottom: 20px;
4 | }
5 |
6 | /* Wrapping element */
7 | /* Set some basic padding to keep content from hitting the edges */
8 | .body-content {
9 | padding-left: 15px;
10 | padding-right: 15px;
11 | }
12 |
13 | /* Set widths on the form inputs since otherwise they're 100% wide */
14 | input,
15 | select,
16 | textarea {
17 | max-width: 280px;
18 | }
19 |
20 | /* Carousel */
21 | .carousel-caption p {
22 | font-size: 20px;
23 | line-height: 1.4;
24 | }
25 |
26 | /* buttons and links extension to use brackets: [ click me ] */
27 | .btn-bracketed::before {
28 | display: inline-block;
29 | content: "[";
30 | padding-right: 0.5em;
31 | }
32 |
33 | .btn-bracketed::after {
34 | display: inline-block;
35 | content: "]";
36 | padding-left: 0.5em;
37 | }
38 |
39 | /* Make .svg files in the carousel display properly in older browsers */
40 | .carousel-inner .item img[src$=".svg"] {
41 | width: 100%;
42 | }
43 |
44 | /* Hide/rearrange for smaller screens */
45 | @media screen and (max-width: 767px) {
46 | /* Hide captions */
47 | .carousel-caption {
48 | display: none;
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/DosFactores/wwwroot/lib/jquery-validation/LICENSE.md:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 | =====================
3 |
4 | Copyright Jörn Zaefferer
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in
14 | all copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | THE SOFTWARE.
23 |
--------------------------------------------------------------------------------
/DosFactores/Views/Shared/_ValidationScriptsPartial.cshtml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
12 |
18 |
19 |
--------------------------------------------------------------------------------
/DosFactores/wwwroot/lib/jquery-validation-unobtrusive/.bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "jquery-validation-unobtrusive",
3 | "version": "3.2.6",
4 | "homepage": "https://github.com/aspnet/jquery-validation-unobtrusive",
5 | "description": "Add-on to jQuery Validation to enable unobtrusive validation options in data-* attributes.",
6 | "main": [
7 | "jquery.validate.unobtrusive.js"
8 | ],
9 | "ignore": [
10 | "**/.*",
11 | "*.json",
12 | "*.md",
13 | "*.txt",
14 | "gulpfile.js"
15 | ],
16 | "keywords": [
17 | "jquery",
18 | "asp.net",
19 | "mvc",
20 | "validation",
21 | "unobtrusive"
22 | ],
23 | "authors": [
24 | "Microsoft"
25 | ],
26 | "license": "http://www.microsoft.com/web/webpi/eula/net_library_eula_enu.htm",
27 | "repository": {
28 | "type": "git",
29 | "url": "git://github.com/aspnet/jquery-validation-unobtrusive.git"
30 | },
31 | "dependencies": {
32 | "jquery-validation": ">=1.8",
33 | "jquery": ">=1.8"
34 | },
35 | "_release": "3.2.6",
36 | "_resolution": {
37 | "type": "version",
38 | "tag": "v3.2.6",
39 | "commit": "13386cd1b5947d8a5d23a12b531ce3960be1eba7"
40 | },
41 | "_source": "git://github.com/aspnet/jquery-validation-unobtrusive.git",
42 | "_target": "3.2.6",
43 | "_originalSource": "jquery-validation-unobtrusive"
44 | }
--------------------------------------------------------------------------------
/DosFactores/Views/Account/ExternalLoginConfirmation.cshtml:
--------------------------------------------------------------------------------
1 | @model ExternalLoginConfirmationViewModel
2 | @{
3 | ViewData["Title"] = "Register";
4 | }
5 |
6 | @ViewData["Title"].
7 | Associate your @ViewData["LoginProvider"] account.
8 |
9 |
32 |
33 | @section Scripts {
34 | @{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); }
35 | }
36 |
--------------------------------------------------------------------------------
/DosFactores/Views/Account/VerifyCode.cshtml:
--------------------------------------------------------------------------------
1 | @model VerifyCodeViewModel
2 | @{
3 | ViewData["Title"] = "Verify";
4 | }
5 |
6 | @ViewData["Title"].
7 |
8 |
35 |
36 | @section Scripts {
37 | @{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); }
38 | }
39 |
--------------------------------------------------------------------------------
/DosFactores/Views/Manage/SetPassword.cshtml:
--------------------------------------------------------------------------------
1 | @model SetPasswordViewModel
2 | @{
3 | ViewData["Title"] = "Set Password";
4 | }
5 |
6 |
7 | You do not have a local username/password for this site. Add a local
8 | account so you can log in without an external login.
9 |
10 |
11 |
35 |
36 | @section Scripts {
37 | @{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); }
38 | }
39 |
--------------------------------------------------------------------------------
/DosFactores.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.26228.4
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DosFactores", "DosFactores\DosFactores.csproj", "{3D386493-FC4F-4047-8349-B8A39E51914A}"
7 | EndProject
8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Google.Authenticator", "Google.Authenticator\Google.Authenticator.csproj", "{156870C6-0FAD-4265-BE4F-71287F9D9B19}"
9 | EndProject
10 | Global
11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
12 | Debug|Any CPU = Debug|Any CPU
13 | Release|Any CPU = Release|Any CPU
14 | EndGlobalSection
15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
16 | {3D386493-FC4F-4047-8349-B8A39E51914A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
17 | {3D386493-FC4F-4047-8349-B8A39E51914A}.Debug|Any CPU.Build.0 = Debug|Any CPU
18 | {3D386493-FC4F-4047-8349-B8A39E51914A}.Release|Any CPU.ActiveCfg = Release|Any CPU
19 | {3D386493-FC4F-4047-8349-B8A39E51914A}.Release|Any CPU.Build.0 = Release|Any CPU
20 | {156870C6-0FAD-4265-BE4F-71287F9D9B19}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
21 | {156870C6-0FAD-4265-BE4F-71287F9D9B19}.Debug|Any CPU.Build.0 = Debug|Any CPU
22 | {156870C6-0FAD-4265-BE4F-71287F9D9B19}.Release|Any CPU.ActiveCfg = Release|Any CPU
23 | {156870C6-0FAD-4265-BE4F-71287F9D9B19}.Release|Any CPU.Build.0 = Release|Any CPU
24 | EndGlobalSection
25 | GlobalSection(SolutionProperties) = preSolution
26 | HideSolutionNode = FALSE
27 | EndGlobalSection
28 | EndGlobal
29 |
--------------------------------------------------------------------------------
/DosFactores/Views/Account/Register.cshtml:
--------------------------------------------------------------------------------
1 | @model RegisterViewModel
2 | @{
3 | ViewData["Title"] = "Register";
4 | }
5 |
6 | @ViewData["Title"].
7 |
8 |
39 |
40 | @section Scripts {
41 | @{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); }
42 | }
43 |
--------------------------------------------------------------------------------
/DosFactores/Views/Manage/ChangePassword.cshtml:
--------------------------------------------------------------------------------
1 | @model ChangePasswordViewModel
2 | @{
3 | ViewData["Title"] = "Change Password";
4 | }
5 |
6 | @ViewData["Title"].
7 |
8 |
39 |
40 | @section Scripts {
41 | @{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); }
42 | }
43 |
--------------------------------------------------------------------------------
/DosFactores/Views/Account/ResetPassword.cshtml:
--------------------------------------------------------------------------------
1 | @model ResetPasswordViewModel
2 | @{
3 | ViewData["Title"] = "Reset password";
4 | }
5 |
6 | @ViewData["Title"].
7 |
8 |
40 |
41 | @section Scripts {
42 | @{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); }
43 | }
44 |
--------------------------------------------------------------------------------
/DosFactores/wwwroot/lib/jquery/LICENSE.txt:
--------------------------------------------------------------------------------
1 | Copyright jQuery Foundation and other contributors, https://jquery.org/
2 |
3 | This software consists of voluntary contributions made by many
4 | individuals. For exact contribution history, see the revision history
5 | available at https://github.com/jquery/jquery
6 |
7 | The following license applies to all parts of this software except as
8 | documented below:
9 |
10 | ====
11 |
12 | Permission is hereby granted, free of charge, to any person obtaining
13 | a copy of this software and associated documentation files (the
14 | "Software"), to deal in the Software without restriction, including
15 | without limitation the rights to use, copy, modify, merge, publish,
16 | distribute, sublicense, and/or sell copies of the Software, and to
17 | permit persons to whom the Software is furnished to do so, subject to
18 | the following conditions:
19 |
20 | The above copyright notice and this permission notice shall be
21 | included in all copies or substantial portions of the Software.
22 |
23 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 |
31 | ====
32 |
33 | All files located in the node_modules and external directories are
34 | externally maintained libraries used by this software which have their
35 | own licenses; we recommend you read them, as their terms may differ from
36 | the terms above.
37 |
--------------------------------------------------------------------------------
/DosFactores/GoogleAuthenticatorProvider.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 | using DosFactores.Data;
6 | using DosFactores.Models;
7 | using Google.Authenticator;
8 | using Microsoft.AspNetCore.Identity;
9 |
10 | namespace DosFactores
11 | {
12 | public class GoogleAuthenticatorProvider : IUserTwoFactorTokenProvider
13 | {
14 | public static readonly string ProviderName = "GoogleAuthenticator";
15 |
16 | private readonly ApplicationDbContext _dbContext;
17 |
18 | public GoogleAuthenticatorProvider(ApplicationDbContext dbContext)
19 | {
20 | _dbContext = dbContext;
21 | }
22 |
23 | public async Task GenerateAsync(string purpose, UserManager manager, ApplicationUser user)
24 | {
25 | var userName = await manager.GetUserNameAsync(user);
26 | var authenticator = new TwoFactorAuthenticator();
27 | var code = authenticator.GenerateSetupCode(userName, userName, 100, 100);
28 | return code.ManualEntryKey;
29 | }
30 |
31 | public Task ValidateAsync(string purpose, string token, UserManager manager, ApplicationUser user)
32 | {
33 | return Task.Factory.StartNew(() =>
34 | {
35 | var authenticator = new TwoFactorAuthenticator();
36 | return authenticator.ValidateTwoFactorPIN(user.TfaKey, token);
37 | });
38 | }
39 |
40 | public Task CanGenerateTwoFactorTokenAsync(UserManager manager, ApplicationUser user)
41 | {
42 | return Task.Factory.StartNew(() =>
43 | {
44 | // Verify if the user is ellegible for 2FA
45 | return true;
46 | });
47 | }
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/DosFactores/Views/Manage/ManageLogins.cshtml:
--------------------------------------------------------------------------------
1 | @model ManageLoginsViewModel
2 | @using Microsoft.AspNetCore.Http.Authentication
3 | @{
4 | ViewData["Title"] = "Manage your external logins";
5 | }
6 |
7 | @ViewData["Title"].
8 |
9 | @ViewData["StatusMessage"]
10 | @if (Model.CurrentLogins.Count > 0)
11 | {
12 | Registered Logins
13 |
14 |
15 | @for (var index = 0; index < Model.CurrentLogins.Count; index++)
16 | {
17 |
18 | | @Model.CurrentLogins[index].LoginProvider |
19 |
20 | @if ((bool)ViewData["ShowRemoveButton"])
21 | {
22 |
29 | }
30 | else
31 | {
32 | @:
33 | }
34 | |
35 |
36 | }
37 |
38 |
39 | }
40 | @if (Model.OtherLogins.Count > 0)
41 | {
42 | Add another service to log in.
43 |
44 |
54 | }
55 |
--------------------------------------------------------------------------------
/DosFactores/DosFactores.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp1.1
5 |
6 |
7 |
8 | $(PackageTargetFallback);portable-net45+win8+wp8+wpa81;
9 |
10 |
11 |
12 | aspnet-DosFactores-8b4894aa-022f-4f37-aade-9e476effe1b5
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/DosFactores/Views/Manage/Index.cshtml:
--------------------------------------------------------------------------------
1 | @model IndexViewModel
2 | @{
3 | ViewData["Title"] = "Manage your account";
4 | }
5 |
6 | @ViewData["Title"].
7 | @ViewData["StatusMessage"]
8 |
9 |
10 |
Change your account settings
11 |
12 |
13 | - Password:
14 | -
15 | @if (Model.HasPassword)
16 | {
17 | Change
18 | }
19 | else
20 | {
21 | Create
22 | }
23 |
24 | - External Logins:
25 | -
26 |
27 | @Model.Logins.Count Manage
28 |
29 | - Phone Number:
30 | -
31 |
32 | Phone Numbers can be used as a second factor of verification in two-factor authentication.
33 | See this article
34 | for details on setting up this ASP.NET application to support two-factor authentication using SMS.
35 |
36 | @*@(Model.PhoneNumber ?? "None")
37 | @if (Model.PhoneNumber != null)
38 | {
39 |
40 | Change
41 |
44 | }
45 | else
46 | {
47 | Add
48 | }*@
49 |
50 |
51 | - Two-Factor Authentication:
52 | -
53 | @if (Model.TwoFactorAuthenticatorQrCode != null)
54 | {
55 |
56 |
59 | }
60 | else
61 | {
62 | if (Model.TwoFactor)
63 | {
64 |
67 | }
68 | else
69 | {
70 |
73 | }
74 | }
75 |
76 |
77 |
78 |
--------------------------------------------------------------------------------
/DosFactores/Views/Shared/_Layout.cshtml:
--------------------------------------------------------------------------------
1 | @inject Microsoft.ApplicationInsights.AspNetCore.JavaScriptSnippet JavaScriptSnippet
2 |
3 |
4 |
5 |
6 |
7 | @ViewData["Title"] - DosFactores
8 |
9 |
10 |
11 |
12 |
13 |
14 |
17 |
18 |
19 | @Html.Raw(JavaScriptSnippet.FullScript)
20 |
21 |
22 |
43 |
44 | @RenderBody()
45 |
46 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
63 |
69 |
70 |
71 |
72 | @RenderSection("Scripts", required: false)
73 |
74 |
75 |
--------------------------------------------------------------------------------
/DosFactores/Views/Account/Login.cshtml:
--------------------------------------------------------------------------------
1 | @using System.Collections.Generic
2 | @using Microsoft.AspNetCore.Http
3 | @using Microsoft.AspNetCore.Http.Authentication
4 | @model LoginViewModel
5 | @inject SignInManager SignInManager
6 |
7 | @{
8 | ViewData["Title"] = "Log in";
9 | }
10 |
11 | @ViewData["Title"].
12 |
13 |
57 |
58 |
59 | Use another service to log in.
60 |
61 | @{
62 | var loginProviders = SignInManager.GetExternalAuthenticationSchemes().ToList();
63 | if (loginProviders.Count == 0)
64 | {
65 |
66 |
67 | There are no external authentication services configured. See this article
68 | for details on setting up this ASP.NET application to support logging in via external services.
69 |
70 |
71 | }
72 | else
73 | {
74 |
84 | }
85 | }
86 |
87 |
88 |
89 |
90 | @section Scripts {
91 | @{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); }
92 | }
93 |
--------------------------------------------------------------------------------
/DosFactores/Startup.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 | using Microsoft.AspNetCore.Builder;
6 | using Microsoft.AspNetCore.Hosting;
7 | using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
8 | using Microsoft.EntityFrameworkCore;
9 | using Microsoft.Extensions.Configuration;
10 | using Microsoft.Extensions.DependencyInjection;
11 | using Microsoft.Extensions.Logging;
12 | using DosFactores.Data;
13 | using DosFactores.Models;
14 | using DosFactores.Services;
15 | using Microsoft.AspNetCore.Identity;
16 | using Microsoft.AspNetCore.Mvc;
17 | using Microsoft.AspNetCore.Rewrite;
18 |
19 | namespace DosFactores
20 | {
21 | public class Startup
22 | {
23 | public Startup(IHostingEnvironment env)
24 | {
25 | var builder = new ConfigurationBuilder()
26 | .SetBasePath(env.ContentRootPath)
27 | .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
28 | .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true);
29 |
30 | if (env.IsDevelopment())
31 | {
32 | // For more details on using the user secret store see https://go.microsoft.com/fwlink/?LinkID=532709
33 | builder.AddUserSecrets();
34 | }
35 |
36 | builder.AddEnvironmentVariables();
37 | Configuration = builder.Build();
38 | }
39 |
40 | public IConfigurationRoot Configuration { get; }
41 |
42 | // This method gets called by the runtime. Use this method to add services to the container.
43 | public void ConfigureServices(IServiceCollection services)
44 | {
45 | // Enforce SSL
46 | services.Configure(options =>
47 | {
48 | options.Filters.Add(new RequireHttpsAttribute());
49 | });
50 |
51 | // Add framework services.
52 | services.AddDbContext(options =>
53 | options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
54 |
55 | services.AddIdentity()
56 | .AddEntityFrameworkStores()
57 | .AddTokenProvider(GoogleAuthenticatorProvider.ProviderName, typeof(GoogleAuthenticatorProvider))
58 | .AddDefaultTokenProviders();
59 |
60 | services.AddMvc();
61 | services.AddSession(options =>
62 | {
63 | // Set a short timeout for easy testing.
64 | options.IdleTimeout = TimeSpan.FromSeconds(10);
65 | options.CookieHttpOnly = true;
66 | });
67 |
68 | // Add application services.
69 | services.AddTransient();
70 | services.AddTransient();
71 | }
72 |
73 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
74 | public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
75 | {
76 | loggerFactory.AddConsole(Configuration.GetSection("Logging"));
77 | loggerFactory.AddDebug();
78 |
79 | // Requires using Microsoft.AspNetCore.Rewrite;
80 | var options = new RewriteOptions()
81 | .AddRedirectToHttps();
82 |
83 | if (env.IsDevelopment())
84 | {
85 | app.UseDeveloperExceptionPage();
86 | app.UseDatabaseErrorPage();
87 | app.UseBrowserLink();
88 | }
89 | else
90 | {
91 | app.UseExceptionHandler("/Home/Error");
92 | }
93 |
94 | app.UseStaticFiles();
95 |
96 | app.UseIdentity();
97 |
98 | // Add external authentication middleware below. To configure them please see https://go.microsoft.com/fwlink/?LinkID=532715
99 | app.UseSession();
100 | app.UseMvc(routes =>
101 | {
102 | routes.MapRoute(
103 | name: "default",
104 | template: "{controller=Home}/{action=Index}/{id?}");
105 | });
106 | }
107 | }
108 | }
109 |
--------------------------------------------------------------------------------
/DosFactores/wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js:
--------------------------------------------------------------------------------
1 | /*
2 | ** Unobtrusive validation support library for jQuery and jQuery Validate
3 | ** Copyright (C) Microsoft Corporation. All rights reserved.
4 | */
5 | !function(a){function e(a,e,n){a.rules[e]=n,a.message&&(a.messages[e]=a.message)}function n(a){return a.replace(/^\s+|\s+$/g,"").split(/\s*,\s*/g)}function t(a){return a.replace(/([!"#$%&'()*+,./:;<=>?@\[\\\]^`{|}~])/g,"\\$1")}function r(a){return a.substr(0,a.lastIndexOf(".")+1)}function i(a,e){return 0===a.indexOf("*.")&&(a=a.replace("*.",e)),a}function o(e,n){var r=a(this).find("[data-valmsg-for='"+t(n[0].name)+"']"),i=r.attr("data-valmsg-replace"),o=i?a.parseJSON(i)!==!1:null;r.removeClass("field-validation-valid").addClass("field-validation-error"),e.data("unobtrusiveContainer",r),o?(r.empty(),e.removeClass("input-validation-error").appendTo(r)):e.hide()}function d(e,n){var t=a(this).find("[data-valmsg-summary=true]"),r=t.find("ul");r&&r.length&&n.errorList.length&&(r.empty(),t.addClass("validation-summary-errors").removeClass("validation-summary-valid"),a.each(n.errorList,function(){a("").html(this.message).appendTo(r)}))}function s(e){var n=e.data("unobtrusiveContainer");if(n){var t=n.attr("data-valmsg-replace"),r=t?a.parseJSON(t):null;n.addClass("field-validation-valid").removeClass("field-validation-error"),e.removeData("unobtrusiveContainer"),r&&n.empty()}}function l(e){var n=a(this),t="__jquery_unobtrusive_validation_form_reset";if(!n.data(t)){n.data(t,!0);try{n.data("validator").resetForm()}finally{n.removeData(t)}n.find(".validation-summary-errors").addClass("validation-summary-valid").removeClass("validation-summary-errors"),n.find(".field-validation-error").addClass("field-validation-valid").removeClass("field-validation-error").removeData("unobtrusiveContainer").find(">*").removeData("unobtrusiveContainer")}}function m(e){var n=a(e),t=n.data(v),r=a.proxy(l,e),i=p.unobtrusive.options||{},m=function(n,t){var r=i[n];r&&a.isFunction(r)&&r.apply(e,t)};return t||(t={options:{errorClass:i.errorClass||"input-validation-error",errorElement:i.errorElement||"span",errorPlacement:function(){o.apply(e,arguments),m("errorPlacement",arguments)},invalidHandler:function(){d.apply(e,arguments),m("invalidHandler",arguments)},messages:{},rules:{},success:function(){s.apply(e,arguments),m("success",arguments)}},attachValidation:function(){n.off("reset."+v,r).on("reset."+v,r).validate(this.options)},validate:function(){return n.validate(),n.valid()}},n.data(v,t)),t}var u,p=a.validator,v="unobtrusiveValidation";p.unobtrusive={adapters:[],parseElement:function(e,n){var t,r,i,o=a(e),d=o.parents("form")[0];d&&(t=m(d),t.options.rules[e.name]=r={},t.options.messages[e.name]=i={},a.each(this.adapters,function(){var n="data-val-"+this.name,t=o.attr(n),s={};void 0!==t&&(n+="-",a.each(this.params,function(){s[this]=o.attr(n+this)}),this.adapt({element:e,form:d,message:t,params:s,rules:r,messages:i}))}),a.extend(r,{__dummy__:!0}),n||t.attachValidation())},parse:function(e){var n=a(e),t=n.parents().addBack().filter("form").add(n.find("form")).has("[data-val=true]");n.find("[data-val=true]").each(function(){p.unobtrusive.parseElement(this,!0)}),t.each(function(){var a=m(this);a&&a.attachValidation()})}},u=p.unobtrusive.adapters,u.add=function(a,e,n){return n||(n=e,e=[]),this.push({name:a,params:e,adapt:n}),this},u.addBool=function(a,n){return this.add(a,function(t){e(t,n||a,!0)})},u.addMinMax=function(a,n,t,r,i,o){return this.add(a,[i||"min",o||"max"],function(a){var i=a.params.min,o=a.params.max;i&&o?e(a,r,[i,o]):i?e(a,n,i):o&&e(a,t,o)})},u.addSingleVal=function(a,n,t){return this.add(a,[n||"val"],function(r){e(r,t||a,r.params[n])})},p.addMethod("__dummy__",function(a,e,n){return!0}),p.addMethod("regex",function(a,e,n){var t;return this.optional(e)?!0:(t=new RegExp(n).exec(a),t&&0===t.index&&t[0].length===a.length)}),p.addMethod("nonalphamin",function(a,e,n){var t;return n&&(t=a.match(/\W/g),t=t&&t.length>=n),t}),p.methods.extension?(u.addSingleVal("accept","mimtype"),u.addSingleVal("extension","extension")):u.addSingleVal("extension","extension","accept"),u.addSingleVal("regex","pattern"),u.addBool("creditcard").addBool("date").addBool("digits").addBool("email").addBool("number").addBool("url"),u.addMinMax("length","minlength","maxlength","rangelength").addMinMax("range","min","max","range"),u.addMinMax("minlength","minlength").addMinMax("maxlength","minlength","maxlength"),u.add("equalto",["other"],function(n){var o=r(n.element.name),d=n.params.other,s=i(d,o),l=a(n.form).find(":input").filter("[name='"+t(s)+"']")[0];e(n,"equalTo",l)}),u.add("required",function(a){("INPUT"!==a.element.tagName.toUpperCase()||"CHECKBOX"!==a.element.type.toUpperCase())&&e(a,"required",!0)}),u.add("remote",["url","type","additionalfields"],function(o){var d={url:o.params.url,type:o.params.type||"GET",data:{}},s=r(o.element.name);a.each(n(o.params.additionalfields||o.element.name),function(e,n){var r=i(n,s);d.data[r]=function(){var e=a(o.form).find(":input").filter("[name='"+t(r)+"']");return e.is(":checkbox")?e.filter(":checked").val()||e.filter(":hidden").val()||"":e.is(":radio")?e.filter(":checked").val()||"":e.val()}}),e(o,"remote",d)}),u.add("password",["min","nonalphamin","regex"],function(a){a.params.min&&e(a,"minlength",a.params.min),a.params.nonalphamin&&e(a,"nonalphamin",a.params.nonalphamin),a.params.regex&&e(a,"regex",a.params.regex)}),a(function(){p.unobtrusive.parse(document)})}(jQuery);
--------------------------------------------------------------------------------
/DosFactores/Views/Home/Index.cshtml:
--------------------------------------------------------------------------------
1 | @{
2 | ViewData["Title"] = "Home Page";
3 | }
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |

15 |
16 |
17 | Learn how to build ASP.NET apps that can run anywhere.
18 |
19 | Learn More
20 |
21 |
22 |
23 |
24 |
25 |

26 |
27 |
28 | There are powerful new features in Visual Studio for building modern web apps.
29 |
30 | Learn More
31 |
32 |
33 |
34 |
35 |
36 |

37 |
38 |
39 | Bring in libraries from NuGet, Bower, and npm, and automate tasks using Grunt or Gulp.
40 |
41 | Learn More
42 |
43 |
44 |
45 |
46 |
47 |

48 |
49 |
50 | Learn how Microsoft's Azure cloud platform allows you to build, deploy, and scale web apps.
51 |
52 | Learn More
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 | Previous
61 |
62 |
63 |
64 | Next
65 |
66 |
67 |
68 |
69 |
70 |
Application uses
71 |
72 | - Sample pages using ASP.NET Core MVC
73 | - Bower for managing client-side libraries
74 | - Theming using Bootstrap
75 |
76 |
77 |
88 |
100 |
101 |
Run & Deploy
102 |
107 |
108 |
109 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 | ##
4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
5 |
6 | # User-specific files
7 | *.suo
8 | *.user
9 | *.userosscache
10 | *.sln.docstates
11 |
12 | # User-specific files (MonoDevelop/Xamarin Studio)
13 | *.userprefs
14 |
15 | # Build results
16 | [Dd]ebug/
17 | [Dd]ebugPublic/
18 | [Rr]elease/
19 | [Rr]eleases/
20 | x64/
21 | x86/
22 | bld/
23 | [Bb]in/
24 | [Oo]bj/
25 | [Ll]og/
26 |
27 | # Visual Studio 2015 cache/options directory
28 | .vs/
29 | # Uncomment if you have tasks that create the project's static files in wwwroot
30 | #wwwroot/
31 |
32 | # MSTest test Results
33 | [Tt]est[Rr]esult*/
34 | [Bb]uild[Ll]og.*
35 |
36 | # NUNIT
37 | *.VisualState.xml
38 | TestResult.xml
39 |
40 | # Build Results of an ATL Project
41 | [Dd]ebugPS/
42 | [Rr]eleasePS/
43 | dlldata.c
44 |
45 | # .NET Core
46 | project.lock.json
47 | project.fragment.lock.json
48 | artifacts/
49 | **/Properties/launchSettings.json
50 |
51 | *_i.c
52 | *_p.c
53 | *_i.h
54 | *.ilk
55 | *.meta
56 | *.obj
57 | *.pch
58 | *.pdb
59 | *.pgc
60 | *.pgd
61 | *.rsp
62 | *.sbr
63 | *.tlb
64 | *.tli
65 | *.tlh
66 | *.tmp
67 | *.tmp_proj
68 | *.log
69 | *.vspscc
70 | *.vssscc
71 | .builds
72 | *.pidb
73 | *.svclog
74 | *.scc
75 |
76 | # Chutzpah Test files
77 | _Chutzpah*
78 |
79 | # Visual C++ cache files
80 | ipch/
81 | *.aps
82 | *.ncb
83 | *.opendb
84 | *.opensdf
85 | *.sdf
86 | *.cachefile
87 | *.VC.db
88 | *.VC.VC.opendb
89 |
90 | # Visual Studio profiler
91 | *.psess
92 | *.vsp
93 | *.vspx
94 | *.sap
95 |
96 | # TFS 2012 Local Workspace
97 | $tf/
98 |
99 | # Guidance Automation Toolkit
100 | *.gpState
101 |
102 | # ReSharper is a .NET coding add-in
103 | _ReSharper*/
104 | *.[Rr]e[Ss]harper
105 | *.DotSettings.user
106 |
107 | # JustCode is a .NET coding add-in
108 | .JustCode
109 |
110 | # TeamCity is a build add-in
111 | _TeamCity*
112 |
113 | # DotCover is a Code Coverage Tool
114 | *.dotCover
115 |
116 | # Visual Studio code coverage results
117 | *.coverage
118 | *.coveragexml
119 |
120 | # NCrunch
121 | _NCrunch_*
122 | .*crunch*.local.xml
123 | nCrunchTemp_*
124 |
125 | # MightyMoose
126 | *.mm.*
127 | AutoTest.Net/
128 |
129 | # Web workbench (sass)
130 | .sass-cache/
131 |
132 | # Installshield output folder
133 | [Ee]xpress/
134 |
135 | # DocProject is a documentation generator add-in
136 | DocProject/buildhelp/
137 | DocProject/Help/*.HxT
138 | DocProject/Help/*.HxC
139 | DocProject/Help/*.hhc
140 | DocProject/Help/*.hhk
141 | DocProject/Help/*.hhp
142 | DocProject/Help/Html2
143 | DocProject/Help/html
144 |
145 | # Click-Once directory
146 | publish/
147 |
148 | # Publish Web Output
149 | *.[Pp]ublish.xml
150 | *.azurePubxml
151 | # TODO: Comment the next line if you want to checkin your web deploy settings
152 | # but database connection strings (with potential passwords) will be unencrypted
153 | *.pubxml
154 | *.publishproj
155 |
156 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
157 | # checkin your Azure Web App publish settings, but sensitive information contained
158 | # in these scripts will be unencrypted
159 | PublishScripts/
160 |
161 | # NuGet Packages
162 | *.nupkg
163 | # The packages folder can be ignored because of Package Restore
164 | **/packages/*
165 | # except build/, which is used as an MSBuild target.
166 | !**/packages/build/
167 | # Uncomment if necessary however generally it will be regenerated when needed
168 | #!**/packages/repositories.config
169 | # NuGet v3's project.json files produces more ignorable files
170 | *.nuget.props
171 | *.nuget.targets
172 |
173 | # Microsoft Azure Build Output
174 | csx/
175 | *.build.csdef
176 |
177 | # Microsoft Azure Emulator
178 | ecf/
179 | rcf/
180 |
181 | # Windows Store app package directories and files
182 | AppPackages/
183 | BundleArtifacts/
184 | Package.StoreAssociation.xml
185 | _pkginfo.txt
186 |
187 | # Visual Studio cache files
188 | # files ending in .cache can be ignored
189 | *.[Cc]ache
190 | # but keep track of directories ending in .cache
191 | !*.[Cc]ache/
192 |
193 | # Others
194 | ClientBin/
195 | ~$*
196 | *~
197 | *.dbmdl
198 | *.dbproj.schemaview
199 | *.jfm
200 | *.pfx
201 | *.publishsettings
202 | orleans.codegen.cs
203 |
204 | # Since there are multiple workflows, uncomment next line to ignore bower_components
205 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
206 | #bower_components/
207 |
208 | # RIA/Silverlight projects
209 | Generated_Code/
210 |
211 | # Backup & report files from converting an old project file
212 | # to a newer Visual Studio version. Backup files are not needed,
213 | # because we have git ;-)
214 | _UpgradeReport_Files/
215 | Backup*/
216 | UpgradeLog*.XML
217 | UpgradeLog*.htm
218 |
219 | # SQL Server files
220 | *.mdf
221 | *.ldf
222 | *.ndf
223 |
224 | # Business Intelligence projects
225 | *.rdl.data
226 | *.bim.layout
227 | *.bim_*.settings
228 |
229 | # Microsoft Fakes
230 | FakesAssemblies/
231 |
232 | # GhostDoc plugin setting file
233 | *.GhostDoc.xml
234 |
235 | # Node.js Tools for Visual Studio
236 | .ntvs_analysis.dat
237 | node_modules/
238 |
239 | # Typescript v1 declaration files
240 | typings/
241 |
242 | # Visual Studio 6 build log
243 | *.plg
244 |
245 | # Visual Studio 6 workspace options file
246 | *.opt
247 |
248 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
249 | *.vbw
250 |
251 | # Visual Studio LightSwitch build output
252 | **/*.HTMLClient/GeneratedArtifacts
253 | **/*.DesktopClient/GeneratedArtifacts
254 | **/*.DesktopClient/ModelManifest.xml
255 | **/*.Server/GeneratedArtifacts
256 | **/*.Server/ModelManifest.xml
257 | _Pvt_Extensions
258 |
259 | # Paket dependency manager
260 | .paket/paket.exe
261 | paket-files/
262 |
263 | # FAKE - F# Make
264 | .fake/
265 |
266 | # JetBrains Rider
267 | .idea/
268 | *.sln.iml
269 |
270 | # CodeRush
271 | .cr/
272 |
273 | # Python Tools for Visual Studio (PTVS)
274 | __pycache__/
275 | *.pyc
276 |
277 | # Cake - Uncomment if you are using it
278 | # tools/**
279 | # !tools/packages.config
280 |
281 | # Telerik's JustMock configuration file
282 | *.jmconfig
283 |
284 | # BizTalk build output
285 | *.btp.cs
286 | *.btm.cs
287 | *.odx.cs
288 | *.xsd.cs
289 |
--------------------------------------------------------------------------------
/DosFactores/wwwroot/images/banner2.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/DosFactores/Data/Migrations/ApplicationDbContextModelSnapshot.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 | using Microsoft.EntityFrameworkCore;
6 | using Microsoft.EntityFrameworkCore.Infrastructure;
7 | using Microsoft.EntityFrameworkCore.Metadata;
8 | using Microsoft.EntityFrameworkCore.Migrations;
9 |
10 | namespace DosFactores.Data.Migrations
11 | {
12 | [DbContext(typeof(ApplicationDbContext))]
13 | partial class ApplicationDbContextModelSnapshot : ModelSnapshot
14 | {
15 | protected override void BuildModel(ModelBuilder modelBuilder)
16 | {
17 | modelBuilder
18 | .HasAnnotation("ProductVersion", "1.0.0-rc3")
19 | .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
20 |
21 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityRole", b =>
22 | {
23 | b.Property("Id");
24 |
25 | b.Property("ConcurrencyStamp")
26 | .IsConcurrencyToken();
27 |
28 | b.Property("Name")
29 | .HasAnnotation("MaxLength", 256);
30 |
31 | b.Property("NormalizedName")
32 | .HasAnnotation("MaxLength", 256);
33 |
34 | b.HasKey("Id");
35 |
36 | b.HasIndex("NormalizedName")
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.IdentityUserClaim", b =>
62 | {
63 | b.Property("Id")
64 | .ValueGeneratedOnAdd();
65 |
66 | b.Property("ClaimType");
67 |
68 | b.Property("ClaimValue");
69 |
70 | b.Property("UserId")
71 | .IsRequired();
72 |
73 | b.HasKey("Id");
74 |
75 | b.HasIndex("UserId");
76 |
77 | b.ToTable("AspNetUserClaims");
78 | });
79 |
80 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserLogin", b =>
81 | {
82 | b.Property("LoginProvider");
83 |
84 | b.Property("ProviderKey");
85 |
86 | b.Property("ProviderDisplayName");
87 |
88 | b.Property("UserId")
89 | .IsRequired();
90 |
91 | b.HasKey("LoginProvider", "ProviderKey");
92 |
93 | b.HasIndex("UserId");
94 |
95 | b.ToTable("AspNetUserLogins");
96 | });
97 |
98 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserRole", b =>
99 | {
100 | b.Property("UserId");
101 |
102 | b.Property("RoleId");
103 |
104 | b.HasKey("UserId", "RoleId");
105 |
106 | b.HasIndex("RoleId");
107 |
108 | b.HasIndex("UserId");
109 |
110 | b.ToTable("AspNetUserRoles");
111 | });
112 |
113 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserToken", b =>
114 | {
115 | b.Property("UserId");
116 |
117 | b.Property("LoginProvider");
118 |
119 | b.Property("Name");
120 |
121 | b.Property("Value");
122 |
123 | b.HasKey("UserId", "LoginProvider", "Name");
124 |
125 | b.ToTable("AspNetUserTokens");
126 | });
127 |
128 | modelBuilder.Entity("DosFactores.Models.ApplicationUser", b =>
129 | {
130 | b.Property("Id");
131 |
132 | b.Property("AccessFailedCount");
133 |
134 | b.Property("ConcurrencyStamp")
135 | .IsConcurrencyToken();
136 |
137 | b.Property("Email")
138 | .HasAnnotation("MaxLength", 256);
139 |
140 | b.Property("EmailConfirmed");
141 |
142 | b.Property("LockoutEnabled");
143 |
144 | b.Property("LockoutEnd");
145 |
146 | b.Property("NormalizedEmail")
147 | .HasAnnotation("MaxLength", 256);
148 |
149 | b.Property("NormalizedUserName")
150 | .HasAnnotation("MaxLength", 256);
151 |
152 | b.Property("PasswordHash");
153 |
154 | b.Property("PhoneNumber");
155 |
156 | b.Property("PhoneNumberConfirmed");
157 |
158 | b.Property("SecurityStamp");
159 |
160 | b.Property("TwoFactorEnabled");
161 |
162 | b.Property("UserName")
163 | .HasAnnotation("MaxLength", 256);
164 |
165 | b.HasKey("Id");
166 |
167 | b.HasIndex("NormalizedEmail")
168 | .HasName("EmailIndex");
169 |
170 | b.HasIndex("NormalizedUserName")
171 | .IsUnique()
172 | .HasName("UserNameIndex");
173 |
174 | b.ToTable("AspNetUsers");
175 | });
176 |
177 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityRoleClaim", b =>
178 | {
179 | b.HasOne("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityRole")
180 | .WithMany("Claims")
181 | .HasForeignKey("RoleId")
182 | .OnDelete(DeleteBehavior.Cascade);
183 | });
184 |
185 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserClaim", b =>
186 | {
187 | b.HasOne("DosFactores.Models.ApplicationUser")
188 | .WithMany("Claims")
189 | .HasForeignKey("UserId")
190 | .OnDelete(DeleteBehavior.Cascade);
191 | });
192 |
193 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserLogin", b =>
194 | {
195 | b.HasOne("DosFactores.Models.ApplicationUser")
196 | .WithMany("Logins")
197 | .HasForeignKey("UserId")
198 | .OnDelete(DeleteBehavior.Cascade);
199 | });
200 |
201 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserRole", b =>
202 | {
203 | b.HasOne("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityRole")
204 | .WithMany("Users")
205 | .HasForeignKey("RoleId")
206 | .OnDelete(DeleteBehavior.Cascade);
207 |
208 | b.HasOne("DosFactores.Models.ApplicationUser")
209 | .WithMany("Roles")
210 | .HasForeignKey("UserId")
211 | .OnDelete(DeleteBehavior.Cascade);
212 | });
213 | }
214 | }
215 | }
216 |
--------------------------------------------------------------------------------
/DosFactores/Data/Migrations/00000000000000_CreateIdentitySchema.Designer.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 | using Microsoft.EntityFrameworkCore;
6 | using Microsoft.EntityFrameworkCore.Infrastructure;
7 | using Microsoft.EntityFrameworkCore.Metadata;
8 | using Microsoft.EntityFrameworkCore.Migrations;
9 |
10 | namespace DosFactores.Data.Migrations
11 | {
12 | [DbContext(typeof(ApplicationDbContext))]
13 | [Migration("00000000000000_CreateIdentitySchema")]
14 | partial class CreateIdentitySchema
15 | {
16 | protected override void BuildTargetModel(ModelBuilder modelBuilder)
17 | {
18 | modelBuilder
19 | .HasAnnotation("ProductVersion", "1.0.0-rc3")
20 | .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
21 |
22 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityRole", b =>
23 | {
24 | b.Property("Id");
25 |
26 | b.Property("ConcurrencyStamp")
27 | .IsConcurrencyToken();
28 |
29 | b.Property("Name")
30 | .HasAnnotation("MaxLength", 256);
31 |
32 | b.Property("NormalizedName")
33 | .HasAnnotation("MaxLength", 256);
34 |
35 | b.HasKey("Id");
36 |
37 | b.HasIndex("NormalizedName")
38 | .HasName("RoleNameIndex");
39 |
40 | b.ToTable("AspNetRoles");
41 | });
42 |
43 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityRoleClaim", b =>
44 | {
45 | b.Property("Id")
46 | .ValueGeneratedOnAdd();
47 |
48 | b.Property("ClaimType");
49 |
50 | b.Property("ClaimValue");
51 |
52 | b.Property("RoleId")
53 | .IsRequired();
54 |
55 | b.HasKey("Id");
56 |
57 | b.HasIndex("RoleId");
58 |
59 | b.ToTable("AspNetRoleClaims");
60 | });
61 |
62 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserClaim", b =>
63 | {
64 | b.Property("Id")
65 | .ValueGeneratedOnAdd();
66 |
67 | b.Property("ClaimType");
68 |
69 | b.Property("ClaimValue");
70 |
71 | b.Property("UserId")
72 | .IsRequired();
73 |
74 | b.HasKey("Id");
75 |
76 | b.HasIndex("UserId");
77 |
78 | b.ToTable("AspNetUserClaims");
79 | });
80 |
81 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserLogin", b =>
82 | {
83 | b.Property("LoginProvider");
84 |
85 | b.Property("ProviderKey");
86 |
87 | b.Property("ProviderDisplayName");
88 |
89 | b.Property("UserId")
90 | .IsRequired();
91 |
92 | b.HasKey("LoginProvider", "ProviderKey");
93 |
94 | b.HasIndex("UserId");
95 |
96 | b.ToTable("AspNetUserLogins");
97 | });
98 |
99 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserRole", b =>
100 | {
101 | b.Property("UserId");
102 |
103 | b.Property("RoleId");
104 |
105 | b.HasKey("UserId", "RoleId");
106 |
107 | b.HasIndex("RoleId");
108 |
109 | b.HasIndex("UserId");
110 |
111 | b.ToTable("AspNetUserRoles");
112 | });
113 |
114 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserToken", b =>
115 | {
116 | b.Property("UserId");
117 |
118 | b.Property("LoginProvider");
119 |
120 | b.Property("Name");
121 |
122 | b.Property("Value");
123 |
124 | b.HasKey("UserId", "LoginProvider", "Name");
125 |
126 | b.ToTable("AspNetUserTokens");
127 | });
128 |
129 | modelBuilder.Entity("DosFactores.Models.ApplicationUser", b =>
130 | {
131 | b.Property("Id");
132 |
133 | b.Property("AccessFailedCount");
134 |
135 | b.Property("ConcurrencyStamp")
136 | .IsConcurrencyToken();
137 |
138 | b.Property("Email")
139 | .HasAnnotation("MaxLength", 256);
140 |
141 | b.Property("EmailConfirmed");
142 |
143 | b.Property("LockoutEnabled");
144 |
145 | b.Property("LockoutEnd");
146 |
147 | b.Property("NormalizedEmail")
148 | .HasAnnotation("MaxLength", 256);
149 |
150 | b.Property("NormalizedUserName")
151 | .HasAnnotation("MaxLength", 256);
152 |
153 | b.Property("PasswordHash");
154 |
155 | b.Property("PhoneNumber");
156 |
157 | b.Property("PhoneNumberConfirmed");
158 |
159 | b.Property("SecurityStamp");
160 |
161 | b.Property("TwoFactorEnabled");
162 |
163 | b.Property("UserName")
164 | .HasAnnotation("MaxLength", 256);
165 |
166 | b.HasKey("Id");
167 |
168 | b.HasIndex("NormalizedEmail")
169 | .HasName("EmailIndex");
170 |
171 | b.HasIndex("NormalizedUserName")
172 | .IsUnique()
173 | .HasName("UserNameIndex");
174 |
175 | b.ToTable("AspNetUsers");
176 | });
177 |
178 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityRoleClaim", b =>
179 | {
180 | b.HasOne("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityRole")
181 | .WithMany("Claims")
182 | .HasForeignKey("RoleId")
183 | .OnDelete(DeleteBehavior.Cascade);
184 | });
185 |
186 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserClaim", b =>
187 | {
188 | b.HasOne("DosFactores.Models.ApplicationUser")
189 | .WithMany("Claims")
190 | .HasForeignKey("UserId")
191 | .OnDelete(DeleteBehavior.Cascade);
192 | });
193 |
194 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserLogin", b =>
195 | {
196 | b.HasOne("DosFactores.Models.ApplicationUser")
197 | .WithMany("Logins")
198 | .HasForeignKey("UserId")
199 | .OnDelete(DeleteBehavior.Cascade);
200 | });
201 |
202 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserRole", b =>
203 | {
204 | b.HasOne("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityRole")
205 | .WithMany("Users")
206 | .HasForeignKey("RoleId")
207 | .OnDelete(DeleteBehavior.Cascade);
208 |
209 | b.HasOne("DosFactores.Models.ApplicationUser")
210 | .WithMany("Roles")
211 | .HasForeignKey("UserId")
212 | .OnDelete(DeleteBehavior.Cascade);
213 | });
214 | }
215 | }
216 | }
217 |
--------------------------------------------------------------------------------
/DosFactores/wwwroot/images/banner1.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/DosFactores/Data/Migrations/00000000000000_CreateIdentitySchema.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 | using Microsoft.EntityFrameworkCore.Metadata;
6 | using Microsoft.EntityFrameworkCore.Migrations;
7 |
8 | namespace DosFactores.Data.Migrations
9 | {
10 | public partial class CreateIdentitySchema : Migration
11 | {
12 | protected override void Up(MigrationBuilder migrationBuilder)
13 | {
14 | migrationBuilder.CreateTable(
15 | name: "AspNetRoles",
16 | columns: table => new
17 | {
18 | Id = table.Column(nullable: false),
19 | ConcurrencyStamp = table.Column(nullable: true),
20 | Name = table.Column(maxLength: 256, nullable: true),
21 | NormalizedName = table.Column(maxLength: 256, nullable: true)
22 | },
23 | constraints: table =>
24 | {
25 | table.PrimaryKey("PK_AspNetRoles", x => x.Id);
26 | });
27 |
28 | migrationBuilder.CreateTable(
29 | name: "AspNetUserTokens",
30 | columns: table => new
31 | {
32 | UserId = table.Column(nullable: false),
33 | LoginProvider = table.Column(nullable: false),
34 | Name = table.Column(nullable: false),
35 | Value = table.Column(nullable: true)
36 | },
37 | constraints: table =>
38 | {
39 | table.PrimaryKey("PK_AspNetUserTokens", x => new { x.UserId, x.LoginProvider, x.Name });
40 | });
41 |
42 | migrationBuilder.CreateTable(
43 | name: "AspNetUsers",
44 | columns: table => new
45 | {
46 | Id = table.Column(nullable: false),
47 | AccessFailedCount = table.Column(nullable: false),
48 | ConcurrencyStamp = table.Column(nullable: true),
49 | Email = table.Column(maxLength: 256, nullable: true),
50 | EmailConfirmed = table.Column(nullable: false),
51 | LockoutEnabled = table.Column(nullable: false),
52 | LockoutEnd = table.Column(nullable: true),
53 | NormalizedEmail = table.Column(maxLength: 256, nullable: true),
54 | NormalizedUserName = table.Column(maxLength: 256, nullable: true),
55 | PasswordHash = table.Column(nullable: true),
56 | PhoneNumber = table.Column(nullable: true),
57 | PhoneNumberConfirmed = table.Column(nullable: false),
58 | SecurityStamp = table.Column(nullable: true),
59 | TfaKey = table.Column(nullable: true),
60 | TwoFactorEnabled = table.Column(nullable: false),
61 | UserName = table.Column(maxLength: 256, nullable: true)
62 | },
63 | constraints: table =>
64 | {
65 | table.PrimaryKey("PK_AspNetUsers", x => x.Id);
66 | });
67 |
68 | migrationBuilder.CreateTable(
69 | name: "AspNetRoleClaims",
70 | columns: table => new
71 | {
72 | Id = table.Column(nullable: false)
73 | .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
74 | ClaimType = table.Column(nullable: true),
75 | ClaimValue = table.Column(nullable: true),
76 | RoleId = table.Column(nullable: false)
77 | },
78 | constraints: table =>
79 | {
80 | table.PrimaryKey("PK_AspNetRoleClaims", x => x.Id);
81 | table.ForeignKey(
82 | name: "FK_AspNetRoleClaims_AspNetRoles_RoleId",
83 | column: x => x.RoleId,
84 | principalTable: "AspNetRoles",
85 | principalColumn: "Id",
86 | onDelete: ReferentialAction.Cascade);
87 | });
88 |
89 | migrationBuilder.CreateTable(
90 | name: "AspNetUserClaims",
91 | columns: table => new
92 | {
93 | Id = table.Column(nullable: false)
94 | .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
95 | ClaimType = table.Column(nullable: true),
96 | ClaimValue = table.Column(nullable: true),
97 | UserId = table.Column(nullable: false)
98 | },
99 | constraints: table =>
100 | {
101 | table.PrimaryKey("PK_AspNetUserClaims", x => x.Id);
102 | table.ForeignKey(
103 | name: "FK_AspNetUserClaims_AspNetUsers_UserId",
104 | column: x => x.UserId,
105 | principalTable: "AspNetUsers",
106 | principalColumn: "Id",
107 | onDelete: ReferentialAction.Cascade);
108 | });
109 |
110 | migrationBuilder.CreateTable(
111 | name: "AspNetUserLogins",
112 | columns: table => new
113 | {
114 | LoginProvider = table.Column(nullable: false),
115 | ProviderKey = table.Column(nullable: false),
116 | ProviderDisplayName = table.Column(nullable: true),
117 | UserId = table.Column(nullable: false)
118 | },
119 | constraints: table =>
120 | {
121 | table.PrimaryKey("PK_AspNetUserLogins", x => new { x.LoginProvider, x.ProviderKey });
122 | table.ForeignKey(
123 | name: "FK_AspNetUserLogins_AspNetUsers_UserId",
124 | column: x => x.UserId,
125 | principalTable: "AspNetUsers",
126 | principalColumn: "Id",
127 | onDelete: ReferentialAction.Cascade);
128 | });
129 |
130 | migrationBuilder.CreateTable(
131 | name: "AspNetUserRoles",
132 | columns: table => new
133 | {
134 | UserId = table.Column(nullable: false),
135 | RoleId = table.Column(nullable: false)
136 | },
137 | constraints: table =>
138 | {
139 | table.PrimaryKey("PK_AspNetUserRoles", x => new { x.UserId, x.RoleId });
140 | table.ForeignKey(
141 | name: "FK_AspNetUserRoles_AspNetRoles_RoleId",
142 | column: x => x.RoleId,
143 | principalTable: "AspNetRoles",
144 | principalColumn: "Id",
145 | onDelete: ReferentialAction.Cascade);
146 | table.ForeignKey(
147 | name: "FK_AspNetUserRoles_AspNetUsers_UserId",
148 | column: x => x.UserId,
149 | principalTable: "AspNetUsers",
150 | principalColumn: "Id",
151 | onDelete: ReferentialAction.Cascade);
152 | });
153 |
154 | migrationBuilder.CreateIndex(
155 | name: "RoleNameIndex",
156 | table: "AspNetRoles",
157 | column: "NormalizedName");
158 |
159 | migrationBuilder.CreateIndex(
160 | name: "IX_AspNetRoleClaims_RoleId",
161 | table: "AspNetRoleClaims",
162 | column: "RoleId");
163 |
164 | migrationBuilder.CreateIndex(
165 | name: "IX_AspNetUserClaims_UserId",
166 | table: "AspNetUserClaims",
167 | column: "UserId");
168 |
169 | migrationBuilder.CreateIndex(
170 | name: "IX_AspNetUserLogins_UserId",
171 | table: "AspNetUserLogins",
172 | column: "UserId");
173 |
174 | migrationBuilder.CreateIndex(
175 | name: "IX_AspNetUserRoles_RoleId",
176 | table: "AspNetUserRoles",
177 | column: "RoleId");
178 |
179 | migrationBuilder.CreateIndex(
180 | name: "IX_AspNetUserRoles_UserId",
181 | table: "AspNetUserRoles",
182 | column: "UserId");
183 |
184 | migrationBuilder.CreateIndex(
185 | name: "EmailIndex",
186 | table: "AspNetUsers",
187 | column: "NormalizedEmail");
188 |
189 | migrationBuilder.CreateIndex(
190 | name: "UserNameIndex",
191 | table: "AspNetUsers",
192 | column: "NormalizedUserName",
193 | unique: true);
194 | }
195 |
196 | protected override void Down(MigrationBuilder migrationBuilder)
197 | {
198 | migrationBuilder.DropTable(
199 | name: "AspNetRoleClaims");
200 |
201 | migrationBuilder.DropTable(
202 | name: "AspNetUserClaims");
203 |
204 | migrationBuilder.DropTable(
205 | name: "AspNetUserLogins");
206 |
207 | migrationBuilder.DropTable(
208 | name: "AspNetUserRoles");
209 |
210 | migrationBuilder.DropTable(
211 | name: "AspNetUserTokens");
212 |
213 | migrationBuilder.DropTable(
214 | name: "AspNetRoles");
215 |
216 | migrationBuilder.DropTable(
217 | name: "AspNetUsers");
218 | }
219 | }
220 | }
221 |
--------------------------------------------------------------------------------
/DosFactores/wwwroot/images/banner3.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/DosFactores/wwwroot/images/banner4.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/Google.Authenticator/TwoFactorAuthenticator.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Security.Cryptography;
5 | using System.Text;
6 |
7 | namespace Google.Authenticator
8 | {
9 | public class TwoFactorAuthenticator
10 | {
11 | public static DateTime _epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
12 | public TimeSpan DefaultClockDriftTolerance { get; set; }
13 | public bool UseManagedSha1Algorithm { get; set; }
14 | public bool TryUnmanagedAlgorithmOnFailure { get; set; }
15 |
16 | public TwoFactorAuthenticator() : this(true, true) { }
17 |
18 | public TwoFactorAuthenticator(bool useManagedSha1, bool useUnmanagedOnFail)
19 | {
20 | DefaultClockDriftTolerance = TimeSpan.FromMinutes(5);
21 | UseManagedSha1Algorithm = useManagedSha1;
22 | TryUnmanagedAlgorithmOnFailure = useUnmanagedOnFail;
23 | }
24 |
25 | ///
26 | /// Generate a setup code for a Google Authenticator user to scan.
27 | ///
28 | /// Account Title (no spaces)
29 | /// Account Secret Key
30 | /// QR Code Width
31 | /// QR Code Height
32 | /// SetupCode object
33 | public SetupCode GenerateSetupCode(string accountTitleNoSpaces, string accountSecretKey, int qrCodeWidth, int qrCodeHeight)
34 | {
35 | return GenerateSetupCode(null, accountTitleNoSpaces, accountSecretKey, qrCodeWidth, qrCodeHeight);
36 | }
37 |
38 | ///
39 | /// Generate a setup code for a Google Authenticator user to scan (with issuer ID).
40 | ///
41 | /// Issuer ID (the name of the system, i.e. 'MyApp')
42 | /// Account Title (no spaces)
43 | /// Account Secret Key
44 | /// QR Code Width
45 | /// QR Code Height
46 | /// SetupCode object
47 | public SetupCode GenerateSetupCode(string issuer, string accountTitleNoSpaces, string accountSecretKey, int qrCodeWidth, int qrCodeHeight)
48 | {
49 | return GenerateSetupCode(issuer, accountTitleNoSpaces, accountSecretKey, qrCodeWidth, qrCodeHeight, false);
50 | }
51 |
52 | ///
53 | /// Generate a setup code for a Google Authenticator user to scan (with issuer ID).
54 | ///
55 | /// Issuer ID (the name of the system, i.e. 'MyApp')
56 | /// Account Title (no spaces)
57 | /// Account Secret Key
58 | /// QR Code Width
59 | /// QR Code Height
60 | /// Use HTTPS instead of HTTP
61 | /// SetupCode object
62 | public SetupCode GenerateSetupCode(string issuer, string accountTitleNoSpaces, string accountSecretKey, int qrCodeWidth, int qrCodeHeight, bool useHttps)
63 | {
64 | if (accountTitleNoSpaces == null) { throw new NullReferenceException("Account Title is null"); }
65 |
66 | accountTitleNoSpaces = accountTitleNoSpaces.Replace(" ", "");
67 |
68 | SetupCode sC = new SetupCode();
69 | sC.Account = accountTitleNoSpaces;
70 | sC.AccountSecretKey = accountSecretKey;
71 |
72 | string encodedSecretKey = EncodeAccountSecretKey(accountSecretKey);
73 | sC.ManualEntryKey = encodedSecretKey;
74 |
75 | string provisionUrl = null;
76 |
77 | if (string.IsNullOrEmpty(issuer))
78 | {
79 | provisionUrl = UrlEncode(String.Format("otpauth://totp/{0}?secret={1}", accountTitleNoSpaces, encodedSecretKey));
80 | }
81 | else
82 | {
83 | provisionUrl = UrlEncode(String.Format("otpauth://totp/{0}?secret={1}&issuer={2}", accountTitleNoSpaces, encodedSecretKey, UrlEncode(issuer)));
84 | }
85 |
86 | string protocol = useHttps ? "https" : "http";
87 | string url = String.Format("{0}://chart.googleapis.com/chart?cht=qr&chs={1}x{2}&chl={3}", protocol, qrCodeWidth, qrCodeHeight, provisionUrl);
88 |
89 | sC.QrCodeSetupImageUrl = url;
90 |
91 | return sC;
92 | }
93 |
94 | private string UrlEncode(string value)
95 | {
96 | StringBuilder result = new StringBuilder();
97 | string validChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.~";
98 |
99 | foreach (char symbol in value)
100 | {
101 | if (validChars.IndexOf(symbol) != -1)
102 | {
103 | result.Append(symbol);
104 | }
105 | else
106 | {
107 | result.Append('%' + String.Format("{0:X2}", (int)symbol));
108 | }
109 | }
110 |
111 | return result.ToString().Replace(" ", "%20");
112 | }
113 |
114 | private string EncodeAccountSecretKey(string accountSecretKey)
115 | {
116 | //if (accountSecretKey.Length < 10)
117 | //{
118 | // accountSecretKey = accountSecretKey.PadRight(10, '0');
119 | //}
120 |
121 | //if (accountSecretKey.Length > 12)
122 | //{
123 | // accountSecretKey = accountSecretKey.Substring(0, 12);
124 | //}
125 |
126 | return Base32Encode(Encoding.UTF8.GetBytes(accountSecretKey));
127 | }
128 |
129 | private string Base32Encode(byte[] data)
130 | {
131 | int inByteSize = 8;
132 | int outByteSize = 5;
133 | char[] alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567".ToCharArray();
134 |
135 | int i = 0, index = 0, digit = 0;
136 | int current_byte, next_byte;
137 | StringBuilder result = new StringBuilder((data.Length + 7) * inByteSize / outByteSize);
138 |
139 | while (i < data.Length)
140 | {
141 | current_byte = (data[i] >= 0) ? data[i] : (data[i] + 256); // Unsign
142 |
143 | /* Is the current digit going to span a byte boundary? */
144 | if (index > (inByteSize - outByteSize))
145 | {
146 | if ((i + 1) < data.Length)
147 | next_byte = (data[i + 1] >= 0) ? data[i + 1] : (data[i + 1] + 256);
148 | else
149 | next_byte = 0;
150 |
151 | digit = current_byte & (0xFF >> index);
152 | index = (index + outByteSize) % inByteSize;
153 | digit <<= index;
154 | digit |= next_byte >> (inByteSize - index);
155 | i++;
156 | }
157 | else
158 | {
159 | digit = (current_byte >> (inByteSize - (index + outByteSize))) & 0x1F;
160 | index = (index + outByteSize) % inByteSize;
161 | if (index == 0)
162 | i++;
163 | }
164 | result.Append(alphabet[digit]);
165 | }
166 |
167 | return result.ToString();
168 | }
169 |
170 | public string GeneratePINAtInterval(string accountSecretKey, long counter, int digits = 6)
171 | {
172 | return GenerateHashedCode(accountSecretKey, counter, digits);
173 | }
174 |
175 | internal string GenerateHashedCode(string secret, long iterationNumber, int digits = 6)
176 | {
177 | byte[] key = Encoding.UTF8.GetBytes(secret);
178 | return GenerateHashedCode(key, iterationNumber, digits);
179 | }
180 |
181 | internal string GenerateHashedCode(byte[] key, long iterationNumber, int digits = 6)
182 | {
183 | byte[] counter = BitConverter.GetBytes(iterationNumber);
184 |
185 | if (BitConverter.IsLittleEndian)
186 | {
187 | Array.Reverse(counter);
188 | }
189 |
190 | HMACSHA1 hmac = getHMACSha1Algorithm(key);
191 |
192 | byte[] hash = hmac.ComputeHash(counter);
193 |
194 | int offset = hash[hash.Length - 1] & 0xf;
195 |
196 | // Convert the 4 bytes into an integer, ignoring the sign.
197 | int binary =
198 | ((hash[offset] & 0x7f) << 24)
199 | | (hash[offset + 1] << 16)
200 | | (hash[offset + 2] << 8)
201 | | (hash[offset + 3]);
202 |
203 | int password = binary % (int)Math.Pow(10, digits);
204 | return password.ToString(new string('0', digits));
205 | }
206 |
207 | private long GetCurrentCounter()
208 | {
209 | return GetCurrentCounter(DateTime.UtcNow, _epoch, 30);
210 | }
211 |
212 | private long GetCurrentCounter(DateTime now, DateTime epoch, int timeStep)
213 | {
214 | return (long)(now - epoch).TotalSeconds / timeStep;
215 | }
216 |
217 | ///
218 | /// Creates a HMACSHA1 algorithm to use to hash the counter bytes. By default, this will attempt to use
219 | /// the managed SHA1 class (SHA1Manager) and on exception (FIPS-compliant machine policy, etc) will attempt
220 | /// to use the unmanaged SHA1 class (SHA1CryptoServiceProvider).
221 | ///
222 | /// User's secret key, in bytes
223 | /// HMACSHA1 cryptographic algorithm
224 | private HMACSHA1 getHMACSha1Algorithm(byte[] key)
225 | {
226 | HMACSHA1 hmac;
227 |
228 | try
229 | {
230 | hmac = new HMACSHA1(key);//, UseManagedSha1Algorithm);
231 | }
232 | catch (InvalidOperationException ioe)
233 | {
234 | if (UseManagedSha1Algorithm && TryUnmanagedAlgorithmOnFailure)
235 | {
236 | try
237 | {
238 | hmac = new HMACSHA1(key);
239 | }
240 | catch (InvalidOperationException ioe2)
241 | {
242 | throw ioe2;
243 | }
244 | }
245 | else
246 | {
247 | throw ioe;
248 | }
249 | }
250 |
251 | return hmac;
252 | }
253 |
254 | public bool ValidateTwoFactorPIN(string accountSecretKey, string twoFactorCodeFromClient)
255 | {
256 | return ValidateTwoFactorPIN(accountSecretKey, twoFactorCodeFromClient, DefaultClockDriftTolerance);
257 | }
258 |
259 | public bool ValidateTwoFactorPIN(string accountSecretKey, string twoFactorCodeFromClient, TimeSpan timeTolerance)
260 | {
261 | var codes = GetCurrentPINs(accountSecretKey, timeTolerance);
262 | return codes.Any(c => c == twoFactorCodeFromClient);
263 | }
264 |
265 | public string GetCurrentPIN(string accountSecretKey)
266 | {
267 | return GeneratePINAtInterval(accountSecretKey, GetCurrentCounter());
268 | }
269 |
270 | public string GetCurrentPIN(string accountSecretKey, DateTime now)
271 | {
272 | return GeneratePINAtInterval(accountSecretKey, GetCurrentCounter(now, _epoch, 30));
273 | }
274 |
275 | public string[] GetCurrentPINs(string accountSecretKey)
276 | {
277 | return GetCurrentPINs(accountSecretKey, DefaultClockDriftTolerance);
278 | }
279 |
280 | public string[] GetCurrentPINs(string accountSecretKey, TimeSpan timeTolerance)
281 | {
282 | List codes = new List();
283 | long iterationCounter = GetCurrentCounter();
284 | int iterationOffset = 0;
285 |
286 | if (timeTolerance.TotalSeconds > 30)
287 | {
288 | iterationOffset = Convert.ToInt32(timeTolerance.TotalSeconds / 30.00);
289 | }
290 |
291 | long iterationStart = iterationCounter - iterationOffset;
292 | long iterationEnd = iterationCounter + iterationOffset;
293 |
294 | for (long counter = iterationStart; counter <= iterationEnd; counter++)
295 | {
296 | codes.Add(GeneratePINAtInterval(accountSecretKey, counter));
297 | }
298 |
299 | return codes.ToArray();
300 | }
301 | }
302 | }
303 |
--------------------------------------------------------------------------------
/DosFactores/wwwroot/lib/jquery-validation/dist/additional-methods.min.js:
--------------------------------------------------------------------------------
1 | /*! jQuery Validation Plugin - v1.14.0 - 6/30/2015
2 | * http://jqueryvalidation.org/
3 | * Copyright (c) 2015 Jörn Zaefferer; Licensed MIT */
4 | !function(a){"function"==typeof define&&define.amd?define(["jquery","./jquery.validate.min"],a):a(jQuery)}(function(a){!function(){function b(a){return a.replace(/<.[^<>]*?>/g," ").replace(/ | /gi," ").replace(/[.(),;:!?%#$'\"_+=\/\-“”’]*/g,"")}a.validator.addMethod("maxWords",function(a,c,d){return this.optional(c)||b(a).match(/\b\w+\b/g).length<=d},a.validator.format("Please enter {0} words or less.")),a.validator.addMethod("minWords",function(a,c,d){return this.optional(c)||b(a).match(/\b\w+\b/g).length>=d},a.validator.format("Please enter at least {0} words.")),a.validator.addMethod("rangeWords",function(a,c,d){var e=b(a),f=/\b\w+\b/g;return this.optional(c)||e.match(f).length>=d[0]&&e.match(f).length<=d[1]},a.validator.format("Please enter between {0} and {1} words."))}(),a.validator.addMethod("accept",function(b,c,d){var e,f,g="string"==typeof d?d.replace(/\s/g,"").replace(/,/g,"|"):"image/*",h=this.optional(c);if(h)return h;if("file"===a(c).attr("type")&&(g=g.replace(/\*/g,".*"),c.files&&c.files.length))for(e=0;ec;c++)d=h-c,e=f.substring(c,c+1),g+=d*e;return g%11===0},"Please specify a valid bank account number"),a.validator.addMethod("bankorgiroaccountNL",function(b,c){return this.optional(c)||a.validator.methods.bankaccountNL.call(this,b,c)||a.validator.methods.giroaccountNL.call(this,b,c)},"Please specify a valid bank or giro account number"),a.validator.addMethod("bic",function(a,b){return this.optional(b)||/^([A-Z]{6}[A-Z2-9][A-NP-Z1-2])(X{3}|[A-WY-Z0-9][A-Z0-9]{2})?$/.test(a)},"Please specify a valid BIC code"),a.validator.addMethod("cifES",function(a){"use strict";var b,c,d,e,f,g,h=[];if(a=a.toUpperCase(),!a.match("((^[A-Z]{1}[0-9]{7}[A-Z0-9]{1}$|^[T]{1}[A-Z0-9]{8}$)|^[0-9]{8}[A-Z]{1}$)"))return!1;for(d=0;9>d;d++)h[d]=parseInt(a.charAt(d),10);for(c=h[2]+h[4]+h[6],e=1;8>e;e+=2)f=(2*h[e]).toString(),g=f.charAt(1),c+=parseInt(f.charAt(0),10)+(""===g?0:parseInt(g,10));return/^[ABCDEFGHJNPQRSUVW]{1}/.test(a)?(c+="",b=10-parseInt(c.charAt(c.length-1),10),a+=b,h[8].toString()===String.fromCharCode(64+b)||h[8].toString()===a.charAt(a.length-1)):!1},"Please specify a valid CIF number."),a.validator.addMethod("cpfBR",function(a){if(a=a.replace(/([~!@#$%^&*()_+=`{}\[\]\-|\\:;'<>,.\/? ])+/g,""),11!==a.length)return!1;var b,c,d,e,f=0;if(b=parseInt(a.substring(9,10),10),c=parseInt(a.substring(10,11),10),d=function(a,b){var c=10*a%11;return(10===c||11===c)&&(c=0),c===b},""===a||"00000000000"===a||"11111111111"===a||"22222222222"===a||"33333333333"===a||"44444444444"===a||"55555555555"===a||"66666666666"===a||"77777777777"===a||"88888888888"===a||"99999999999"===a)return!1;for(e=1;9>=e;e++)f+=parseInt(a.substring(e-1,e),10)*(11-e);if(d(f,b)){for(f=0,e=1;10>=e;e++)f+=parseInt(a.substring(e-1,e),10)*(12-e);return d(f,c)}return!1},"Please specify a valid CPF number"),a.validator.addMethod("creditcardtypes",function(a,b,c){if(/[^0-9\-]+/.test(a))return!1;a=a.replace(/\D/g,"");var d=0;return c.mastercard&&(d|=1),c.visa&&(d|=2),c.amex&&(d|=4),c.dinersclub&&(d|=8),c.enroute&&(d|=16),c.discover&&(d|=32),c.jcb&&(d|=64),c.unknown&&(d|=128),c.all&&(d=255),1&d&&/^(5[12345])/.test(a)?16===a.length:2&d&&/^(4)/.test(a)?16===a.length:4&d&&/^(3[47])/.test(a)?15===a.length:8&d&&/^(3(0[012345]|[68]))/.test(a)?14===a.length:16&d&&/^(2(014|149))/.test(a)?15===a.length:32&d&&/^(6011)/.test(a)?16===a.length:64&d&&/^(3)/.test(a)?16===a.length:64&d&&/^(2131|1800)/.test(a)?15===a.length:128&d?!0:!1},"Please enter a valid credit card number."),a.validator.addMethod("currency",function(a,b,c){var d,e="string"==typeof c,f=e?c:c[0],g=e?!0:c[1];return f=f.replace(/,/g,""),f=g?f+"]":f+"]?",d="^["+f+"([1-9]{1}[0-9]{0,2}(\\,[0-9]{3})*(\\.[0-9]{0,2})?|[1-9]{1}[0-9]{0,}(\\.[0-9]{0,2})?|0(\\.[0-9]{0,2})?|(\\.[0-9]{1,2})?)$",d=new RegExp(d),this.optional(b)||d.test(a)},"Please specify a valid currency"),a.validator.addMethod("dateFA",function(a,b){return this.optional(b)||/^[1-4]\d{3}\/((0?[1-6]\/((3[0-1])|([1-2][0-9])|(0?[1-9])))|((1[0-2]|(0?[7-9]))\/(30|([1-2][0-9])|(0?[1-9]))))$/.test(a)},a.validator.messages.date),a.validator.addMethod("dateITA",function(a,b){var c,d,e,f,g,h=!1,i=/^\d{1,2}\/\d{1,2}\/\d{4}$/;return i.test(a)?(c=a.split("/"),d=parseInt(c[0],10),e=parseInt(c[1],10),f=parseInt(c[2],10),g=new Date(Date.UTC(f,e-1,d,12,0,0,0)),h=g.getUTCFullYear()===f&&g.getUTCMonth()===e-1&&g.getUTCDate()===d?!0:!1):h=!1,this.optional(b)||h},a.validator.messages.date),a.validator.addMethod("dateNL",function(a,b){return this.optional(b)||/^(0?[1-9]|[12]\d|3[01])[\.\/\-](0?[1-9]|1[012])[\.\/\-]([12]\d)?(\d\d)$/.test(a)},a.validator.messages.date),a.validator.addMethod("extension",function(a,b,c){return c="string"==typeof c?c.replace(/,/g,"|"):"png|jpe?g|gif",this.optional(b)||a.match(new RegExp("\\.("+c+")$","i"))},a.validator.format("Please enter a value with a valid extension.")),a.validator.addMethod("giroaccountNL",function(a,b){return this.optional(b)||/^[0-9]{1,7}$/.test(a)},"Please specify a valid giro account number"),a.validator.addMethod("iban",function(a,b){if(this.optional(b))return!0;var c,d,e,f,g,h,i,j,k,l=a.replace(/ /g,"").toUpperCase(),m="",n=!0,o="",p="";if(c=l.substring(0,2),h={AL:"\\d{8}[\\dA-Z]{16}",AD:"\\d{8}[\\dA-Z]{12}",AT:"\\d{16}",AZ:"[\\dA-Z]{4}\\d{20}",BE:"\\d{12}",BH:"[A-Z]{4}[\\dA-Z]{14}",BA:"\\d{16}",BR:"\\d{23}[A-Z][\\dA-Z]",BG:"[A-Z]{4}\\d{6}[\\dA-Z]{8}",CR:"\\d{17}",HR:"\\d{17}",CY:"\\d{8}[\\dA-Z]{16}",CZ:"\\d{20}",DK:"\\d{14}",DO:"[A-Z]{4}\\d{20}",EE:"\\d{16}",FO:"\\d{14}",FI:"\\d{14}",FR:"\\d{10}[\\dA-Z]{11}\\d{2}",GE:"[\\dA-Z]{2}\\d{16}",DE:"\\d{18}",GI:"[A-Z]{4}[\\dA-Z]{15}",GR:"\\d{7}[\\dA-Z]{16}",GL:"\\d{14}",GT:"[\\dA-Z]{4}[\\dA-Z]{20}",HU:"\\d{24}",IS:"\\d{22}",IE:"[\\dA-Z]{4}\\d{14}",IL:"\\d{19}",IT:"[A-Z]\\d{10}[\\dA-Z]{12}",KZ:"\\d{3}[\\dA-Z]{13}",KW:"[A-Z]{4}[\\dA-Z]{22}",LV:"[A-Z]{4}[\\dA-Z]{13}",LB:"\\d{4}[\\dA-Z]{20}",LI:"\\d{5}[\\dA-Z]{12}",LT:"\\d{16}",LU:"\\d{3}[\\dA-Z]{13}",MK:"\\d{3}[\\dA-Z]{10}\\d{2}",MT:"[A-Z]{4}\\d{5}[\\dA-Z]{18}",MR:"\\d{23}",MU:"[A-Z]{4}\\d{19}[A-Z]{3}",MC:"\\d{10}[\\dA-Z]{11}\\d{2}",MD:"[\\dA-Z]{2}\\d{18}",ME:"\\d{18}",NL:"[A-Z]{4}\\d{10}",NO:"\\d{11}",PK:"[\\dA-Z]{4}\\d{16}",PS:"[\\dA-Z]{4}\\d{21}",PL:"\\d{24}",PT:"\\d{21}",RO:"[A-Z]{4}[\\dA-Z]{16}",SM:"[A-Z]\\d{10}[\\dA-Z]{12}",SA:"\\d{2}[\\dA-Z]{18}",RS:"\\d{18}",SK:"\\d{20}",SI:"\\d{15}",ES:"\\d{20}",SE:"\\d{20}",CH:"\\d{5}[\\dA-Z]{12}",TN:"\\d{20}",TR:"\\d{5}[\\dA-Z]{17}",AE:"\\d{3}\\d{16}",GB:"[A-Z]{4}\\d{14}",VG:"[\\dA-Z]{4}\\d{16}"},g=h[c],"undefined"!=typeof g&&(i=new RegExp("^[A-Z]{2}\\d{2}"+g+"$",""),!i.test(l)))return!1;for(d=l.substring(4,l.length)+l.substring(0,4),j=0;j9&&a.match(/^(?:(?:(?:00\s?|\+)44\s?|0)7(?:[1345789]\d{2}|624)\s?\d{3}\s?\d{3})$/)},"Please specify a valid mobile number"),a.validator.addMethod("nieES",function(a){"use strict";return a=a.toUpperCase(),a.match("((^[A-Z]{1}[0-9]{7}[A-Z0-9]{1}$|^[T]{1}[A-Z0-9]{8}$)|^[0-9]{8}[A-Z]{1}$)")?/^[T]{1}/.test(a)?a[8]===/^[T]{1}[A-Z0-9]{8}$/.test(a):/^[XYZ]{1}/.test(a)?a[8]==="TRWAGMYFPDXBNJZSQVHLCKE".charAt(a.replace("X","0").replace("Y","1").replace("Z","2").substring(0,8)%23):!1:!1},"Please specify a valid NIE number."),a.validator.addMethod("nifES",function(a){"use strict";return a=a.toUpperCase(),a.match("((^[A-Z]{1}[0-9]{7}[A-Z0-9]{1}$|^[T]{1}[A-Z0-9]{8}$)|^[0-9]{8}[A-Z]{1}$)")?/^[0-9]{8}[A-Z]{1}$/.test(a)?"TRWAGMYFPDXBNJZSQVHLCKE".charAt(a.substring(8,0)%23)===a.charAt(8):/^[KLM]{1}/.test(a)?a[8]===String.fromCharCode(64):!1:!1},"Please specify a valid NIF number."),jQuery.validator.addMethod("notEqualTo",function(b,c,d){return this.optional(c)||!a.validator.methods.equalTo.call(this,b,c,d)},"Please enter a different value, values must not be the same."),a.validator.addMethod("nowhitespace",function(a,b){return this.optional(b)||/^\S+$/i.test(a)},"No white space please"),a.validator.addMethod("pattern",function(a,b,c){return this.optional(b)?!0:("string"==typeof c&&(c=new RegExp("^(?:"+c+")$")),c.test(a))},"Invalid format."),a.validator.addMethod("phoneNL",function(a,b){return this.optional(b)||/^((\+|00(\s|\s?\-\s?)?)31(\s|\s?\-\s?)?(\(0\)[\-\s]?)?|0)[1-9]((\s|\s?\-\s?)?[0-9]){8}$/.test(a)},"Please specify a valid phone number."),a.validator.addMethod("phoneUK",function(a,b){return a=a.replace(/\(|\)|\s+|-/g,""),this.optional(b)||a.length>9&&a.match(/^(?:(?:(?:00\s?|\+)44\s?)|(?:\(?0))(?:\d{2}\)?\s?\d{4}\s?\d{4}|\d{3}\)?\s?\d{3}\s?\d{3,4}|\d{4}\)?\s?(?:\d{5}|\d{3}\s?\d{3})|\d{5}\)?\s?\d{4,5})$/)},"Please specify a valid phone number"),a.validator.addMethod("phoneUS",function(a,b){return a=a.replace(/\s+/g,""),this.optional(b)||a.length>9&&a.match(/^(\+?1-?)?(\([2-9]([02-9]\d|1[02-9])\)|[2-9]([02-9]\d|1[02-9]))-?[2-9]([02-9]\d|1[02-9])-?\d{4}$/)},"Please specify a valid phone number"),a.validator.addMethod("phonesUK",function(a,b){return a=a.replace(/\(|\)|\s+|-/g,""),this.optional(b)||a.length>9&&a.match(/^(?:(?:(?:00\s?|\+)44\s?|0)(?:1\d{8,9}|[23]\d{9}|7(?:[1345789]\d{8}|624\d{6})))$/)},"Please specify a valid uk phone number"),a.validator.addMethod("postalCodeCA",function(a,b){return this.optional(b)||/^[ABCEGHJKLMNPRSTVXY]\d[A-Z] \d[A-Z]\d$/.test(a)},"Please specify a valid postal code"),a.validator.addMethod("postalcodeBR",function(a,b){return this.optional(b)||/^\d{2}.\d{3}-\d{3}?$|^\d{5}-?\d{3}?$/.test(a)},"Informe um CEP válido."),a.validator.addMethod("postalcodeIT",function(a,b){return this.optional(b)||/^\d{5}$/.test(a)},"Please specify a valid postal code"),a.validator.addMethod("postalcodeNL",function(a,b){return this.optional(b)||/^[1-9][0-9]{3}\s?[a-zA-Z]{2}$/.test(a)},"Please specify a valid postal code"),a.validator.addMethod("postcodeUK",function(a,b){return this.optional(b)||/^((([A-PR-UWYZ][0-9])|([A-PR-UWYZ][0-9][0-9])|([A-PR-UWYZ][A-HK-Y][0-9])|([A-PR-UWYZ][A-HK-Y][0-9][0-9])|([A-PR-UWYZ][0-9][A-HJKSTUW])|([A-PR-UWYZ][A-HK-Y][0-9][ABEHMNPRVWXY]))\s?([0-9][ABD-HJLNP-UW-Z]{2})|(GIR)\s?(0AA))$/i.test(a)},"Please specify a valid UK postcode"),a.validator.addMethod("require_from_group",function(b,c,d){var e=a(d[1],c.form),f=e.eq(0),g=f.data("valid_req_grp")?f.data("valid_req_grp"):a.extend({},this),h=e.filter(function(){return g.elementValue(this)}).length>=d[0];return f.data("valid_req_grp",g),a(c).data("being_validated")||(e.data("being_validated",!0),e.each(function(){g.element(this)}),e.data("being_validated",!1)),h},a.validator.format("Please fill at least {0} of these fields.")),a.validator.addMethod("skip_or_fill_minimum",function(b,c,d){var e=a(d[1],c.form),f=e.eq(0),g=f.data("valid_skip")?f.data("valid_skip"):a.extend({},this),h=e.filter(function(){return g.elementValue(this)}).length,i=0===h||h>=d[0];return f.data("valid_skip",g),a(c).data("being_validated")||(e.data("being_validated",!0),e.each(function(){g.element(this)}),e.data("being_validated",!1)),i},a.validator.format("Please either skip these fields or fill at least {0} of them.")),a.validator.addMethod("stateUS",function(a,b,c){var d,e="undefined"==typeof c,f=e||"undefined"==typeof c.caseSensitive?!1:c.caseSensitive,g=e||"undefined"==typeof c.includeTerritories?!1:c.includeTerritories,h=e||"undefined"==typeof c.includeMilitary?!1:c.includeMilitary;return d=g||h?g&&h?"^(A[AEKLPRSZ]|C[AOT]|D[CE]|FL|G[AU]|HI|I[ADLN]|K[SY]|LA|M[ADEINOPST]|N[CDEHJMVY]|O[HKR]|P[AR]|RI|S[CD]|T[NX]|UT|V[AIT]|W[AIVY])$":g?"^(A[KLRSZ]|C[AOT]|D[CE]|FL|G[AU]|HI|I[ADLN]|K[SY]|LA|M[ADEINOPST]|N[CDEHJMVY]|O[HKR]|P[AR]|RI|S[CD]|T[NX]|UT|V[AIT]|W[AIVY])$":"^(A[AEKLPRZ]|C[AOT]|D[CE]|FL|GA|HI|I[ADLN]|K[SY]|LA|M[ADEINOST]|N[CDEHJMVY]|O[HKR]|PA|RI|S[CD]|T[NX]|UT|V[AT]|W[AIVY])$":"^(A[KLRZ]|C[AOT]|D[CE]|FL|GA|HI|I[ADLN]|K[SY]|LA|M[ADEINOST]|N[CDEHJMVY]|O[HKR]|PA|RI|S[CD]|T[NX]|UT|V[AT]|W[AIVY])$",d=f?new RegExp(d):new RegExp(d,"i"),this.optional(b)||d.test(a)},"Please specify a valid state"),a.validator.addMethod("strippedminlength",function(b,c,d){return a(b).text().length>=d},a.validator.format("Please enter at least {0} characters")),a.validator.addMethod("time",function(a,b){return this.optional(b)||/^([01]\d|2[0-3]|[0-9])(:[0-5]\d){1,2}$/.test(a)},"Please enter a valid time, between 00:00 and 23:59"),a.validator.addMethod("time12h",function(a,b){return this.optional(b)||/^((0?[1-9]|1[012])(:[0-5]\d){1,2}(\ ?[AP]M))$/i.test(a)},"Please enter a valid time in 12-hour am/pm format"),a.validator.addMethod("url2",function(a,b){return this.optional(b)||/^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)*(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test(a)},a.validator.messages.url),a.validator.addMethod("vinUS",function(a){if(17!==a.length)return!1;var b,c,d,e,f,g,h=["A","B","C","D","E","F","G","H","J","K","L","M","N","P","R","S","T","U","V","W","X","Y","Z"],i=[1,2,3,4,5,6,7,8,1,2,3,4,5,7,9,2,3,4,5,6,7,8,9],j=[8,7,6,5,4,3,2,10,0,9,8,7,6,5,4,3,2],k=0;for(b=0;17>b;b++){if(e=j[b],d=a.slice(b,b+1),8===b&&(g=d),isNaN(d)){for(c=0;c _userManager;
21 | private readonly SignInManager _signInManager;
22 | private readonly string _externalCookieScheme;
23 | private readonly IEmailSender _emailSender;
24 | private readonly ISmsSender _smsSender;
25 | private readonly ILogger _logger;
26 |
27 | public ManageController(
28 | UserManager userManager,
29 | SignInManager signInManager,
30 | IOptions identityCookieOptions,
31 | IEmailSender emailSender,
32 | ISmsSender smsSender,
33 | ILoggerFactory loggerFactory)
34 | {
35 | _userManager = userManager;
36 | _signInManager = signInManager;
37 | _externalCookieScheme = identityCookieOptions.Value.ExternalCookieAuthenticationScheme;
38 | _emailSender = emailSender;
39 | _smsSender = smsSender;
40 | _logger = loggerFactory.CreateLogger();
41 | }
42 |
43 | //
44 | // GET: /Manage/Index
45 | [HttpGet]
46 | public async Task Index(ManageMessageId? message = null)
47 | {
48 | ViewData["StatusMessage"] =
49 | message == ManageMessageId.ChangePasswordSuccess ? "Your password has been changed."
50 | : message == ManageMessageId.SetPasswordSuccess ? "Your password has been set."
51 | : message == ManageMessageId.SetTwoFactorSuccess ? "Your two-factor authentication provider has been set."
52 | : message == ManageMessageId.Error ? "An error has occurred."
53 | : message == ManageMessageId.AddPhoneSuccess ? "Your phone number was added."
54 | : message == ManageMessageId.RemovePhoneSuccess ? "Your phone number was removed."
55 | : "";
56 |
57 | var user = await GetCurrentUserAsync();
58 | if (user == null)
59 | {
60 | return View("Error");
61 | }
62 | var model = new IndexViewModel
63 | {
64 | TwoFactorAuthenticatorQrCode = TempData["AuthenticatorQr"]?.ToString(),
65 | HasPassword = await _userManager.HasPasswordAsync(user),
66 | PhoneNumber = await _userManager.GetPhoneNumberAsync(user),
67 | TwoFactor = await _userManager.GetTwoFactorEnabledAsync(user),
68 | Logins = await _userManager.GetLoginsAsync(user),
69 | BrowserRemembered = await _signInManager.IsTwoFactorClientRememberedAsync(user)
70 | };
71 | return View(model);
72 | }
73 |
74 | //
75 | // POST: /Manage/RemoveLogin
76 | [HttpPost]
77 | [ValidateAntiForgeryToken]
78 | public async Task RemoveLogin(RemoveLoginViewModel account)
79 | {
80 | ManageMessageId? message = ManageMessageId.Error;
81 | var user = await GetCurrentUserAsync();
82 | if (user != null)
83 | {
84 | var result = await _userManager.RemoveLoginAsync(user, account.LoginProvider, account.ProviderKey);
85 | if (result.Succeeded)
86 | {
87 | await _signInManager.SignInAsync(user, isPersistent: false);
88 | message = ManageMessageId.RemoveLoginSuccess;
89 | }
90 | }
91 | return RedirectToAction(nameof(ManageLogins), new { Message = message });
92 | }
93 |
94 | //
95 | // GET: /Manage/AddPhoneNumber
96 | public IActionResult AddPhoneNumber()
97 | {
98 | return View();
99 | }
100 |
101 | //
102 | // POST: /Manage/AddPhoneNumber
103 | [HttpPost]
104 | [ValidateAntiForgeryToken]
105 | public async Task AddPhoneNumber(AddPhoneNumberViewModel model)
106 | {
107 | if (!ModelState.IsValid)
108 | {
109 | return View(model);
110 | }
111 | // Generate the token and send it
112 | var user = await GetCurrentUserAsync();
113 | if (user == null)
114 | {
115 | return View("Error");
116 | }
117 | var code = await _userManager.GenerateChangePhoneNumberTokenAsync(user, model.PhoneNumber);
118 | await _smsSender.SendSmsAsync(model.PhoneNumber, "Your security code is: " + code);
119 | return RedirectToAction(nameof(VerifyPhoneNumber), new { PhoneNumber = model.PhoneNumber });
120 | }
121 |
122 | //
123 | // POST: /Manage/RequestTwoFactorAuthentication
124 | [HttpPost]
125 | [ValidateAntiForgeryToken]
126 | public async Task RequestTwoFactorAuthentication()
127 | {
128 | var user = await GetCurrentUserAsync();
129 | if (user != null)
130 | {
131 | var tfaKey = Guid.NewGuid().ToString("N");
132 | user.TfaKey = tfaKey;
133 | await _userManager.UpdateAsync(user);
134 | var authenticator = new TwoFactorAuthenticator();
135 | var code = authenticator.GenerateSetupCode(user.UserName, tfaKey, 300, 300);
136 | TempData["AuthenticatorQr"] = code.QrCodeSetupImageUrl;
137 | _logger.LogInformation(1, "User enabled two-factor authentication.");
138 | }
139 | return RedirectToAction(nameof(Index), "Manage");
140 | }
141 |
142 | //
143 | // POST: /Manage/EnableTwoFactorAuthentication
144 | [HttpPost]
145 | [ValidateAntiForgeryToken]
146 | public async Task EnableTwoFactorAuthentication()
147 | {
148 | var user = await GetCurrentUserAsync();
149 | if (user != null)
150 | {
151 | await _userManager.SetTwoFactorEnabledAsync(user, true);
152 | await _signInManager.SignInAsync(user, isPersistent: false);
153 | _logger.LogInformation(1, "User enabled two-factor authentication.");
154 | }
155 | return RedirectToAction(nameof(Index), "Manage");
156 | }
157 |
158 | //
159 | // POST: /Manage/DisableTwoFactorAuthentication
160 | [HttpPost]
161 | [ValidateAntiForgeryToken]
162 | public async Task DisableTwoFactorAuthentication()
163 | {
164 | var user = await GetCurrentUserAsync();
165 | if (user != null)
166 | {
167 | await _userManager.SetTwoFactorEnabledAsync(user, false);
168 | user.TfaKey = null;
169 | await _userManager.UpdateAsync(user);
170 | await _signInManager.SignInAsync(user, isPersistent: false);
171 | _logger.LogInformation(2, "User disabled two-factor authentication.");
172 | }
173 | return RedirectToAction(nameof(Index), "Manage");
174 | }
175 |
176 | //
177 | // GET: /Manage/VerifyPhoneNumber
178 | [HttpGet]
179 | public async Task VerifyPhoneNumber(string phoneNumber)
180 | {
181 | var user = await GetCurrentUserAsync();
182 | if (user == null)
183 | {
184 | return View("Error");
185 | }
186 | var code = await _userManager.GenerateChangePhoneNumberTokenAsync(user, phoneNumber);
187 | // Send an SMS to verify the phone number
188 | return phoneNumber == null ? View("Error") : View(new VerifyPhoneNumberViewModel { PhoneNumber = phoneNumber });
189 | }
190 |
191 | //
192 | // POST: /Manage/VerifyPhoneNumber
193 | [HttpPost]
194 | [ValidateAntiForgeryToken]
195 | public async Task VerifyPhoneNumber(VerifyPhoneNumberViewModel model)
196 | {
197 | if (!ModelState.IsValid)
198 | {
199 | return View(model);
200 | }
201 | var user = await GetCurrentUserAsync();
202 | if (user != null)
203 | {
204 | var result = await _userManager.ChangePhoneNumberAsync(user, model.PhoneNumber, model.Code);
205 | if (result.Succeeded)
206 | {
207 | await _signInManager.SignInAsync(user, isPersistent: false);
208 | return RedirectToAction(nameof(Index), new { Message = ManageMessageId.AddPhoneSuccess });
209 | }
210 | }
211 | // If we got this far, something failed, redisplay the form
212 | ModelState.AddModelError(string.Empty, "Failed to verify phone number");
213 | return View(model);
214 | }
215 |
216 | //
217 | // POST: /Manage/RemovePhoneNumber
218 | [HttpPost]
219 | [ValidateAntiForgeryToken]
220 | public async Task RemovePhoneNumber()
221 | {
222 | var user = await GetCurrentUserAsync();
223 | if (user != null)
224 | {
225 | var result = await _userManager.SetPhoneNumberAsync(user, null);
226 | if (result.Succeeded)
227 | {
228 | await _signInManager.SignInAsync(user, isPersistent: false);
229 | return RedirectToAction(nameof(Index), new { Message = ManageMessageId.RemovePhoneSuccess });
230 | }
231 | }
232 | return RedirectToAction(nameof(Index), new { Message = ManageMessageId.Error });
233 | }
234 |
235 | //
236 | // GET: /Manage/ChangePassword
237 | [HttpGet]
238 | public IActionResult ChangePassword()
239 | {
240 | return View();
241 | }
242 |
243 | //
244 | // POST: /Manage/ChangePassword
245 | [HttpPost]
246 | [ValidateAntiForgeryToken]
247 | public async Task ChangePassword(ChangePasswordViewModel model)
248 | {
249 | if (!ModelState.IsValid)
250 | {
251 | return View(model);
252 | }
253 | var user = await GetCurrentUserAsync();
254 | if (user != null)
255 | {
256 | var result = await _userManager.ChangePasswordAsync(user, model.OldPassword, model.NewPassword);
257 | if (result.Succeeded)
258 | {
259 | await _signInManager.SignInAsync(user, isPersistent: false);
260 | _logger.LogInformation(3, "User changed their password successfully.");
261 | return RedirectToAction(nameof(Index), new { Message = ManageMessageId.ChangePasswordSuccess });
262 | }
263 | AddErrors(result);
264 | return View(model);
265 | }
266 | return RedirectToAction(nameof(Index), new { Message = ManageMessageId.Error });
267 | }
268 |
269 | //
270 | // GET: /Manage/SetPassword
271 | [HttpGet]
272 | public IActionResult SetPassword()
273 | {
274 | return View();
275 | }
276 |
277 | //
278 | // POST: /Manage/SetPassword
279 | [HttpPost]
280 | [ValidateAntiForgeryToken]
281 | public async Task SetPassword(SetPasswordViewModel model)
282 | {
283 | if (!ModelState.IsValid)
284 | {
285 | return View(model);
286 | }
287 |
288 | var user = await GetCurrentUserAsync();
289 | if (user != null)
290 | {
291 | var result = await _userManager.AddPasswordAsync(user, model.NewPassword);
292 | if (result.Succeeded)
293 | {
294 | await _signInManager.SignInAsync(user, isPersistent: false);
295 | return RedirectToAction(nameof(Index), new { Message = ManageMessageId.SetPasswordSuccess });
296 | }
297 | AddErrors(result);
298 | return View(model);
299 | }
300 | return RedirectToAction(nameof(Index), new { Message = ManageMessageId.Error });
301 | }
302 |
303 | //GET: /Manage/ManageLogins
304 | [HttpGet]
305 | public async Task ManageLogins(ManageMessageId? message = null)
306 | {
307 | ViewData["StatusMessage"] =
308 | message == ManageMessageId.RemoveLoginSuccess ? "The external login was removed."
309 | : message == ManageMessageId.AddLoginSuccess ? "The external login was added."
310 | : message == ManageMessageId.Error ? "An error has occurred."
311 | : "";
312 | var user = await GetCurrentUserAsync();
313 | if (user == null)
314 | {
315 | return View("Error");
316 | }
317 | var userLogins = await _userManager.GetLoginsAsync(user);
318 | var otherLogins = _signInManager.GetExternalAuthenticationSchemes().Where(auth => userLogins.All(ul => auth.AuthenticationScheme != ul.LoginProvider)).ToList();
319 | ViewData["ShowRemoveButton"] = user.PasswordHash != null || userLogins.Count > 1;
320 | return View(new ManageLoginsViewModel
321 | {
322 | CurrentLogins = userLogins,
323 | OtherLogins = otherLogins
324 | });
325 | }
326 |
327 | //
328 | // POST: /Manage/LinkLogin
329 | [HttpPost]
330 | [ValidateAntiForgeryToken]
331 | public async Task LinkLogin(string provider)
332 | {
333 | // Clear the existing external cookie to ensure a clean login process
334 | await HttpContext.Authentication.SignOutAsync(_externalCookieScheme);
335 |
336 | // Request a redirect to the external login provider to link a login for the current user
337 | var redirectUrl = Url.Action(nameof(LinkLoginCallback), "Manage");
338 | var properties = _signInManager.ConfigureExternalAuthenticationProperties(provider, redirectUrl, _userManager.GetUserId(User));
339 | return Challenge(properties, provider);
340 | }
341 |
342 | //
343 | // GET: /Manage/LinkLoginCallback
344 | [HttpGet]
345 | public async Task LinkLoginCallback()
346 | {
347 | var user = await GetCurrentUserAsync();
348 | if (user == null)
349 | {
350 | return View("Error");
351 | }
352 | var info = await _signInManager.GetExternalLoginInfoAsync(await _userManager.GetUserIdAsync(user));
353 | if (info == null)
354 | {
355 | return RedirectToAction(nameof(ManageLogins), new { Message = ManageMessageId.Error });
356 | }
357 | var result = await _userManager.AddLoginAsync(user, info);
358 | var message = ManageMessageId.Error;
359 | if (result.Succeeded)
360 | {
361 | message = ManageMessageId.AddLoginSuccess;
362 | // Clear the existing external cookie to ensure a clean login process
363 | await HttpContext.Authentication.SignOutAsync(_externalCookieScheme);
364 | }
365 | return RedirectToAction(nameof(ManageLogins), new { Message = message });
366 | }
367 |
368 | #region Helpers
369 |
370 | private void AddErrors(IdentityResult result)
371 | {
372 | foreach (var error in result.Errors)
373 | {
374 | ModelState.AddModelError(string.Empty, error.Description);
375 | }
376 | }
377 |
378 | public enum ManageMessageId
379 | {
380 | AddPhoneSuccess,
381 | AddLoginSuccess,
382 | ChangePasswordSuccess,
383 | SetTwoFactorSuccess,
384 | SetPasswordSuccess,
385 | RemoveLoginSuccess,
386 | RemovePhoneSuccess,
387 | Error
388 | }
389 |
390 | private Task GetCurrentUserAsync()
391 | {
392 | return _userManager.GetUserAsync(HttpContext.User);
393 | }
394 |
395 | #endregion
396 | }
397 | }
398 |
--------------------------------------------------------------------------------