609 changed files with 166857 additions and 0 deletions
@ -0,0 +1,28 @@ |
|||
using System.Threading.Tasks; |
|||
using Microsoft.AspNet.Authentication.Cookies; |
|||
using Microsoft.AspNet.Authentication.OpenIdConnect; |
|||
using Microsoft.AspNet.Http.Authentication; |
|||
using Microsoft.AspNet.Mvc; |
|||
|
|||
namespace Mvc.Client.Controllers { |
|||
public class AuthenticationController : Controller { |
|||
[HttpGet("~/signin")] |
|||
public ActionResult SignIn() { |
|||
// Instruct the OIDC client middleware to redirect the user agent to the identity provider.
|
|||
// Note: the authenticationType parameter must match the value configured in Startup.cs
|
|||
return new ChallengeResult(OpenIdConnectDefaults.AuthenticationScheme, new AuthenticationProperties { |
|||
RedirectUri = "/" |
|||
}); |
|||
} |
|||
|
|||
[HttpGet("~/signout"), HttpPost("~/signout")] |
|||
public async Task SignOut() { |
|||
// Instruct the cookies middleware to delete the local cookie created when the user agent
|
|||
// is redirected from the identity provider after a successful authorization flow.
|
|||
await HttpContext.Authentication.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme); |
|||
|
|||
// Instruct the OpenID Connect middleware to redirect the user agent to the identity provider to sign out.
|
|||
await HttpContext.Authentication.SignOutAsync(OpenIdConnectDefaults.AuthenticationScheme); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,40 @@ |
|||
using System; |
|||
using System.Net.Http; |
|||
using System.Net.Http.Headers; |
|||
using System.Threading; |
|||
using System.Threading.Tasks; |
|||
using Microsoft.AspNet.Authorization; |
|||
using Microsoft.AspNet.Mvc; |
|||
|
|||
namespace Mvc.Client.Controllers { |
|||
public class HomeController : Controller { |
|||
[HttpGet("~/")] |
|||
public ActionResult Index() { |
|||
return View("Home"); |
|||
} |
|||
|
|||
[Authorize, HttpPost("~/")] |
|||
public async Task<ActionResult> Index(CancellationToken cancellationToken) { |
|||
using (var client = new HttpClient()) { |
|||
var request = new HttpRequestMessage(HttpMethod.Get, "http://localhost:54540/api/message"); |
|||
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", AccessToken); |
|||
|
|||
var response = await client.SendAsync(request, cancellationToken); |
|||
response.EnsureSuccessStatusCode(); |
|||
|
|||
return View("Home", model: await response.Content.ReadAsStringAsync()); |
|||
} |
|||
} |
|||
|
|||
protected string AccessToken { |
|||
get { |
|||
var claim = HttpContext.User?.FindFirst("access_token"); |
|||
if (claim == null) { |
|||
throw new InvalidOperationException(); |
|||
} |
|||
|
|||
return claim.Value; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,29 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<Project ToolsVersion="__ToolsVersion__" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
|||
<PropertyGroup> |
|||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion> |
|||
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath> |
|||
</PropertyGroup> |
|||
<PropertyGroup Label="Globals"> |
|||
<ProjectGuid>96b22eb9-771a-4dca-b828-e6ea2774cf1b</ProjectGuid> |
|||
<OutputType>Web</OutputType> |
|||
</PropertyGroup> |
|||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x86'" Label="Configuration"> |
|||
</PropertyGroup> |
|||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x86'" Label="Configuration"> |
|||
</PropertyGroup> |
|||
<PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'"> |
|||
<AssemblyName>Mvc.Client</AssemblyName> |
|||
</PropertyGroup> |
|||
<PropertyGroup Label="Configuration"> |
|||
<RootNamespace>Mvc.Client</RootNamespace> |
|||
</PropertyGroup> |
|||
<PropertyGroup> |
|||
<SchemaVersion>2.0</SchemaVersion> |
|||
<DevelopmentServerPort>53507</DevelopmentServerPort> |
|||
<CommandLineArguments /> |
|||
<DebugTarget>web</DebugTarget> |
|||
</PropertyGroup> |
|||
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.Props" /> |
|||
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.targets" /> |
|||
</Project> |
|||
@ -0,0 +1,71 @@ |
|||
using System; |
|||
using Microsoft.AspNet.Authentication; |
|||
using Microsoft.AspNet.Authentication.Cookies; |
|||
using Microsoft.AspNet.Builder; |
|||
using Microsoft.AspNet.Http; |
|||
using Microsoft.Dnx.Runtime; |
|||
using Microsoft.Framework.DependencyInjection; |
|||
using Microsoft.Framework.Logging; |
|||
using Microsoft.IdentityModel.Protocols; |
|||
using Microsoft.IdentityModel.Protocols.OpenIdConnect; |
|||
|
|||
namespace Mvc.Client { |
|||
public class Startup { |
|||
public void ConfigureServices(IServiceCollection services) { |
|||
services.Configure<SharedAuthenticationOptions>(options => { |
|||
options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme; |
|||
}); |
|||
|
|||
services.AddAuthentication(); |
|||
services.AddMvc(); |
|||
} |
|||
|
|||
public void Configure(IApplicationBuilder app, IRuntimeEnvironment environment) { |
|||
var factory = app.ApplicationServices.GetRequiredService<ILoggerFactory>(); |
|||
factory.AddConsole(); |
|||
|
|||
// Insert a new cookies middleware in the pipeline to store the user
|
|||
// identity after he has been redirected from the identity provider.
|
|||
app.UseCookieAuthentication(options => { |
|||
options.AutomaticAuthentication = true; |
|||
options.LoginPath = new PathString("/signin"); |
|||
}); |
|||
|
|||
app.UseOpenIdConnectAuthentication(options => { |
|||
// Note: these settings must match the application details
|
|||
// inserted in the database at the server level.
|
|||
options.ClientId = "myClient"; |
|||
options.ClientSecret = "secret_secret_secret"; |
|||
options.RedirectUri = "http://localhost:53507/oidc"; |
|||
options.PostLogoutRedirectUri = "http://localhost:53507/"; |
|||
|
|||
// Use the authorization code flow.
|
|||
options.ResponseType = OpenIdConnectResponseTypes.Code; |
|||
|
|||
// Note: setting the Authority allows the OIDC client middleware to automatically
|
|||
// retrieve the identity provider's configuration and spare you from setting
|
|||
// the different endpoints URIs or the token validation parameters explicitly.
|
|||
options.Authority = "http://localhost:54540/"; |
|||
|
|||
// Note: the resource property represents the different endpoints the
|
|||
// access token should be issued for (values must be space-delimited).
|
|||
options.Resource = "http://localhost:54540/"; |
|||
|
|||
options.Scope.Add("email"); |
|||
options.Scope.Add("profile"); |
|||
|
|||
// Note: by default, IdentityModel beta8 now refuses to initiate non-HTTPS calls.
|
|||
// To work around this limitation, the configuration manager is manually
|
|||
// instantiated with a document retriever allowing HTTP calls.
|
|||
options.ConfigurationManager = new ConfigurationManager<OpenIdConnectConfiguration>( |
|||
metadataAddress: options.Authority + ".well-known/openid-configuration", |
|||
configRetriever: new OpenIdConnectConfigurationRetriever(), |
|||
docRetriever: new HttpDocumentRetriever { RequireHttps = false }); |
|||
}); |
|||
|
|||
app.UseStaticFiles(); |
|||
|
|||
app.UseMvc(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,28 @@ |
|||
@model string |
|||
|
|||
<div class="jumbotron"> |
|||
@if (User?.Identity?.IsAuthenticated ?? false) { |
|||
<h1>Welcome, @User.Identity.Name</h1> |
|||
|
|||
<p> |
|||
@foreach (var claim in Context.User.Claims) { |
|||
<div>@claim.Type: <b>@claim.Value</b></div> |
|||
} |
|||
</p> |
|||
|
|||
if (!string.IsNullOrEmpty(Model)) { |
|||
<h3>Message received from the resource controller: @Model</h3> |
|||
} |
|||
|
|||
<form action="~/" method="post"> |
|||
<button class="btn btn-lg btn-warning" type="submit">Query the resource controller</button> |
|||
</form> |
|||
|
|||
<a class="btn btn-lg btn-danger" href="/signout">Sign out</a> |
|||
} |
|||
|
|||
else { |
|||
<h1>Welcome, anonymous</h1> |
|||
<a class="btn btn-lg btn-success" href="/signin">Sign in</a> |
|||
} |
|||
</div> |
|||
@ -0,0 +1,30 @@ |
|||
<!DOCTYPE html> |
|||
<html lang="en"> |
|||
<head> |
|||
<meta charset="utf-8" /> |
|||
<meta http-equiv="X-UA-Compatible" content="IE=edge" /> |
|||
<meta name="viewport" content="width=device-width, initial-scale=1" /> |
|||
<meta name="description" content="" /> |
|||
<meta name="author" content="" /> |
|||
|
|||
<title>Mvc.Client (OSOS sample)</title> |
|||
|
|||
<link href="~/stylesheets/bootstrap.min.css" rel="stylesheet" /> |
|||
<link href="~/stylesheets/jumbotron-narrow.css" rel="stylesheet" /> |
|||
</head> |
|||
|
|||
<body> |
|||
<div class="container"> |
|||
<div class="header"> |
|||
<h3 class="text-muted">Your application (Mvc.Client)</h3> |
|||
</div> |
|||
|
|||
@RenderBody() |
|||
|
|||
<div class="footer"> |
|||
<p>© Your company 2014</p> |
|||
</div> |
|||
|
|||
</div> |
|||
</body> |
|||
</html> |
|||
@ -0,0 +1,3 @@ |
|||
@{ |
|||
Layout = "_Layout"; |
|||
} |
|||
@ -0,0 +1,30 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
|
|||
<!-- For more information on using web.config transformation visit http://go.microsoft.com/fwlink/?LinkId=125889 --> |
|||
|
|||
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform"> |
|||
<!-- |
|||
In the example below, the "SetAttributes" transform will change the value of |
|||
"connectionString" to use "ReleaseSQLServer" only when the "Match" locator |
|||
finds an attribute "name" that has a value of "MyDB". |
|||
|
|||
<connectionStrings> |
|||
<add name="MyDB" |
|||
connectionString="Data Source=ReleaseSQLServer;Initial Catalog=MyReleaseDB;Integrated Security=True" |
|||
xdt:Transform="SetAttributes" xdt:Locator="Match(name)"/> |
|||
</connectionStrings> |
|||
--> |
|||
<system.web> |
|||
<!-- |
|||
In the example below, the "Replace" transform will replace the entire |
|||
<customErrors> section of your web.config file. |
|||
Note that because there is only one customErrors section under the |
|||
<system.web> node, there is no need to use the "xdt:Locator" attribute. |
|||
|
|||
<customErrors defaultRedirect="GenericError.htm" |
|||
mode="RemoteOnly" xdt:Transform="Replace"> |
|||
<error statusCode="500" redirect="InternalError.htm"/> |
|||
</customErrors> |
|||
--> |
|||
</system.web> |
|||
</configuration> |
|||
@ -0,0 +1,31 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
|
|||
<!-- For more information on using web.config transformation visit http://go.microsoft.com/fwlink/?LinkId=125889 --> |
|||
|
|||
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform"> |
|||
<!-- |
|||
In the example below, the "SetAttributes" transform will change the value of |
|||
"connectionString" to use "ReleaseSQLServer" only when the "Match" locator |
|||
finds an attribute "name" that has a value of "MyDB". |
|||
|
|||
<connectionStrings> |
|||
<add name="MyDB" |
|||
connectionString="Data Source=ReleaseSQLServer;Initial Catalog=MyReleaseDB;Integrated Security=True" |
|||
xdt:Transform="SetAttributes" xdt:Locator="Match(name)"/> |
|||
</connectionStrings> |
|||
--> |
|||
<system.web> |
|||
<compilation xdt:Transform="RemoveAttributes(debug)" /> |
|||
<!-- |
|||
In the example below, the "Replace" transform will replace the entire |
|||
<customErrors> section of your web.config file. |
|||
Note that because there is only one customErrors section under the |
|||
<system.web> node, there is no need to use the "xdt:Locator" attribute. |
|||
|
|||
<customErrors defaultRedirect="GenericError.htm" |
|||
mode="RemoteOnly" xdt:Transform="Replace"> |
|||
<error statusCode="500" redirect="InternalError.htm"/> |
|||
</customErrors> |
|||
--> |
|||
</system.web> |
|||
</configuration> |
|||
@ -0,0 +1,10 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<!-- |
|||
For more information on how to configure your ASP.NET application, please visit |
|||
http://go.microsoft.com/fwlink/?LinkId=169433 |
|||
--> |
|||
<configuration> |
|||
<system.webServer> |
|||
<modules runAllManagedModulesForAllRequests="true"/> |
|||
</system.webServer> |
|||
</configuration> |
|||
@ -0,0 +1,40 @@ |
|||
{ |
|||
"webroot": "wwwroot", |
|||
"exclude": "wwwroot/**/*.*", |
|||
|
|||
"version": "1.0.0-beta2-*", |
|||
|
|||
"dependencies": { |
|||
"Microsoft.AspNet.Mvc": "6.0.0-*", |
|||
"Microsoft.AspNet.Authentication.Cookies": "1.0.0-*", |
|||
"Microsoft.AspNet.Authentication.OpenIdConnect": "1.0.0-*", |
|||
"Microsoft.AspNet.Server.IIS": "1.0.0-*", |
|||
"Microsoft.AspNet.Server.Kestrel": "1.0.0-*", |
|||
"Microsoft.AspNet.Server.WebListener": "1.0.0-*", |
|||
"Microsoft.AspNet.StaticFiles": "1.0.0-*", |
|||
|
|||
"Microsoft.Framework.Logging.Console": "1.0.0-*", |
|||
|
|||
"Newtonsoft.Json": "7.0.1" |
|||
}, |
|||
|
|||
"commands": { |
|||
"kestrel": "Microsoft.AspNet.Hosting --server=Microsoft.AspNet.Server.Kestrel --server.urls=http://localhost:53507", |
|||
"web": "Microsoft.AspNet.Hosting server=Microsoft.AspNet.Server.WebListener server.urls=http://localhost:53507" |
|||
}, |
|||
|
|||
"frameworks": { |
|||
"dnx451": { |
|||
"frameworkAssemblies": { |
|||
"System.Net.Http": "4.0.0.0" |
|||
} |
|||
}, |
|||
|
|||
"dnxcore50": { |
|||
"dependencies": { |
|||
"System.Net.Http": "4.0.1-*", |
|||
"System.Runtime.Serialization.Primitives": "4.0.11-*" |
|||
} |
|||
} |
|||
} |
|||
} |
|||
Binary file not shown.
|
After Width: | Height: | Size: 62 KiB |
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
File diff suppressed because it is too large
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -0,0 +1,442 @@ |
|||
/*! |
|||
* Bootstrap v3.2.0 (http://getbootstrap.com) |
|||
* Copyright 2011-2014 Twitter, Inc. |
|||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) |
|||
*/ |
|||
|
|||
.btn-default, |
|||
.btn-primary, |
|||
.btn-success, |
|||
.btn-info, |
|||
.btn-warning, |
|||
.btn-danger { |
|||
text-shadow: 0 -1px 0 rgba(0, 0, 0, .2); |
|||
-webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075); |
|||
box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075); |
|||
} |
|||
.btn-default:active, |
|||
.btn-primary:active, |
|||
.btn-success:active, |
|||
.btn-info:active, |
|||
.btn-warning:active, |
|||
.btn-danger:active, |
|||
.btn-default.active, |
|||
.btn-primary.active, |
|||
.btn-success.active, |
|||
.btn-info.active, |
|||
.btn-warning.active, |
|||
.btn-danger.active { |
|||
-webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); |
|||
box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); |
|||
} |
|||
.btn:active, |
|||
.btn.active { |
|||
background-image: none; |
|||
} |
|||
.btn-default { |
|||
text-shadow: 0 1px 0 #fff; |
|||
background-image: -webkit-linear-gradient(top, #fff 0%, #e0e0e0 100%); |
|||
background-image: -o-linear-gradient(top, #fff 0%, #e0e0e0 100%); |
|||
background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#e0e0e0)); |
|||
background-image: linear-gradient(to bottom, #fff 0%, #e0e0e0 100%); |
|||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0); |
|||
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); |
|||
background-repeat: repeat-x; |
|||
border-color: #dbdbdb; |
|||
border-color: #ccc; |
|||
} |
|||
.btn-default:hover, |
|||
.btn-default:focus { |
|||
background-color: #e0e0e0; |
|||
background-position: 0 -15px; |
|||
} |
|||
.btn-default:active, |
|||
.btn-default.active { |
|||
background-color: #e0e0e0; |
|||
border-color: #dbdbdb; |
|||
} |
|||
.btn-default:disabled, |
|||
.btn-default[disabled] { |
|||
background-color: #e0e0e0; |
|||
background-image: none; |
|||
} |
|||
.btn-primary { |
|||
background-image: -webkit-linear-gradient(top, #428bca 0%, #2d6ca2 100%); |
|||
background-image: -o-linear-gradient(top, #428bca 0%, #2d6ca2 100%); |
|||
background-image: -webkit-gradient(linear, left top, left bottom, from(#428bca), to(#2d6ca2)); |
|||
background-image: linear-gradient(to bottom, #428bca 0%, #2d6ca2 100%); |
|||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff2d6ca2', GradientType=0); |
|||
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); |
|||
background-repeat: repeat-x; |
|||
border-color: #2b669a; |
|||
} |
|||
.btn-primary:hover, |
|||
.btn-primary:focus { |
|||
background-color: #2d6ca2; |
|||
background-position: 0 -15px; |
|||
} |
|||
.btn-primary:active, |
|||
.btn-primary.active { |
|||
background-color: #2d6ca2; |
|||
border-color: #2b669a; |
|||
} |
|||
.btn-primary:disabled, |
|||
.btn-primary[disabled] { |
|||
background-color: #2d6ca2; |
|||
background-image: none; |
|||
} |
|||
.btn-success { |
|||
background-image: -webkit-linear-gradient(top, #5cb85c 0%, #419641 100%); |
|||
background-image: -o-linear-gradient(top, #5cb85c 0%, #419641 100%); |
|||
background-image: -webkit-gradient(linear, left top, left bottom, from(#5cb85c), to(#419641)); |
|||
background-image: linear-gradient(to bottom, #5cb85c 0%, #419641 100%); |
|||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0); |
|||
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); |
|||
background-repeat: repeat-x; |
|||
border-color: #3e8f3e; |
|||
} |
|||
.btn-success:hover, |
|||
.btn-success:focus { |
|||
background-color: #419641; |
|||
background-position: 0 -15px; |
|||
} |
|||
.btn-success:active, |
|||
.btn-success.active { |
|||
background-color: #419641; |
|||
border-color: #3e8f3e; |
|||
} |
|||
.btn-success:disabled, |
|||
.btn-success[disabled] { |
|||
background-color: #419641; |
|||
background-image: none; |
|||
} |
|||
.btn-info { |
|||
background-image: -webkit-linear-gradient(top, #5bc0de 0%, #2aabd2 100%); |
|||
background-image: -o-linear-gradient(top, #5bc0de 0%, #2aabd2 100%); |
|||
background-image: -webkit-gradient(linear, left top, left bottom, from(#5bc0de), to(#2aabd2)); |
|||
background-image: linear-gradient(to bottom, #5bc0de 0%, #2aabd2 100%); |
|||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0); |
|||
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); |
|||
background-repeat: repeat-x; |
|||
border-color: #28a4c9; |
|||
} |
|||
.btn-info:hover, |
|||
.btn-info:focus { |
|||
background-color: #2aabd2; |
|||
background-position: 0 -15px; |
|||
} |
|||
.btn-info:active, |
|||
.btn-info.active { |
|||
background-color: #2aabd2; |
|||
border-color: #28a4c9; |
|||
} |
|||
.btn-info:disabled, |
|||
.btn-info[disabled] { |
|||
background-color: #2aabd2; |
|||
background-image: none; |
|||
} |
|||
.btn-warning { |
|||
background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #eb9316 100%); |
|||
background-image: -o-linear-gradient(top, #f0ad4e 0%, #eb9316 100%); |
|||
background-image: -webkit-gradient(linear, left top, left bottom, from(#f0ad4e), to(#eb9316)); |
|||
background-image: linear-gradient(to bottom, #f0ad4e 0%, #eb9316 100%); |
|||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0); |
|||
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); |
|||
background-repeat: repeat-x; |
|||
border-color: #e38d13; |
|||
} |
|||
.btn-warning:hover, |
|||
.btn-warning:focus { |
|||
background-color: #eb9316; |
|||
background-position: 0 -15px; |
|||
} |
|||
.btn-warning:active, |
|||
.btn-warning.active { |
|||
background-color: #eb9316; |
|||
border-color: #e38d13; |
|||
} |
|||
.btn-warning:disabled, |
|||
.btn-warning[disabled] { |
|||
background-color: #eb9316; |
|||
background-image: none; |
|||
} |
|||
.btn-danger { |
|||
background-image: -webkit-linear-gradient(top, #d9534f 0%, #c12e2a 100%); |
|||
background-image: -o-linear-gradient(top, #d9534f 0%, #c12e2a 100%); |
|||
background-image: -webkit-gradient(linear, left top, left bottom, from(#d9534f), to(#c12e2a)); |
|||
background-image: linear-gradient(to bottom, #d9534f 0%, #c12e2a 100%); |
|||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0); |
|||
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); |
|||
background-repeat: repeat-x; |
|||
border-color: #b92c28; |
|||
} |
|||
.btn-danger:hover, |
|||
.btn-danger:focus { |
|||
background-color: #c12e2a; |
|||
background-position: 0 -15px; |
|||
} |
|||
.btn-danger:active, |
|||
.btn-danger.active { |
|||
background-color: #c12e2a; |
|||
border-color: #b92c28; |
|||
} |
|||
.btn-danger:disabled, |
|||
.btn-danger[disabled] { |
|||
background-color: #c12e2a; |
|||
background-image: none; |
|||
} |
|||
.thumbnail, |
|||
.img-thumbnail { |
|||
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .075); |
|||
box-shadow: 0 1px 2px rgba(0, 0, 0, .075); |
|||
} |
|||
.dropdown-menu > li > a:hover, |
|||
.dropdown-menu > li > a:focus { |
|||
background-color: #e8e8e8; |
|||
background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); |
|||
background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); |
|||
background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8)); |
|||
background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%); |
|||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0); |
|||
background-repeat: repeat-x; |
|||
} |
|||
.dropdown-menu > .active > a, |
|||
.dropdown-menu > .active > a:hover, |
|||
.dropdown-menu > .active > a:focus { |
|||
background-color: #357ebd; |
|||
background-image: -webkit-linear-gradient(top, #428bca 0%, #357ebd 100%); |
|||
background-image: -o-linear-gradient(top, #428bca 0%, #357ebd 100%); |
|||
background-image: -webkit-gradient(linear, left top, left bottom, from(#428bca), to(#357ebd)); |
|||
background-image: linear-gradient(to bottom, #428bca 0%, #357ebd 100%); |
|||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0); |
|||
background-repeat: repeat-x; |
|||
} |
|||
.navbar-default { |
|||
background-image: -webkit-linear-gradient(top, #fff 0%, #f8f8f8 100%); |
|||
background-image: -o-linear-gradient(top, #fff 0%, #f8f8f8 100%); |
|||
background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#f8f8f8)); |
|||
background-image: linear-gradient(to bottom, #fff 0%, #f8f8f8 100%); |
|||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0); |
|||
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); |
|||
background-repeat: repeat-x; |
|||
border-radius: 4px; |
|||
-webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 5px rgba(0, 0, 0, .075); |
|||
box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 5px rgba(0, 0, 0, .075); |
|||
} |
|||
.navbar-default .navbar-nav > .active > a { |
|||
background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f3f3f3 100%); |
|||
background-image: -o-linear-gradient(top, #ebebeb 0%, #f3f3f3 100%); |
|||
background-image: -webkit-gradient(linear, left top, left bottom, from(#ebebeb), to(#f3f3f3)); |
|||
background-image: linear-gradient(to bottom, #ebebeb 0%, #f3f3f3 100%); |
|||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff3f3f3', GradientType=0); |
|||
background-repeat: repeat-x; |
|||
-webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, .075); |
|||
box-shadow: inset 0 3px 9px rgba(0, 0, 0, .075); |
|||
} |
|||
.navbar-brand, |
|||
.navbar-nav > li > a { |
|||
text-shadow: 0 1px 0 rgba(255, 255, 255, .25); |
|||
} |
|||
.navbar-inverse { |
|||
background-image: -webkit-linear-gradient(top, #3c3c3c 0%, #222 100%); |
|||
background-image: -o-linear-gradient(top, #3c3c3c 0%, #222 100%); |
|||
background-image: -webkit-gradient(linear, left top, left bottom, from(#3c3c3c), to(#222)); |
|||
background-image: linear-gradient(to bottom, #3c3c3c 0%, #222 100%); |
|||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0); |
|||
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); |
|||
background-repeat: repeat-x; |
|||
} |
|||
.navbar-inverse .navbar-nav > .active > a { |
|||
background-image: -webkit-linear-gradient(top, #222 0%, #282828 100%); |
|||
background-image: -o-linear-gradient(top, #222 0%, #282828 100%); |
|||
background-image: -webkit-gradient(linear, left top, left bottom, from(#222), to(#282828)); |
|||
background-image: linear-gradient(to bottom, #222 0%, #282828 100%); |
|||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff282828', GradientType=0); |
|||
background-repeat: repeat-x; |
|||
-webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, .25); |
|||
box-shadow: inset 0 3px 9px rgba(0, 0, 0, .25); |
|||
} |
|||
.navbar-inverse .navbar-brand, |
|||
.navbar-inverse .navbar-nav > li > a { |
|||
text-shadow: 0 -1px 0 rgba(0, 0, 0, .25); |
|||
} |
|||
.navbar-static-top, |
|||
.navbar-fixed-top, |
|||
.navbar-fixed-bottom { |
|||
border-radius: 0; |
|||
} |
|||
.alert { |
|||
text-shadow: 0 1px 0 rgba(255, 255, 255, .2); |
|||
-webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 1px 2px rgba(0, 0, 0, .05); |
|||
box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 1px 2px rgba(0, 0, 0, .05); |
|||
} |
|||
.alert-success { |
|||
background-image: -webkit-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%); |
|||
background-image: -o-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%); |
|||
background-image: -webkit-gradient(linear, left top, left bottom, from(#dff0d8), to(#c8e5bc)); |
|||
background-image: linear-gradient(to bottom, #dff0d8 0%, #c8e5bc 100%); |
|||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0); |
|||
background-repeat: repeat-x; |
|||
border-color: #b2dba1; |
|||
} |
|||
.alert-info { |
|||
background-image: -webkit-linear-gradient(top, #d9edf7 0%, #b9def0 100%); |
|||
background-image: -o-linear-gradient(top, #d9edf7 0%, #b9def0 100%); |
|||
background-image: -webkit-gradient(linear, left top, left bottom, from(#d9edf7), to(#b9def0)); |
|||
background-image: linear-gradient(to bottom, #d9edf7 0%, #b9def0 100%); |
|||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0); |
|||
background-repeat: repeat-x; |
|||
border-color: #9acfea; |
|||
} |
|||
.alert-warning { |
|||
background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%); |
|||
background-image: -o-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%); |
|||
background-image: -webkit-gradient(linear, left top, left bottom, from(#fcf8e3), to(#f8efc0)); |
|||
background-image: linear-gradient(to bottom, #fcf8e3 0%, #f8efc0 100%); |
|||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0); |
|||
background-repeat: repeat-x; |
|||
border-color: #f5e79e; |
|||
} |
|||
.alert-danger { |
|||
background-image: -webkit-linear-gradient(top, #f2dede 0%, #e7c3c3 100%); |
|||
background-image: -o-linear-gradient(top, #f2dede 0%, #e7c3c3 100%); |
|||
background-image: -webkit-gradient(linear, left top, left bottom, from(#f2dede), to(#e7c3c3)); |
|||
background-image: linear-gradient(to bottom, #f2dede 0%, #e7c3c3 100%); |
|||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0); |
|||
background-repeat: repeat-x; |
|||
border-color: #dca7a7; |
|||
} |
|||
.progress { |
|||
background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%); |
|||
background-image: -o-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%); |
|||
background-image: -webkit-gradient(linear, left top, left bottom, from(#ebebeb), to(#f5f5f5)); |
|||
background-image: linear-gradient(to bottom, #ebebeb 0%, #f5f5f5 100%); |
|||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0); |
|||
background-repeat: repeat-x; |
|||
} |
|||
.progress-bar { |
|||
background-image: -webkit-linear-gradient(top, #428bca 0%, #3071a9 100%); |
|||
background-image: -o-linear-gradient(top, #428bca 0%, #3071a9 100%); |
|||
background-image: -webkit-gradient(linear, left top, left bottom, from(#428bca), to(#3071a9)); |
|||
background-image: linear-gradient(to bottom, #428bca 0%, #3071a9 100%); |
|||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3071a9', GradientType=0); |
|||
background-repeat: repeat-x; |
|||
} |
|||
.progress-bar-success { |
|||
background-image: -webkit-linear-gradient(top, #5cb85c 0%, #449d44 100%); |
|||
background-image: -o-linear-gradient(top, #5cb85c 0%, #449d44 100%); |
|||
background-image: -webkit-gradient(linear, left top, left bottom, from(#5cb85c), to(#449d44)); |
|||
background-image: linear-gradient(to bottom, #5cb85c 0%, #449d44 100%); |
|||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0); |
|||
background-repeat: repeat-x; |
|||
} |
|||
.progress-bar-info { |
|||
background-image: -webkit-linear-gradient(top, #5bc0de 0%, #31b0d5 100%); |
|||
background-image: -o-linear-gradient(top, #5bc0de 0%, #31b0d5 100%); |
|||
background-image: -webkit-gradient(linear, left top, left bottom, from(#5bc0de), to(#31b0d5)); |
|||
background-image: linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%); |
|||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0); |
|||
background-repeat: repeat-x; |
|||
} |
|||
.progress-bar-warning { |
|||
background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #ec971f 100%); |
|||
background-image: -o-linear-gradient(top, #f0ad4e 0%, #ec971f 100%); |
|||
background-image: -webkit-gradient(linear, left top, left bottom, from(#f0ad4e), to(#ec971f)); |
|||
background-image: linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%); |
|||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0); |
|||
background-repeat: repeat-x; |
|||
} |
|||
.progress-bar-danger { |
|||
background-image: -webkit-linear-gradient(top, #d9534f 0%, #c9302c 100%); |
|||
background-image: -o-linear-gradient(top, #d9534f 0%, #c9302c 100%); |
|||
background-image: -webkit-gradient(linear, left top, left bottom, from(#d9534f), to(#c9302c)); |
|||
background-image: linear-gradient(to bottom, #d9534f 0%, #c9302c 100%); |
|||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0); |
|||
background-repeat: repeat-x; |
|||
} |
|||
.progress-bar-striped { |
|||
background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); |
|||
background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); |
|||
background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); |
|||
} |
|||
.list-group { |
|||
border-radius: 4px; |
|||
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .075); |
|||
box-shadow: 0 1px 2px rgba(0, 0, 0, .075); |
|||
} |
|||
.list-group-item.active, |
|||
.list-group-item.active:hover, |
|||
.list-group-item.active:focus { |
|||
text-shadow: 0 -1px 0 #3071a9; |
|||
background-image: -webkit-linear-gradient(top, #428bca 0%, #3278b3 100%); |
|||
background-image: -o-linear-gradient(top, #428bca 0%, #3278b3 100%); |
|||
background-image: -webkit-gradient(linear, left top, left bottom, from(#428bca), to(#3278b3)); |
|||
background-image: linear-gradient(to bottom, #428bca 0%, #3278b3 100%); |
|||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3278b3', GradientType=0); |
|||
background-repeat: repeat-x; |
|||
border-color: #3278b3; |
|||
} |
|||
.panel { |
|||
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .05); |
|||
box-shadow: 0 1px 2px rgba(0, 0, 0, .05); |
|||
} |
|||
.panel-default > .panel-heading { |
|||
background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); |
|||
background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); |
|||
background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8)); |
|||
background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%); |
|||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0); |
|||
background-repeat: repeat-x; |
|||
} |
|||
.panel-primary > .panel-heading { |
|||
background-image: -webkit-linear-gradient(top, #428bca 0%, #357ebd 100%); |
|||
background-image: -o-linear-gradient(top, #428bca 0%, #357ebd 100%); |
|||
background-image: -webkit-gradient(linear, left top, left bottom, from(#428bca), to(#357ebd)); |
|||
background-image: linear-gradient(to bottom, #428bca 0%, #357ebd 100%); |
|||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0); |
|||
background-repeat: repeat-x; |
|||
} |
|||
.panel-success > .panel-heading { |
|||
background-image: -webkit-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%); |
|||
background-image: -o-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%); |
|||
background-image: -webkit-gradient(linear, left top, left bottom, from(#dff0d8), to(#d0e9c6)); |
|||
background-image: linear-gradient(to bottom, #dff0d8 0%, #d0e9c6 100%); |
|||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0); |
|||
background-repeat: repeat-x; |
|||
} |
|||
.panel-info > .panel-heading { |
|||
background-image: -webkit-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%); |
|||
background-image: -o-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%); |
|||
background-image: -webkit-gradient(linear, left top, left bottom, from(#d9edf7), to(#c4e3f3)); |
|||
background-image: linear-gradient(to bottom, #d9edf7 0%, #c4e3f3 100%); |
|||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0); |
|||
background-repeat: repeat-x; |
|||
} |
|||
.panel-warning > .panel-heading { |
|||
background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%); |
|||
background-image: -o-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%); |
|||
background-image: -webkit-gradient(linear, left top, left bottom, from(#fcf8e3), to(#faf2cc)); |
|||
background-image: linear-gradient(to bottom, #fcf8e3 0%, #faf2cc 100%); |
|||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0); |
|||
background-repeat: repeat-x; |
|||
} |
|||
.panel-danger > .panel-heading { |
|||
background-image: -webkit-linear-gradient(top, #f2dede 0%, #ebcccc 100%); |
|||
background-image: -o-linear-gradient(top, #f2dede 0%, #ebcccc 100%); |
|||
background-image: -webkit-gradient(linear, left top, left bottom, from(#f2dede), to(#ebcccc)); |
|||
background-image: linear-gradient(to bottom, #f2dede 0%, #ebcccc 100%); |
|||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0); |
|||
background-repeat: repeat-x; |
|||
} |
|||
.well { |
|||
background-image: -webkit-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%); |
|||
background-image: -o-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%); |
|||
background-image: -webkit-gradient(linear, left top, left bottom, from(#e8e8e8), to(#f5f5f5)); |
|||
background-image: linear-gradient(to bottom, #e8e8e8 0%, #f5f5f5 100%); |
|||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0); |
|||
background-repeat: repeat-x; |
|||
border-color: #dcdcdc; |
|||
-webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, .05), 0 1px 0 rgba(255, 255, 255, .1); |
|||
box-shadow: inset 0 1px 3px rgba(0, 0, 0, .05), 0 1px 0 rgba(255, 255, 255, .1); |
|||
} |
|||
/*# sourceMappingURL=bootstrap-theme.css.map */ |
|||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -0,0 +1,79 @@ |
|||
/* Space out content a bit */ |
|||
body { |
|||
padding-top: 20px; |
|||
padding-bottom: 20px; |
|||
} |
|||
|
|||
/* Everything but the jumbotron gets side spacing for mobile first views */ |
|||
.header, |
|||
.marketing, |
|||
.footer { |
|||
padding-right: 15px; |
|||
padding-left: 15px; |
|||
} |
|||
|
|||
/* Custom page header */ |
|||
.header { |
|||
border-bottom: 1px solid #e5e5e5; |
|||
} |
|||
/* Make the masthead heading the same height as the navigation */ |
|||
.header h3 { |
|||
padding-bottom: 19px; |
|||
margin-top: 0; |
|||
margin-bottom: 0; |
|||
line-height: 40px; |
|||
} |
|||
|
|||
/* Custom page footer */ |
|||
.footer { |
|||
padding-top: 19px; |
|||
color: #777; |
|||
border-top: 1px solid #e5e5e5; |
|||
} |
|||
|
|||
/* Customize container */ |
|||
@media (min-width: 768px) { |
|||
.container { |
|||
max-width: 730px; |
|||
} |
|||
} |
|||
.container-narrow > hr { |
|||
margin: 30px 0; |
|||
} |
|||
|
|||
/* Main marketing message and sign up button */ |
|||
.jumbotron { |
|||
text-align: center; |
|||
border-bottom: 1px solid #e5e5e5; |
|||
} |
|||
.jumbotron .btn { |
|||
padding: 14px 24px; |
|||
font-size: 21px; |
|||
} |
|||
|
|||
/* Supporting marketing content */ |
|||
.marketing { |
|||
margin: 40px 0; |
|||
} |
|||
.marketing p + h4 { |
|||
margin-top: 28px; |
|||
} |
|||
|
|||
/* Responsive: Portrait tablets and up */ |
|||
@media screen and (min-width: 768px) { |
|||
/* Remove the padding we set earlier */ |
|||
.header, |
|||
.marketing, |
|||
.footer { |
|||
padding-right: 0; |
|||
padding-left: 0; |
|||
} |
|||
/* Space out the masthead */ |
|||
.header { |
|||
margin-bottom: 30px; |
|||
} |
|||
/* Remove the bottom border on the jumbotron for visual effect */ |
|||
.jumbotron { |
|||
border-bottom: 0; |
|||
} |
|||
} |
|||
@ -0,0 +1,3 @@ |
|||
{ |
|||
"directory": "wwwroot/lib" |
|||
} |
|||
@ -0,0 +1,412 @@ |
|||
using System.Linq; |
|||
using System.Security.Claims; |
|||
using System.Threading.Tasks; |
|||
using Microsoft.AspNet.Authorization; |
|||
using Microsoft.AspNet.Identity; |
|||
using Microsoft.AspNet.Mvc; |
|||
using Microsoft.AspNet.Mvc.Rendering; |
|||
using Microsoft.Data.Entity; |
|||
using Mvc.Server.Models; |
|||
using Mvc.Server.Services; |
|||
using Mvc.Server.ViewModels.Account; |
|||
|
|||
namespace Mvc.Server.Controllers { |
|||
[Authorize] |
|||
public class AccountController : Controller { |
|||
private readonly UserManager<ApplicationUser> _userManager; |
|||
private readonly SignInManager<ApplicationUser> _signInManager; |
|||
private readonly IEmailSender _emailSender; |
|||
private readonly ISmsSender _smsSender; |
|||
private readonly ApplicationDbContext _applicationDbContext; |
|||
private static bool _databaseChecked; |
|||
|
|||
public AccountController( |
|||
UserManager<ApplicationUser> userManager, |
|||
SignInManager<ApplicationUser> signInManager, |
|||
IEmailSender emailSender, |
|||
ISmsSender smsSender, |
|||
ApplicationDbContext applicationDbContext) { |
|||
_userManager = userManager; |
|||
_signInManager = signInManager; |
|||
_emailSender = emailSender; |
|||
_smsSender = smsSender; |
|||
_applicationDbContext = applicationDbContext; |
|||
} |
|||
|
|||
//
|
|||
// GET: /Account/Login
|
|||
[HttpGet] |
|||
[AllowAnonymous] |
|||
public IActionResult Login(string returnUrl = null) { |
|||
ViewData["ReturnUrl"] = returnUrl; |
|||
return View(); |
|||
} |
|||
|
|||
//
|
|||
// POST: /Account/Login
|
|||
[HttpPost] |
|||
[AllowAnonymous] |
|||
[ValidateAntiForgeryToken] |
|||
public async Task<IActionResult> Login(LoginViewModel model, string returnUrl = null) { |
|||
EnsureDatabaseCreated(_applicationDbContext); |
|||
ViewData["ReturnUrl"] = returnUrl; |
|||
if (ModelState.IsValid) { |
|||
// This doesn't count login failures towards account lockout
|
|||
// To enable password failures to trigger account lockout, set lockoutOnFailure: true
|
|||
var result = await _signInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, lockoutOnFailure: false); |
|||
if (result.Succeeded) { |
|||
return RedirectToLocal(returnUrl); |
|||
} |
|||
if (result.RequiresTwoFactor) { |
|||
return RedirectToAction(nameof(SendCode), new { ReturnUrl = returnUrl, RememberMe = model.RememberMe }); |
|||
} |
|||
if (result.IsLockedOut) { |
|||
return View("Lockout"); |
|||
} |
|||
else { |
|||
ModelState.AddModelError(string.Empty, "Invalid login attempt."); |
|||
return View(model); |
|||
} |
|||
} |
|||
|
|||
// If we got this far, something failed, redisplay form
|
|||
return View(model); |
|||
} |
|||
|
|||
//
|
|||
// GET: /Account/Register
|
|||
[HttpGet] |
|||
[AllowAnonymous] |
|||
public IActionResult Register(string returnUrl = null) { |
|||
ViewData["ReturnUrl"] = returnUrl; |
|||
return View(); |
|||
} |
|||
|
|||
//
|
|||
// POST: /Account/Register
|
|||
[HttpPost] |
|||
[AllowAnonymous] |
|||
[ValidateAntiForgeryToken] |
|||
public async Task<IActionResult> Register(RegisterViewModel model, string returnUrl = null) { |
|||
EnsureDatabaseCreated(_applicationDbContext); |
|||
ViewData["ReturnUrl"] = returnUrl; |
|||
if (ModelState.IsValid) { |
|||
var user = new ApplicationUser { UserName = model.Email, Email = model.Email }; |
|||
var result = await _userManager.CreateAsync(user, model.Password); |
|||
if (result.Succeeded) { |
|||
// For more information on how to enable account confirmation and password reset please visit http://go.microsoft.com/fwlink/?LinkID=532713
|
|||
// Send an email with this link
|
|||
//var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
|
|||
//var callbackUrl = Url.Action("ConfirmEmail", "Account", new { userId = user.Id, code = code }, protocol: Context.Request.Scheme);
|
|||
//await _emailSender.SendEmailAsync(model.Email, "Confirm your account",
|
|||
// "Please confirm your account by clicking this link: <a href=\"" + callbackUrl + "\">link</a>");
|
|||
await _signInManager.SignInAsync(user, isPersistent: false); |
|||
return RedirectToLocal(returnUrl); |
|||
} |
|||
AddErrors(result); |
|||
} |
|||
|
|||
// If we got this far, something failed, redisplay form
|
|||
return View(model); |
|||
} |
|||
|
|||
//
|
|||
// POST: /Account/LogOff
|
|||
[HttpPost] |
|||
[ValidateAntiForgeryToken] |
|||
public async Task<IActionResult> LogOff() { |
|||
await _signInManager.SignOutAsync(); |
|||
return RedirectToAction(nameof(HomeController.Index), "Home"); |
|||
} |
|||
|
|||
//
|
|||
// POST: /Account/ExternalLogin
|
|||
[HttpPost] |
|||
[AllowAnonymous] |
|||
[ValidateAntiForgeryToken] |
|||
public IActionResult ExternalLogin(string provider, string returnUrl = null) { |
|||
EnsureDatabaseCreated(_applicationDbContext); |
|||
// Request a redirect to the external login provider.
|
|||
var redirectUrl = Url.Action("ExternalLoginCallback", "Account", new { ReturnUrl = returnUrl }); |
|||
var properties = _signInManager.ConfigureExternalAuthenticationProperties(provider, redirectUrl); |
|||
return new ChallengeResult(provider, properties); |
|||
} |
|||
|
|||
//
|
|||
// GET: /Account/ExternalLoginCallback
|
|||
[HttpGet] |
|||
[AllowAnonymous] |
|||
public async Task<IActionResult> ExternalLoginCallback(string returnUrl = null) { |
|||
var info = await _signInManager.GetExternalLoginInfoAsync(); |
|||
if (info == null) { |
|||
return RedirectToAction(nameof(Login)); |
|||
} |
|||
|
|||
// Sign in the user with this external login provider if the user already has a login.
|
|||
var result = await _signInManager.ExternalLoginSignInAsync(info.LoginProvider, info.ProviderKey, isPersistent: false); |
|||
if (result.Succeeded) { |
|||
return RedirectToLocal(returnUrl); |
|||
} |
|||
if (result.RequiresTwoFactor) { |
|||
return RedirectToAction(nameof(SendCode), new { ReturnUrl = returnUrl }); |
|||
} |
|||
if (result.IsLockedOut) { |
|||
return View("Lockout"); |
|||
} |
|||
else { |
|||
// If the user does not have an account, then ask the user to create an account.
|
|||
ViewData["ReturnUrl"] = returnUrl; |
|||
ViewData["LoginProvider"] = info.LoginProvider; |
|||
var email = info.ExternalPrincipal.FindFirstValue(ClaimTypes.Email); |
|||
return View("ExternalLoginConfirmation", new ExternalLoginConfirmationViewModel { Email = email }); |
|||
} |
|||
} |
|||
|
|||
//
|
|||
// POST: /Account/ExternalLoginConfirmation
|
|||
[HttpPost] |
|||
[AllowAnonymous] |
|||
[ValidateAntiForgeryToken] |
|||
public async Task<IActionResult> ExternalLoginConfirmation(ExternalLoginConfirmationViewModel model, string returnUrl = null) { |
|||
if (User.IsSignedIn()) { |
|||
return RedirectToAction(nameof(ManageController.Index), "Manage"); |
|||
} |
|||
|
|||
if (ModelState.IsValid) { |
|||
// Get the information about the user from the external login provider
|
|||
var info = await _signInManager.GetExternalLoginInfoAsync(); |
|||
if (info == null) { |
|||
return View("ExternalLoginFailure"); |
|||
} |
|||
var user = new ApplicationUser { UserName = model.Email, Email = model.Email }; |
|||
var result = await _userManager.CreateAsync(user); |
|||
if (result.Succeeded) { |
|||
result = await _userManager.AddLoginAsync(user, info); |
|||
if (result.Succeeded) { |
|||
await _signInManager.SignInAsync(user, isPersistent: false); |
|||
return RedirectToLocal(returnUrl); |
|||
} |
|||
} |
|||
AddErrors(result); |
|||
} |
|||
|
|||
ViewData["ReturnUrl"] = returnUrl; |
|||
return View(model); |
|||
} |
|||
|
|||
// GET: /Account/ConfirmEmail
|
|||
[HttpGet] |
|||
[AllowAnonymous] |
|||
public async Task<IActionResult> ConfirmEmail(string userId, string code) { |
|||
if (userId == null || code == null) { |
|||
return View("Error"); |
|||
} |
|||
var user = await _userManager.FindByIdAsync(userId); |
|||
if (user == null) { |
|||
return View("Error"); |
|||
} |
|||
var result = await _userManager.ConfirmEmailAsync(user, code); |
|||
return View(result.Succeeded ? "ConfirmEmail" : "Error"); |
|||
} |
|||
|
|||
//
|
|||
// GET: /Account/ForgotPassword
|
|||
[HttpGet] |
|||
[AllowAnonymous] |
|||
public IActionResult ForgotPassword() { |
|||
return View(); |
|||
} |
|||
|
|||
//
|
|||
// POST: /Account/ForgotPassword
|
|||
[HttpPost] |
|||
[AllowAnonymous] |
|||
[ValidateAntiForgeryToken] |
|||
public async Task<IActionResult> ForgotPassword(ForgotPasswordViewModel model) { |
|||
if (ModelState.IsValid) { |
|||
var user = await _userManager.FindByNameAsync(model.Email); |
|||
if (user == null || !(await _userManager.IsEmailConfirmedAsync(user))) { |
|||
// Don't reveal that the user does not exist or is not confirmed
|
|||
return View("ForgotPasswordConfirmation"); |
|||
} |
|||
|
|||
// For more information on how to enable account confirmation and password reset please visit http://go.microsoft.com/fwlink/?LinkID=532713
|
|||
// Send an email with this link
|
|||
//var code = await _userManager.GeneratePasswordResetTokenAsync(user);
|
|||
//var callbackUrl = Url.Action("ResetPassword", "Account", new { userId = user.Id, code = code }, protocol: Context.Request.Scheme);
|
|||
//await _emailSender.SendEmailAsync(model.Email, "Reset Password",
|
|||
// "Please reset your password by clicking here: <a href=\"" + callbackUrl + "\">link</a>");
|
|||
//return View("ForgotPasswordConfirmation");
|
|||
} |
|||
|
|||
// If we got this far, something failed, redisplay form
|
|||
return View(model); |
|||
} |
|||
|
|||
//
|
|||
// GET: /Account/ForgotPasswordConfirmation
|
|||
[HttpGet] |
|||
[AllowAnonymous] |
|||
public IActionResult ForgotPasswordConfirmation() { |
|||
return View(); |
|||
} |
|||
|
|||
//
|
|||
// GET: /Account/ResetPassword
|
|||
[HttpGet] |
|||
[AllowAnonymous] |
|||
public IActionResult ResetPassword(string code = null) { |
|||
return code == null ? View("Error") : View(); |
|||
} |
|||
|
|||
//
|
|||
// POST: /Account/ResetPassword
|
|||
[HttpPost] |
|||
[AllowAnonymous] |
|||
[ValidateAntiForgeryToken] |
|||
public async Task<IActionResult> ResetPassword(ResetPasswordViewModel model) { |
|||
if (!ModelState.IsValid) { |
|||
return View(model); |
|||
} |
|||
var user = await _userManager.FindByNameAsync(model.Email); |
|||
if (user == null) { |
|||
// Don't reveal that the user does not exist
|
|||
return RedirectToAction(nameof(AccountController.ResetPasswordConfirmation), "Account"); |
|||
} |
|||
var result = await _userManager.ResetPasswordAsync(user, model.Code, model.Password); |
|||
if (result.Succeeded) { |
|||
return RedirectToAction(nameof(AccountController.ResetPasswordConfirmation), "Account"); |
|||
} |
|||
AddErrors(result); |
|||
return View(); |
|||
} |
|||
|
|||
//
|
|||
// GET: /Account/ResetPasswordConfirmation
|
|||
[HttpGet] |
|||
[AllowAnonymous] |
|||
public IActionResult ResetPasswordConfirmation() { |
|||
return View(); |
|||
} |
|||
|
|||
//
|
|||
// GET: /Account/SendCode
|
|||
[HttpGet] |
|||
[AllowAnonymous] |
|||
public async Task<ActionResult> SendCode(string returnUrl = null, bool rememberMe = false) { |
|||
var user = await _signInManager.GetTwoFactorAuthenticationUserAsync(); |
|||
if (user == null) { |
|||
return View("Error"); |
|||
} |
|||
var userFactors = await _userManager.GetValidTwoFactorProvidersAsync(user); |
|||
var factorOptions = userFactors.Select(purpose => new SelectListItem { Text = purpose, Value = purpose }).ToList(); |
|||
return View(new SendCodeViewModel { Providers = factorOptions, ReturnUrl = returnUrl, RememberMe = rememberMe }); |
|||
} |
|||
|
|||
//
|
|||
// POST: /Account/SendCode
|
|||
[HttpPost] |
|||
[AllowAnonymous] |
|||
[ValidateAntiForgeryToken] |
|||
public async Task<IActionResult> SendCode(SendCodeViewModel model) { |
|||
if (!ModelState.IsValid) { |
|||
return View(); |
|||
} |
|||
|
|||
var user = await _signInManager.GetTwoFactorAuthenticationUserAsync(); |
|||
if (user == null) { |
|||
return View("Error"); |
|||
} |
|||
|
|||
// Generate the token and send it
|
|||
var code = await _userManager.GenerateTwoFactorTokenAsync(user, model.SelectedProvider); |
|||
if (string.IsNullOrWhiteSpace(code)) { |
|||
return View("Error"); |
|||
} |
|||
|
|||
var message = "Your security code is: " + code; |
|||
if (model.SelectedProvider == "Email") { |
|||
await _emailSender.SendEmailAsync(await _userManager.GetEmailAsync(user), "Security Code", message); |
|||
} |
|||
else if (model.SelectedProvider == "Phone") { |
|||
await _smsSender.SendSmsAsync(await _userManager.GetPhoneNumberAsync(user), message); |
|||
} |
|||
|
|||
return RedirectToAction(nameof(VerifyCode), new { Provider = model.SelectedProvider, ReturnUrl = model.ReturnUrl, RememberMe = model.RememberMe }); |
|||
} |
|||
|
|||
//
|
|||
// GET: /Account/VerifyCode
|
|||
[HttpGet] |
|||
[AllowAnonymous] |
|||
public async Task<IActionResult> VerifyCode(string provider, bool rememberMe, string returnUrl = null) { |
|||
// Require that the user has already logged in via username/password or external login
|
|||
var user = await _signInManager.GetTwoFactorAuthenticationUserAsync(); |
|||
if (user == null) { |
|||
return View("Error"); |
|||
} |
|||
return View(new VerifyCodeViewModel { Provider = provider, ReturnUrl = returnUrl, RememberMe = rememberMe }); |
|||
} |
|||
|
|||
//
|
|||
// POST: /Account/VerifyCode
|
|||
[HttpPost] |
|||
[AllowAnonymous] |
|||
[ValidateAntiForgeryToken] |
|||
public async Task<IActionResult> VerifyCode(VerifyCodeViewModel model) { |
|||
if (!ModelState.IsValid) { |
|||
return View(model); |
|||
} |
|||
|
|||
// The following code protects for brute force attacks against the two factor codes.
|
|||
// If a user enters incorrect codes for a specified amount of time then the user account
|
|||
// will be locked out for a specified amount of time.
|
|||
var result = await _signInManager.TwoFactorSignInAsync(model.Provider, model.Code, model.RememberMe, model.RememberBrowser); |
|||
if (result.Succeeded) { |
|||
return RedirectToLocal(model.ReturnUrl); |
|||
} |
|||
if (result.IsLockedOut) { |
|||
return View("Lockout"); |
|||
} |
|||
else { |
|||
ModelState.AddModelError("", "Invalid code."); |
|||
return View(model); |
|||
} |
|||
} |
|||
|
|||
#region Helpers
|
|||
|
|||
// The following code creates the database and schema if they don't exist.
|
|||
// This is a temporary workaround since deploying database through EF migrations is
|
|||
// not yet supported in this release.
|
|||
// Please see this http://go.microsoft.com/fwlink/?LinkID=615859 for more information on how to do deploy the database
|
|||
// when publishing your application.
|
|||
private static void EnsureDatabaseCreated(ApplicationDbContext context) { |
|||
if (!_databaseChecked) { |
|||
_databaseChecked = true; |
|||
context.Database.EnsureCreated(); |
|||
} |
|||
} |
|||
|
|||
private void AddErrors(IdentityResult result) { |
|||
foreach (var error in result.Errors) { |
|||
ModelState.AddModelError(string.Empty, error.Description); |
|||
} |
|||
} |
|||
|
|||
private async Task<ApplicationUser> GetCurrentUserAsync() { |
|||
return await _userManager.FindByIdAsync(User.GetUserId()); |
|||
} |
|||
|
|||
private IActionResult RedirectToLocal(string returnUrl) { |
|||
if (Url.IsLocalUrl(returnUrl)) { |
|||
return Redirect(returnUrl); |
|||
} |
|||
else { |
|||
return RedirectToAction(nameof(HomeController.Index), "Home"); |
|||
} |
|||
} |
|||
|
|||
#endregion
|
|||
} |
|||
} |
|||
@ -0,0 +1,25 @@ |
|||
using Microsoft.AspNet.Mvc; |
|||
|
|||
namespace Mvc.Server.Controllers { |
|||
public class HomeController : Controller { |
|||
public IActionResult Index() { |
|||
return View(); |
|||
} |
|||
|
|||
public IActionResult About() { |
|||
ViewData["Message"] = "Your application description page."; |
|||
|
|||
return View(); |
|||
} |
|||
|
|||
public IActionResult Contact() { |
|||
ViewData["Message"] = "Your contact page."; |
|||
|
|||
return View(); |
|||
} |
|||
|
|||
public IActionResult Error() { |
|||
return View("~/Views/Shared/Error.cshtml"); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,321 @@ |
|||
using System.Linq; |
|||
using System.Security.Claims; |
|||
using System.Threading.Tasks; |
|||
using Microsoft.AspNet.Authorization; |
|||
using Microsoft.AspNet.Identity; |
|||
using Microsoft.AspNet.Mvc; |
|||
using Mvc.Server.Models; |
|||
using Mvc.Server.Services; |
|||
using Mvc.Server.ViewModels.Manage; |
|||
|
|||
namespace Mvc.Server.Controllers { |
|||
[Authorize] |
|||
public class ManageController : Controller { |
|||
private readonly UserManager<ApplicationUser> _userManager; |
|||
private readonly SignInManager<ApplicationUser> _signInManager; |
|||
private readonly IEmailSender _emailSender; |
|||
private readonly ISmsSender _smsSender; |
|||
|
|||
public ManageController( |
|||
UserManager<ApplicationUser> userManager, |
|||
SignInManager<ApplicationUser> signInManager, |
|||
IEmailSender emailSender, |
|||
ISmsSender smsSender) { |
|||
_userManager = userManager; |
|||
_signInManager = signInManager; |
|||
_emailSender = emailSender; |
|||
_smsSender = smsSender; |
|||
} |
|||
|
|||
//
|
|||
// GET: /Account/Index
|
|||
[HttpGet] |
|||
public async Task<IActionResult> Index(ManageMessageId? message = null) { |
|||
ViewData["StatusMessage"] = |
|||
message == ManageMessageId.ChangePasswordSuccess ? "Your password has been changed." |
|||
: message == ManageMessageId.SetPasswordSuccess ? "Your password has been set." |
|||
: message == ManageMessageId.SetTwoFactorSuccess ? "Your two-factor authentication provider has been set." |
|||
: message == ManageMessageId.Error ? "An error has occurred." |
|||
: message == ManageMessageId.AddPhoneSuccess ? "Your phone number was added." |
|||
: message == ManageMessageId.RemovePhoneSuccess ? "Your phone number was removed." |
|||
: ""; |
|||
|
|||
var user = await GetCurrentUserAsync(); |
|||
var model = new IndexViewModel { |
|||
HasPassword = await _userManager.HasPasswordAsync(user), |
|||
PhoneNumber = await _userManager.GetPhoneNumberAsync(user), |
|||
TwoFactor = await _userManager.GetTwoFactorEnabledAsync(user), |
|||
Logins = await _userManager.GetLoginsAsync(user), |
|||
BrowserRemembered = await _signInManager.IsTwoFactorClientRememberedAsync(user) |
|||
}; |
|||
return View(model); |
|||
} |
|||
|
|||
//
|
|||
// GET: /Account/RemoveLogin
|
|||
[HttpGet] |
|||
public async Task<IActionResult> RemoveLogin() { |
|||
var user = await GetCurrentUserAsync(); |
|||
var linkedAccounts = await _userManager.GetLoginsAsync(user); |
|||
ViewData["ShowRemoveButton"] = await _userManager.HasPasswordAsync(user) || linkedAccounts.Count > 1; |
|||
return View(linkedAccounts); |
|||
} |
|||
|
|||
//
|
|||
// POST: /Manage/RemoveLogin
|
|||
[HttpPost] |
|||
[ValidateAntiForgeryToken] |
|||
public async Task<IActionResult> RemoveLogin(string loginProvider, string providerKey) { |
|||
ManageMessageId? message = ManageMessageId.Error; |
|||
var user = await GetCurrentUserAsync(); |
|||
if (user != null) { |
|||
var result = await _userManager.RemoveLoginAsync(user, loginProvider, providerKey); |
|||
if (result.Succeeded) { |
|||
await _signInManager.SignInAsync(user, isPersistent: false); |
|||
message = ManageMessageId.RemoveLoginSuccess; |
|||
} |
|||
} |
|||
return RedirectToAction(nameof(ManageLogins), new { Message = message }); |
|||
} |
|||
|
|||
//
|
|||
// GET: /Account/AddPhoneNumber
|
|||
public IActionResult AddPhoneNumber() { |
|||
return View(); |
|||
} |
|||
|
|||
//
|
|||
// POST: /Account/AddPhoneNumber
|
|||
[HttpPost] |
|||
[ValidateAntiForgeryToken] |
|||
public async Task<IActionResult> AddPhoneNumber(AddPhoneNumberViewModel model) { |
|||
if (!ModelState.IsValid) { |
|||
return View(model); |
|||
} |
|||
// Generate the token and send it
|
|||
var user = await GetCurrentUserAsync(); |
|||
var code = await _userManager.GenerateChangePhoneNumberTokenAsync(user, model.PhoneNumber); |
|||
await _smsSender.SendSmsAsync(model.PhoneNumber, "Your security code is: " + code); |
|||
return RedirectToAction(nameof(VerifyPhoneNumber), new { PhoneNumber = model.PhoneNumber }); |
|||
} |
|||
|
|||
//
|
|||
// POST: /Manage/EnableTwoFactorAuthentication
|
|||
[HttpPost] |
|||
[ValidateAntiForgeryToken] |
|||
public async Task<IActionResult> EnableTwoFactorAuthentication() { |
|||
var user = await GetCurrentUserAsync(); |
|||
if (user != null) { |
|||
await _userManager.SetTwoFactorEnabledAsync(user, true); |
|||
await _signInManager.SignInAsync(user, isPersistent: false); |
|||
} |
|||
return RedirectToAction(nameof(Index), "Manage"); |
|||
} |
|||
|
|||
//
|
|||
// POST: /Manage/DisableTwoFactorAuthentication
|
|||
[HttpPost] |
|||
[ValidateAntiForgeryToken] |
|||
public async Task<IActionResult> DisableTwoFactorAuthentication() { |
|||
var user = await GetCurrentUserAsync(); |
|||
if (user != null) { |
|||
await _userManager.SetTwoFactorEnabledAsync(user, false); |
|||
await _signInManager.SignInAsync(user, isPersistent: false); |
|||
} |
|||
return RedirectToAction(nameof(Index), "Manage"); |
|||
} |
|||
|
|||
//
|
|||
// GET: /Account/VerifyPhoneNumber
|
|||
[HttpGet] |
|||
public async Task<IActionResult> VerifyPhoneNumber(string phoneNumber) { |
|||
var code = await _userManager.GenerateChangePhoneNumberTokenAsync(await GetCurrentUserAsync(), phoneNumber); |
|||
// Send an SMS to verify the phone number
|
|||
return phoneNumber == null ? View("Error") : View(new VerifyPhoneNumberViewModel { PhoneNumber = phoneNumber }); |
|||
} |
|||
|
|||
//
|
|||
// POST: /Account/VerifyPhoneNumber
|
|||
[HttpPost] |
|||
[ValidateAntiForgeryToken] |
|||
public async Task<IActionResult> VerifyPhoneNumber(VerifyPhoneNumberViewModel model) { |
|||
if (!ModelState.IsValid) { |
|||
return View(model); |
|||
} |
|||
var user = await GetCurrentUserAsync(); |
|||
if (user != null) { |
|||
var result = await _userManager.ChangePhoneNumberAsync(user, model.PhoneNumber, model.Code); |
|||
if (result.Succeeded) { |
|||
await _signInManager.SignInAsync(user, isPersistent: false); |
|||
return RedirectToAction(nameof(Index), new { Message = ManageMessageId.AddPhoneSuccess }); |
|||
} |
|||
} |
|||
// If we got this far, something failed, redisplay the form
|
|||
ModelState.AddModelError(string.Empty, "Failed to verify phone number"); |
|||
return View(model); |
|||
} |
|||
|
|||
//
|
|||
// GET: /Account/RemovePhoneNumber
|
|||
[HttpGet] |
|||
public async Task<IActionResult> RemovePhoneNumber() { |
|||
var user = await GetCurrentUserAsync(); |
|||
if (user != null) { |
|||
var result = await _userManager.SetPhoneNumberAsync(user, null); |
|||
if (result.Succeeded) { |
|||
await _signInManager.SignInAsync(user, isPersistent: false); |
|||
return RedirectToAction(nameof(Index), new { Message = ManageMessageId.RemovePhoneSuccess }); |
|||
} |
|||
} |
|||
return RedirectToAction(nameof(Index), new { Message = ManageMessageId.Error }); |
|||
} |
|||
|
|||
//
|
|||
// GET: /Manage/ChangePassword
|
|||
[HttpGet] |
|||
public IActionResult ChangePassword() { |
|||
return View(); |
|||
} |
|||
|
|||
//
|
|||
// POST: /Account/Manage
|
|||
[HttpPost] |
|||
[ValidateAntiForgeryToken] |
|||
public async Task<IActionResult> ChangePassword(ChangePasswordViewModel model) { |
|||
if (!ModelState.IsValid) { |
|||
return View(model); |
|||
} |
|||
var user = await GetCurrentUserAsync(); |
|||
if (user != null) { |
|||
var result = await _userManager.ChangePasswordAsync(user, model.OldPassword, model.NewPassword); |
|||
if (result.Succeeded) { |
|||
await _signInManager.SignInAsync(user, isPersistent: false); |
|||
return RedirectToAction(nameof(Index), new { Message = ManageMessageId.ChangePasswordSuccess }); |
|||
} |
|||
AddErrors(result); |
|||
return View(model); |
|||
} |
|||
return RedirectToAction(nameof(Index), new { Message = ManageMessageId.Error }); |
|||
} |
|||
|
|||
//
|
|||
// GET: /Manage/SetPassword
|
|||
[HttpGet] |
|||
public IActionResult SetPassword() { |
|||
return View(); |
|||
} |
|||
|
|||
//
|
|||
// POST: /Manage/SetPassword
|
|||
[HttpPost] |
|||
[ValidateAntiForgeryToken] |
|||
public async Task<IActionResult> SetPassword(SetPasswordViewModel model) { |
|||
if (!ModelState.IsValid) { |
|||
return View(model); |
|||
} |
|||
|
|||
var user = await GetCurrentUserAsync(); |
|||
if (user != null) { |
|||
var result = await _userManager.AddPasswordAsync(user, model.NewPassword); |
|||
if (result.Succeeded) { |
|||
await _signInManager.SignInAsync(user, isPersistent: false); |
|||
return RedirectToAction(nameof(Index), new { Message = ManageMessageId.SetPasswordSuccess }); |
|||
} |
|||
AddErrors(result); |
|||
return View(model); |
|||
} |
|||
return RedirectToAction(nameof(Index), new { Message = ManageMessageId.Error }); |
|||
} |
|||
|
|||
//GET: /Account/Manage
|
|||
[HttpGet] |
|||
public async Task<IActionResult> ManageLogins(ManageMessageId? message = null) { |
|||
ViewData["StatusMessage"] = |
|||
message == ManageMessageId.RemoveLoginSuccess ? "The external login was removed." |
|||
: message == ManageMessageId.AddLoginSuccess ? "The external login was added." |
|||
: message == ManageMessageId.Error ? "An error has occurred." |
|||
: ""; |
|||
var user = await GetCurrentUserAsync(); |
|||
if (user == null) { |
|||
return View("Error"); |
|||
} |
|||
var userLogins = await _userManager.GetLoginsAsync(user); |
|||
var otherLogins = _signInManager.GetExternalAuthenticationSchemes().Where(auth => userLogins.All(ul => auth.AuthenticationScheme != ul.LoginProvider)).ToList(); |
|||
ViewData["ShowRemoveButton"] = user.PasswordHash != null || userLogins.Count > 1; |
|||
return View(new ManageLoginsViewModel { |
|||
CurrentLogins = userLogins, |
|||
OtherLogins = otherLogins |
|||
}); |
|||
} |
|||
|
|||
//
|
|||
// POST: /Manage/LinkLogin
|
|||
[HttpPost] |
|||
[ValidateAntiForgeryToken] |
|||
public IActionResult LinkLogin(string provider) { |
|||
// Request a redirect to the external login provider to link a login for the current user
|
|||
var redirectUrl = Url.Action("LinkLoginCallback", "Manage"); |
|||
var properties = _signInManager.ConfigureExternalAuthenticationProperties(provider, redirectUrl, User.GetUserId()); |
|||
return new ChallengeResult(provider, properties); |
|||
} |
|||
|
|||
//
|
|||
// GET: /Manage/LinkLoginCallback
|
|||
[HttpGet] |
|||
public async Task<ActionResult> LinkLoginCallback() { |
|||
var user = await GetCurrentUserAsync(); |
|||
if (user == null) { |
|||
return View("Error"); |
|||
} |
|||
var info = await _signInManager.GetExternalLoginInfoAsync(User.GetUserId()); |
|||
if (info == null) { |
|||
return RedirectToAction(nameof(ManageLogins), new { Message = ManageMessageId.Error }); |
|||
} |
|||
var result = await _userManager.AddLoginAsync(user, info); |
|||
var message = result.Succeeded ? ManageMessageId.AddLoginSuccess : ManageMessageId.Error; |
|||
return RedirectToAction(nameof(ManageLogins), new { Message = message }); |
|||
} |
|||
|
|||
#region Helpers
|
|||
|
|||
private void AddErrors(IdentityResult result) { |
|||
foreach (var error in result.Errors) { |
|||
ModelState.AddModelError(string.Empty, error.Description); |
|||
} |
|||
} |
|||
|
|||
private async Task<bool> HasPhoneNumber() { |
|||
var user = await _userManager.FindByIdAsync(User.GetUserId()); |
|||
if (user != null) { |
|||
return user.PhoneNumber != null; |
|||
} |
|||
return false; |
|||
} |
|||
|
|||
public enum ManageMessageId { |
|||
AddPhoneSuccess, |
|||
AddLoginSuccess, |
|||
ChangePasswordSuccess, |
|||
SetTwoFactorSuccess, |
|||
SetPasswordSuccess, |
|||
RemoveLoginSuccess, |
|||
RemovePhoneSuccess, |
|||
Error |
|||
} |
|||
|
|||
private async Task<ApplicationUser> GetCurrentUserAsync() { |
|||
return await _userManager.FindByIdAsync(User.GetUserId()); |
|||
} |
|||
|
|||
private IActionResult RedirectToLocal(string returnUrl) { |
|||
if (Url.IsLocalUrl(returnUrl)) { |
|||
return Redirect(returnUrl); |
|||
} |
|||
else { |
|||
return RedirectToAction(nameof(HomeController.Index), nameof(HomeController)); |
|||
} |
|||
} |
|||
|
|||
#endregion
|
|||
} |
|||
} |
|||
@ -0,0 +1,26 @@ |
|||
using System.Globalization; |
|||
using System.Security.Claims; |
|||
using Microsoft.AspNet.Authorization; |
|||
using Microsoft.AspNet.Mvc; |
|||
|
|||
namespace Mvc.Server.Controllers { |
|||
[Route("api")] |
|||
public class ResourceController : Controller { |
|||
[Authorize(ActiveAuthenticationSchemes = "Bearer")] |
|||
[HttpGet("message")] |
|||
public IActionResult GetMessage() { |
|||
var identity = User.Identity as ClaimsIdentity; |
|||
if (identity == null) { |
|||
return HttpBadRequest(); |
|||
} |
|||
|
|||
// Note: identity is the ClaimsIdentity representing the resource owner
|
|||
// and identity.Actor is the identity corresponding to the client
|
|||
// application the access token has been issued to (delegation).
|
|||
return Content(string.Format( |
|||
CultureInfo.InvariantCulture, |
|||
"{0} has been successfully authenticated via {1}", |
|||
identity.Name, identity.Actor.Name)); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,14 @@ |
|||
using Microsoft.Data.Entity; |
|||
using OpenIddict; |
|||
|
|||
namespace Mvc.Server.Models { |
|||
public class ApplicationDbContext : OpenIddictContext<ApplicationUser> { |
|||
protected override void OnModelCreating(ModelBuilder builder) { |
|||
base.OnModelCreating(builder); |
|||
|
|||
// Customize the ASP.NET Identity model and override the defaults if needed.
|
|||
// For example, you can rename the ASP.NET Identity table names and more.
|
|||
// Add your customizations after calling base.OnModelCreating(builder);
|
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,7 @@ |
|||
using Microsoft.AspNet.Identity.EntityFramework; |
|||
|
|||
namespace Mvc.Server.Models { |
|||
// Add profile data for application users by adding properties to the ApplicationUser class
|
|||
public class ApplicationUser : IdentityUser { |
|||
} |
|||
} |
|||
@ -0,0 +1,29 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<Project ToolsVersion="__ToolsVersion__" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
|||
<PropertyGroup> |
|||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion> |
|||
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath> |
|||
</PropertyGroup> |
|||
<PropertyGroup Label="Globals"> |
|||
<ProjectGuid>7cbeafd2-e3d0-4424-9b78-e87ab52327a6</ProjectGuid> |
|||
<OutputType>Web</OutputType> |
|||
</PropertyGroup> |
|||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x86'" Label="Configuration"> |
|||
</PropertyGroup> |
|||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x86'" Label="Configuration"> |
|||
</PropertyGroup> |
|||
<PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'"> |
|||
<AssemblyName>Mvc.Server</AssemblyName> |
|||
</PropertyGroup> |
|||
<PropertyGroup Label="Configuration"> |
|||
<RootNamespace>Mvc.Server</RootNamespace> |
|||
</PropertyGroup> |
|||
<PropertyGroup> |
|||
<SchemaVersion>2.0</SchemaVersion> |
|||
<DevelopmentServerPort>54540</DevelopmentServerPort> |
|||
<CommandLineArguments /> |
|||
<DebugTarget>web</DebugTarget> |
|||
</PropertyGroup> |
|||
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.Props" /> |
|||
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.targets" /> |
|||
</Project> |
|||
@ -0,0 +1,7 @@ |
|||
using System.Threading.Tasks; |
|||
|
|||
namespace Mvc.Server.Services { |
|||
public interface IEmailSender { |
|||
Task SendEmailAsync(string email, string subject, string message); |
|||
} |
|||
} |
|||
@ -0,0 +1,7 @@ |
|||
using System.Threading.Tasks; |
|||
|
|||
namespace Mvc.Server.Services { |
|||
public interface ISmsSender { |
|||
Task SendSmsAsync(string number, string message); |
|||
} |
|||
} |
|||
@ -0,0 +1,18 @@ |
|||
using System.Threading.Tasks; |
|||
|
|||
namespace Mvc.Server.Services { |
|||
// This class is used by the application to send Email and SMS
|
|||
// when you turn on two-factor authentication in ASP.NET Identity.
|
|||
// For more details see this link http://go.microsoft.com/fwlink/?LinkID=532713
|
|||
public class AuthMessageSender : IEmailSender, ISmsSender { |
|||
public Task SendEmailAsync(string email, string subject, string message) { |
|||
// Plug in your email service here to send an email.
|
|||
return Task.FromResult(0); |
|||
} |
|||
|
|||
public Task SendSmsAsync(string number, string message) { |
|||
// Plug in your SMS service here to send a text message.
|
|||
return Task.FromResult(0); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,103 @@ |
|||
using System.Linq; |
|||
using Microsoft.AspNet.Builder; |
|||
using Microsoft.AspNet.Identity.EntityFramework; |
|||
using Microsoft.Data.Entity; |
|||
using Microsoft.Dnx.Runtime; |
|||
using Microsoft.Framework.Configuration; |
|||
using Microsoft.Framework.DependencyInjection; |
|||
using Microsoft.Framework.Logging; |
|||
using Microsoft.IdentityModel.Protocols; |
|||
using Microsoft.IdentityModel.Protocols.OpenIdConnect; |
|||
using Mvc.Server.Models; |
|||
using Mvc.Server.Services; |
|||
using OpenIddict.Models; |
|||
|
|||
namespace Mvc.Server { |
|||
public class Startup { |
|||
public Startup(IApplicationEnvironment environment) { |
|||
Configuration = new ConfigurationBuilder() |
|||
.SetBasePath(environment.ApplicationBasePath) |
|||
.AddJsonFile("config.json") |
|||
.AddEnvironmentVariables() |
|||
.Build(); |
|||
} |
|||
|
|||
public IConfiguration Configuration { get; } |
|||
|
|||
public void ConfigureServices(IServiceCollection services) { |
|||
services.AddMvc(); |
|||
|
|||
services.AddEntityFramework() |
|||
.AddSqlServer() |
|||
.AddDbContext<ApplicationDbContext>(options => |
|||
options.UseSqlServer(Configuration["Data:DefaultConnection:ConnectionString"])); |
|||
|
|||
services.AddIdentity<ApplicationUser, IdentityRole>() |
|||
.AddEntityFrameworkStores<ApplicationDbContext>() |
|||
.AddDefaultTokenProviders(); |
|||
|
|||
services.AddTransient<IEmailSender, AuthMessageSender>(); |
|||
services.AddTransient<ISmsSender, AuthMessageSender>(); |
|||
} |
|||
|
|||
public void Configure(IApplicationBuilder app) { |
|||
var factory = app.ApplicationServices.GetRequiredService<ILoggerFactory>(); |
|||
factory.AddConsole(); |
|||
|
|||
app.UseStaticFiles(); |
|||
|
|||
// Add a middleware used to validate access
|
|||
// tokens and protect the API endpoints.
|
|||
app.UseJwtBearerAuthentication(options => { |
|||
options.Audience = "http://localhost:54540/"; |
|||
options.Authority = "http://localhost:54540/"; |
|||
|
|||
// Note: by default, IdentityModel beta8 now refuses to initiate non-HTTPS calls.
|
|||
// To work around this limitation, the configuration manager is manually
|
|||
// instantiated with a document retriever allowing HTTP calls.
|
|||
options.ConfigurationManager = new ConfigurationManager<OpenIdConnectConfiguration>( |
|||
metadataAddress: options.Authority + ".well-known/openid-configuration", |
|||
configRetriever: new OpenIdConnectConfigurationRetriever(), |
|||
docRetriever: new HttpDocumentRetriever { RequireHttps = false }); |
|||
}); |
|||
|
|||
app.UseIdentity(); |
|||
|
|||
app.UseGoogleAuthentication(options => { |
|||
options.ClientId = "560027070069-37ldt4kfuohhu3m495hk2j4pjp92d382.apps.googleusercontent.com"; |
|||
options.ClientSecret = "n2Q-GEw9RQjzcRbU3qhfTj8f"; |
|||
}); |
|||
|
|||
app.UseTwitterAuthentication(options => { |
|||
options.ConsumerKey = "6XaCTaLbMqfj6ww3zvZ5g"; |
|||
options.ConsumerSecret = "Il2eFzGIrYhz6BWjYhVXBPQSfZuS4xoHpSSyD9PI"; |
|||
}); |
|||
|
|||
// Note: OpenIddict must be added after
|
|||
// ASP.NET Identity and the external providers.
|
|||
app.UseOpenIddict<ApplicationDbContext, ApplicationUser>(options => { |
|||
options.AllowInsecureHttp = true; |
|||
}); |
|||
|
|||
app.UseMvcWithDefaultRoute(); |
|||
|
|||
using (var context = app.ApplicationServices.GetRequiredService<ApplicationDbContext>()) { |
|||
context.Database.EnsureCreated(); |
|||
|
|||
// Add Mvc.Client to the known applications.
|
|||
if (!context.Applications.Any()) { |
|||
context.Applications.Add(new Application { |
|||
ApplicationID = "myClient", |
|||
DisplayName = "My client application", |
|||
RedirectUri = "http://localhost:53507/oidc", |
|||
LogoutRedirectUri = "http://localhost:53507/", |
|||
Secret = "secret_secret_secret", |
|||
Type = ApplicationType.Confidential |
|||
}); |
|||
|
|||
context.SaveChanges(); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,10 @@ |
|||
using System.ComponentModel.DataAnnotations; |
|||
|
|||
namespace Mvc.Server.ViewModels.Account { |
|||
public class ExternalLoginConfirmationViewModel |
|||
{ |
|||
[Required] |
|||
[EmailAddress] |
|||
public string Email { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,9 @@ |
|||
using System.ComponentModel.DataAnnotations; |
|||
|
|||
namespace Mvc.Server.ViewModels.Account { |
|||
public class ForgotPasswordViewModel { |
|||
[Required] |
|||
[EmailAddress] |
|||
public string Email { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,16 @@ |
|||
using System.ComponentModel.DataAnnotations; |
|||
|
|||
namespace Mvc.Server.ViewModels.Account { |
|||
public class LoginViewModel { |
|||
[Required] |
|||
[EmailAddress] |
|||
public string Email { get; set; } |
|||
|
|||
[Required] |
|||
[DataType(DataType.Password)] |
|||
public string Password { get; set; } |
|||
|
|||
[Display(Name = "Remember me?")] |
|||
public bool RememberMe { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,21 @@ |
|||
using System.ComponentModel.DataAnnotations; |
|||
|
|||
namespace Mvc.Server.ViewModels.Account { |
|||
public class RegisterViewModel { |
|||
[Required] |
|||
[EmailAddress] |
|||
[Display(Name = "Email")] |
|||
public string Email { get; set; } |
|||
|
|||
[Required] |
|||
[StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)] |
|||
[DataType(DataType.Password)] |
|||
[Display(Name = "Password")] |
|||
public string Password { get; set; } |
|||
|
|||
[DataType(DataType.Password)] |
|||
[Display(Name = "Confirm password")] |
|||
[Compare("Password", ErrorMessage = "The password and confirmation password do not match.")] |
|||
public string ConfirmPassword { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,21 @@ |
|||
using System.ComponentModel.DataAnnotations; |
|||
|
|||
namespace Mvc.Server.ViewModels.Account { |
|||
public class ResetPasswordViewModel { |
|||
[Required] |
|||
[EmailAddress] |
|||
public string Email { get; set; } |
|||
|
|||
[Required] |
|||
[StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)] |
|||
[DataType(DataType.Password)] |
|||
public string Password { get; set; } |
|||
|
|||
[DataType(DataType.Password)] |
|||
[Display(Name = "Confirm password")] |
|||
[Compare("Password", ErrorMessage = "The password and confirmation password do not match.")] |
|||
public string ConfirmPassword { get; set; } |
|||
|
|||
public string Code { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,14 @@ |
|||
using System.Collections.Generic; |
|||
using Microsoft.AspNet.Mvc.Rendering; |
|||
|
|||
namespace Mvc.Server.ViewModels.Account { |
|||
public class SendCodeViewModel { |
|||
public string SelectedProvider { get; set; } |
|||
|
|||
public ICollection<SelectListItem> Providers { get; set; } |
|||
|
|||
public string ReturnUrl { get; set; } |
|||
|
|||
public bool RememberMe { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,19 @@ |
|||
using System.ComponentModel.DataAnnotations; |
|||
|
|||
namespace Mvc.Server.ViewModels.Account { |
|||
public class VerifyCodeViewModel { |
|||
[Required] |
|||
public string Provider { get; set; } |
|||
|
|||
[Required] |
|||
public string Code { get; set; } |
|||
|
|||
public string ReturnUrl { get; set; } |
|||
|
|||
[Display(Name = "Remember this browser?")] |
|||
public bool RememberBrowser { get; set; } |
|||
|
|||
[Display(Name = "Remember me?")] |
|||
public bool RememberMe { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,10 @@ |
|||
using System.ComponentModel.DataAnnotations; |
|||
|
|||
namespace Mvc.Server.ViewModels.Manage { |
|||
public class AddPhoneNumberViewModel { |
|||
[Required] |
|||
[Phone] |
|||
[Display(Name = "Phone number")] |
|||
public string PhoneNumber { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,21 @@ |
|||
using System.ComponentModel.DataAnnotations; |
|||
|
|||
namespace Mvc.Server.ViewModels.Manage { |
|||
public class ChangePasswordViewModel { |
|||
[Required] |
|||
[DataType(DataType.Password)] |
|||
[Display(Name = "Current password")] |
|||
public string OldPassword { get; set; } |
|||
|
|||
[Required] |
|||
[StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)] |
|||
[DataType(DataType.Password)] |
|||
[Display(Name = "New password")] |
|||
public string NewPassword { get; set; } |
|||
|
|||
[DataType(DataType.Password)] |
|||
[Display(Name = "Confirm new password")] |
|||
[Compare("NewPassword", ErrorMessage = "The new password and confirmation password do not match.")] |
|||
public string ConfirmPassword { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,10 @@ |
|||
using System.Collections.Generic; |
|||
using Microsoft.AspNet.Mvc.Rendering; |
|||
|
|||
namespace Mvc.Server.ViewModels.Manage { |
|||
public class ConfigureTwoFactorViewModel { |
|||
public string SelectedProvider { get; set; } |
|||
|
|||
public ICollection<SelectListItem> Providers { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,5 @@ |
|||
namespace Mvc.Server.ViewModels.Manage { |
|||
public class FactorViewModel { |
|||
public string Purpose { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,16 @@ |
|||
using System.Collections.Generic; |
|||
using Microsoft.AspNet.Identity; |
|||
|
|||
namespace Mvc.Server.ViewModels.Manage { |
|||
public class IndexViewModel { |
|||
public bool HasPassword { get; set; } |
|||
|
|||
public IList<UserLoginInfo> Logins { get; set; } |
|||
|
|||
public string PhoneNumber { get; set; } |
|||
|
|||
public bool TwoFactor { get; set; } |
|||
|
|||
public bool BrowserRemembered { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,12 @@ |
|||
using System.Collections.Generic; |
|||
using Microsoft.AspNet.Http.Authentication; |
|||
using Microsoft.AspNet.Identity; |
|||
|
|||
namespace Mvc.Server.ViewModels.Manage { |
|||
public class ManageLoginsViewModel |
|||
{ |
|||
public IList<UserLoginInfo> CurrentLogins { get; set; } |
|||
|
|||
public IList<AuthenticationDescription> OtherLogins { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,16 @@ |
|||
using System.ComponentModel.DataAnnotations; |
|||
|
|||
namespace Mvc.Server.ViewModels.Manage { |
|||
public class SetPasswordViewModel { |
|||
[Required] |
|||
[StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)] |
|||
[DataType(DataType.Password)] |
|||
[Display(Name = "New password")] |
|||
public string NewPassword { get; set; } |
|||
|
|||
[DataType(DataType.Password)] |
|||
[Display(Name = "Confirm new password")] |
|||
[Compare("NewPassword", ErrorMessage = "The new password and confirmation password do not match.")] |
|||
public string ConfirmPassword { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,13 @@ |
|||
using System.ComponentModel.DataAnnotations; |
|||
|
|||
namespace Mvc.Server.ViewModels.Manage { |
|||
public class VerifyPhoneNumberViewModel { |
|||
[Required] |
|||
public string Code { get; set; } |
|||
|
|||
[Required] |
|||
[Phone] |
|||
[Display(Name = "Phone number")] |
|||
public string PhoneNumber { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,10 @@ |
|||
@{ |
|||
ViewData["Title"] = "Confirm Email"; |
|||
} |
|||
|
|||
<h2>@ViewData["Title"].</h2> |
|||
<div> |
|||
<p> |
|||
Thank you for confirming your email. Please <a asp-controller="Account" asp-action="Login">Click here to Log in</a>. |
|||
</p> |
|||
</div> |
|||
@ -0,0 +1,35 @@ |
|||
@model ExternalLoginConfirmationViewModel |
|||
@{ |
|||
ViewData["Title"] = "Register"; |
|||
} |
|||
|
|||
<h2>@ViewData["Title"].</h2> |
|||
<h3>Associate your @ViewData["LoginProvider"] account.</h3> |
|||
|
|||
<form asp-controller="Account" asp-action="ExternalLoginConfirmation" asp-route-returnurl="@ViewData["ReturnUrl"]" method="post" class="form-horizontal" role="form"> |
|||
<h4>Association Form</h4> |
|||
<hr /> |
|||
<div asp-validation-summary="ValidationSummary.All" class="text-danger"></div> |
|||
|
|||
<p class="text-info"> |
|||
You've successfully authenticated with <strong>@ViewData["LoginProvider"]</strong>. |
|||
Please enter a user name for this site below and click the Register button to finish |
|||
logging in. |
|||
</p> |
|||
<div class="form-group"> |
|||
<label asp-for="Email" class="col-md-2 control-label"></label> |
|||
<div class="col-md-10"> |
|||
<input asp-for="Email" class="form-control" /> |
|||
<span asp-validation-for="Email" class="text-danger"></span> |
|||
</div> |
|||
</div> |
|||
<div class="form-group"> |
|||
<div class="col-md-offset-2 col-md-10"> |
|||
<button type="submit" class="btn btn-default">Register</button> |
|||
</div> |
|||
</div> |
|||
</form> |
|||
|
|||
@section Scripts { |
|||
@{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); } |
|||
} |
|||
@ -0,0 +1,8 @@ |
|||
@{ |
|||
ViewData["Title"] = "Login Failure"; |
|||
} |
|||
|
|||
<hgroup> |
|||
<h2>@ViewData["Title"].</h2> |
|||
<h3 class="text-danger">Unsuccessful login with service.</h3> |
|||
</hgroup> |
|||
@ -0,0 +1,31 @@ |
|||
@model ForgotPasswordViewModel |
|||
@{ |
|||
ViewData["Title"] = "Forgot your password?"; |
|||
} |
|||
|
|||
<h2>@ViewData["Title"].</h2> |
|||
<p> |
|||
For more information on how to enable reset password please see this <a href="http://go.microsoft.com/fwlink/?LinkID=532713">article</a>. |
|||
</p> |
|||
|
|||
@*<form asp-controller="Account" asp-action="ForgotPassword" method="post" class="form-horizontal" role="form"> |
|||
<h4>Enter your email.</h4> |
|||
<hr /> |
|||
<div asp-validation-summary="ValidationSummary.All" class="text-danger"></div> |
|||
<div class="form-group"> |
|||
<label asp-for="Email" class="col-md-2 control-label"></label> |
|||
<div class="col-md-10"> |
|||
<input asp-for="Email" class="form-control" /> |
|||
<span asp-validation-for="Email" class="text-danger"></span> |
|||
</div> |
|||
</div> |
|||
<div class="form-group"> |
|||
<div class="col-md-offset-2 col-md-10"> |
|||
<button type="submit" class="btn btn-default">Submit</button> |
|||
</div> |
|||
</div> |
|||
</form>*@ |
|||
|
|||
@section Scripts { |
|||
@{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); } |
|||
} |
|||
@ -0,0 +1,8 @@ |
|||
@{ |
|||
ViewData["Title"] = "Forgot Password Confirmation"; |
|||
} |
|||
|
|||
<h2>@ViewData["Title"].</h2> |
|||
<p> |
|||
Please check your email to reset your password. |
|||
</p> |
|||
@ -0,0 +1,8 @@ |
|||
@{ |
|||
ViewData["Title"] = "Locked out"; |
|||
} |
|||
|
|||
<hgroup> |
|||
<h1 class="text-danger">Locked out.</h1> |
|||
<h2 class="text-danger">This account has been locked out, please try again later.</h2> |
|||
</hgroup> |
|||
@ -0,0 +1,90 @@ |
|||
@using System.Collections.Generic |
|||
@using Microsoft.AspNet.Http |
|||
@using Microsoft.AspNet.Http.Authentication |
|||
@model LoginViewModel |
|||
@inject SignInManager<ApplicationUser> SignInManager |
|||
|
|||
@{ |
|||
ViewData["Title"] = "Log in"; |
|||
} |
|||
|
|||
<h2>@ViewData["Title"].</h2> |
|||
<div class="row"> |
|||
<div class="col-md-8"> |
|||
<section> |
|||
<form asp-controller="Account" asp-action="Login" asp-route-returnurl="@ViewData["ReturnUrl"]" method="post" class="form-horizontal" role="form"> |
|||
<h4>Use a local account to log in.</h4> |
|||
<hr /> |
|||
<div asp-validation-summary="ValidationSummary.All" class="text-danger"></div> |
|||
<div class="form-group"> |
|||
<label asp-for="Email" class="col-md-2 control-label"></label> |
|||
<div class="col-md-10"> |
|||
<input asp-for="Email" class="form-control" /> |
|||
<span asp-validation-for="Email" class="text-danger"></span> |
|||
</div> |
|||
</div> |
|||
<div class="form-group"> |
|||
<label asp-for="Password" class="col-md-2 control-label"></label> |
|||
<div class="col-md-10"> |
|||
<input asp-for="Password" class="form-control" /> |
|||
<span asp-validation-for="Password" class="text-danger"></span> |
|||
</div> |
|||
</div> |
|||
<div class="form-group"> |
|||
<div class="col-md-offset-2 col-md-10"> |
|||
<div class="checkbox"> |
|||
<input asp-for="RememberMe" /> |
|||
<label asp-for="RememberMe"></label> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<div class="form-group"> |
|||
<div class="col-md-offset-2 col-md-10"> |
|||
<button type="submit" class="btn btn-default">Log in</button> |
|||
</div> |
|||
</div> |
|||
<p> |
|||
<a asp-action="Register" asp-route-returnUrl="@ViewData["ReturnUrl"]">Register as a new user?</a> |
|||
</p> |
|||
<p> |
|||
<a asp-action="ForgotPassword">Forgot your password?</a> |
|||
</p> |
|||
</form> |
|||
</section> |
|||
</div> |
|||
<div class="col-md-4"> |
|||
<section> |
|||
<h4>Use another service to log in.</h4> |
|||
<hr /> |
|||
@{ |
|||
var loginProviders = SignInManager.GetExternalAuthenticationSchemes().ToList(); |
|||
if (loginProviders.Count == 0) |
|||
{ |
|||
<div> |
|||
<p> |
|||
There are no external authentication services configured. See <a href="http://go.microsoft.com/fwlink/?LinkID=532715">this article</a> |
|||
for details on setting up this ASP.NET application to support logging in via external services. |
|||
</p> |
|||
</div> |
|||
} |
|||
else |
|||
{ |
|||
<form asp-controller="Account" asp-action="ExternalLogin" asp-route-returnurl="@ViewData["ReturnUrl"]" method="post" class="form-horizontal" role="form"> |
|||
<div> |
|||
<p> |
|||
@foreach (var provider in loginProviders) |
|||
{ |
|||
<button type="submit" class="btn btn-default" name="provider" value="@provider.AuthenticationScheme" title="Log in using your @provider.DisplayName account">@provider.AuthenticationScheme</button> |
|||
} |
|||
</p> |
|||
</div> |
|||
</form> |
|||
} |
|||
} |
|||
</section> |
|||
</div> |
|||
</div> |
|||
|
|||
@section Scripts { |
|||
@{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); } |
|||
} |
|||
@ -0,0 +1,42 @@ |
|||
@model RegisterViewModel |
|||
@{ |
|||
ViewData["Title"] = "Register"; |
|||
} |
|||
|
|||
<h2>@ViewData["Title"].</h2> |
|||
|
|||
<form asp-controller="Account" asp-action="Register" asp-route-returnUrl="@ViewData["returnUrl"]" method="post" class="form-horizontal" role="form"> |
|||
<h4>Create a new account.</h4> |
|||
<hr /> |
|||
<div asp-validation-summary="ValidationSummary.All" class="text-danger"></div> |
|||
<div class="form-group"> |
|||
<label asp-for="Email" class="col-md-2 control-label"></label> |
|||
<div class="col-md-10"> |
|||
<input asp-for="Email" class="form-control" /> |
|||
<span asp-validation-for="Email" class="text-danger"></span> |
|||
</div> |
|||
</div> |
|||
<div class="form-group"> |
|||
<label asp-for="Password" class="col-md-2 control-label"></label> |
|||
<div class="col-md-10"> |
|||
<input asp-for="Password" class="form-control" /> |
|||
<span asp-validation-for="Password" class="text-danger"></span> |
|||
</div> |
|||
</div> |
|||
<div class="form-group"> |
|||
<label asp-for="ConfirmPassword" class="col-md-2 control-label"></label> |
|||
<div class="col-md-10"> |
|||
<input asp-for="ConfirmPassword" class="form-control" /> |
|||
<span asp-validation-for="ConfirmPassword" class="text-danger"></span> |
|||
</div> |
|||
</div> |
|||
<div class="form-group"> |
|||
<div class="col-md-offset-2 col-md-10"> |
|||
<button type="submit" class="btn btn-default">Register</button> |
|||
</div> |
|||
</div> |
|||
</form> |
|||
|
|||
@section Scripts { |
|||
@{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); } |
|||
} |
|||
@ -0,0 +1,43 @@ |
|||
@model ResetPasswordViewModel |
|||
@{ |
|||
ViewData["Title"] = "Reset password"; |
|||
} |
|||
|
|||
<h2>@ViewData["Title"].</h2> |
|||
|
|||
<form asp-controller="Account" asp-action="ResetPassword" method="post" class="form-horizontal" role="form"> |
|||
<h4>Reset your password.</h4> |
|||
<hr /> |
|||
<div asp-validation-summary="ValidationSummary.All" class="text-danger"></div> |
|||
<input asp-for="Code" type="hidden" /> |
|||
<div class="form-group"> |
|||
<label asp-for="Email" class="col-md-2 control-label"></label> |
|||
<div class="col-md-10"> |
|||
<input asp-for="Email" class="form-control" /> |
|||
<span asp-validation-for="Email" class="text-danger"></span> |
|||
</div> |
|||
</div> |
|||
<div class="form-group"> |
|||
<label asp-for="Password" class="col-md-2 control-label"></label> |
|||
<div class="col-md-10"> |
|||
<input asp-for="Password" class="form-control" /> |
|||
<span asp-validation-for="Password" class="text-danger"></span> |
|||
</div> |
|||
</div> |
|||
<div class="form-group"> |
|||
<label asp-for="ConfirmPassword" class="col-md-2 control-label"></label> |
|||
<div class="col-md-10"> |
|||
<input asp-for="ConfirmPassword" class="form-control" /> |
|||
<span asp-validation-for="ConfirmPassword" class="text-danger"></span> |
|||
</div> |
|||
</div> |
|||
<div class="form-group"> |
|||
<div class="col-md-offset-2 col-md-10"> |
|||
<button type="submit" class="btn btn-default">Reset</button> |
|||
</div> |
|||
</div> |
|||
</form> |
|||
|
|||
@section Scripts { |
|||
@{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); } |
|||
} |
|||
@ -0,0 +1,8 @@ |
|||
@{ |
|||
ViewData["Title"] = "Reset password confirmation"; |
|||
} |
|||
|
|||
<h1>@ViewData["Title"].</h1> |
|||
<p> |
|||
Your password has been reset. Please <a asp-controller="Account" asp-action="Login">Click here to log in</a>. |
|||
</p> |
|||
@ -0,0 +1,21 @@ |
|||
@model SendCodeViewModel |
|||
@{ |
|||
ViewData["Title"] = "Send Verification Code"; |
|||
} |
|||
|
|||
<h2>@ViewData["Title"].</h2> |
|||
|
|||
<form asp-controller="Account" asp-action="SendCode" asp-route-returnurl="@Model.ReturnUrl" method="post" class="form-horizontal" role="form"> |
|||
<input asp-for="RememberMe" type="hidden" /> |
|||
<div class="row"> |
|||
<div class="col-md-8"> |
|||
Select Two-Factor Authentication Provider: |
|||
<select asp-for="SelectedProvider" asp-items="Model.Providers"></select> |
|||
<button type="submit" class="btn btn-default">Submit</button> |
|||
</div> |
|||
</div> |
|||
</form> |
|||
|
|||
@section Scripts { |
|||
@{await Html.RenderPartialAsync("_ValidationScriptsPartial"); } |
|||
} |
|||
@ -0,0 +1,38 @@ |
|||
@model VerifyCodeViewModel |
|||
@{ |
|||
ViewData["Title"] = "Verify"; |
|||
} |
|||
|
|||
<h2>@ViewData["Title"].</h2> |
|||
|
|||
<form asp-controller="Account" asp-action="VerifyCode" asp-route-returnurl="@ViewData["ReturnUrl"]" method="post" class="form-horizontal" role="form"> |
|||
<div asp-validation-summary="ValidationSummary.All" class="text-danger"></div> |
|||
<input asp-for="Provider" type="hidden" /> |
|||
<input asp-for="RememberMe" type="hidden" /> |
|||
<h4>@ViewData["Status"]</h4> |
|||
<hr /> |
|||
<div class="form-group"> |
|||
<label asp-for="Code" class="col-md-2 control-label"></label> |
|||
<div class="col-md-10"> |
|||
<input asp-for="Code" class="form-control" /> |
|||
<span asp-validation-for="Code" class="text-danger"></span> |
|||
</div> |
|||
</div> |
|||
<div class="form-group"> |
|||
<div class="col-md-offset-2 col-md-10"> |
|||
<div class="checkbox"> |
|||
<input asp-for="RememberBrowser" /> |
|||
<label asp-for="RememberBrowser"></label> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<div class="form-group"> |
|||
<div class="col-md-offset-2 col-md-10"> |
|||
<button type="submit" class="btn btn-default">Submit</button> |
|||
</div> |
|||
</div> |
|||
</form> |
|||
|
|||
@section Scripts { |
|||
@{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); } |
|||
} |
|||
@ -0,0 +1,7 @@ |
|||
@{ |
|||
ViewData["Title"] = "About"; |
|||
} |
|||
<h2>@ViewData["Title"].</h2> |
|||
<h3>@ViewData["Message"]</h3> |
|||
|
|||
<p>Use this area to provide additional information.</p> |
|||
@ -0,0 +1,17 @@ |
|||
@{ |
|||
ViewData["Title"] = "Contact"; |
|||
} |
|||
<h2>@ViewData["Title"].</h2> |
|||
<h3>@ViewData["Message"]</h3> |
|||
|
|||
<address> |
|||
One Microsoft Way<br /> |
|||
Redmond, WA 98052-6399<br /> |
|||
<abbr title="Phone">P:</abbr> |
|||
425.555.0100 |
|||
</address> |
|||
|
|||
<address> |
|||
<strong>Support:</strong> <a href="mailto:Support@example.com">Support@example.com</a><br /> |
|||
<strong>Marketing:</strong> <a href="mailto:Marketing@example.com">Marketing@example.com</a> |
|||
</address> |
|||
@ -0,0 +1,104 @@ |
|||
@{ |
|||
ViewData["Title"] = "Home Page"; |
|||
} |
|||
|
|||
<div id="myCarousel" class="carousel slide" data-ride="carousel" data-interval="6000"> |
|||
<ol class="carousel-indicators"> |
|||
<li data-target="#myCarousel" data-slide-to="0" class="active"></li> |
|||
<li data-target="#myCarousel" data-slide-to="1"></li> |
|||
<li data-target="#myCarousel" data-slide-to="2"></li> |
|||
<li data-target="#myCarousel" data-slide-to="3"></li> |
|||
</ol> |
|||
<div class="carousel-inner" role="listbox"> |
|||
<div class="item active"> |
|||
<img src="~/images/ASP-NET-Banners-01.png" alt="ASP.NET" class="img-responsive" /> |
|||
<div class="container"> |
|||
<div class="carousel-caption"> |
|||
<p> |
|||
Learn how to build ASP.NET apps that can run anywhere. |
|||
<a class="btn btn-default btn-default" href="http://go.microsoft.com/fwlink/?LinkID=525028&clcid=0x409"> |
|||
Learn More |
|||
</a> |
|||
</p> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<div class="item"> |
|||
<img src="~/images/Banner-02-VS.png" alt="Visual Studio" class="img-responsive" /> |
|||
<div class="container"> |
|||
<div class="carousel-caption"> |
|||
<p> |
|||
There are powerful new features in Visual Studio for building modern web apps. |
|||
<a class="btn btn-default btn-default" href="http://go.microsoft.com/fwlink/?LinkID=525030&clcid=0x409"> |
|||
Learn More |
|||
</a> |
|||
</p> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<div class="item"> |
|||
<img src="~/images/ASP-NET-Banners-02.png" alt="Package Management" class="img-responsive" /> |
|||
<div class="container"> |
|||
<div class="carousel-caption"> |
|||
<p> |
|||
Bring in libraries from NuGet, Bower, and npm, and automate tasks using Grunt or Gulp. |
|||
<a class="btn btn-default btn-default" href="http://go.microsoft.com/fwlink/?LinkID=525029&clcid=0x409"> |
|||
Learn More |
|||
</a> |
|||
</p> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<div class="item"> |
|||
<img src="~/images/Banner-01-Azure.png" alt="Microsoft Azure" class="img-responsive" /> |
|||
<div class="container"> |
|||
<div class="carousel-caption"> |
|||
<p> |
|||
Learn how Microsoft's Azure cloud platform allows you to build, deploy, and scale web apps. |
|||
<a class="btn btn-default btn-default" href="http://go.microsoft.com/fwlink/?LinkID=525027&clcid=0x409"> |
|||
Learn More |
|||
</a> |
|||
</p> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
|
|||
<div class="row"> |
|||
<div class="col-md-3"> |
|||
<h2>Application uses</h2> |
|||
<ul> |
|||
<li>Sample pages using ASP.NET 5 (MVC 6)</li> |
|||
<li><a href="http://go.microsoft.com/fwlink/?LinkId=518007">Gulp</a> and <a href="http://go.microsoft.com/fwlink/?LinkId=518004">Bower</a> for managing client-side resources</li> |
|||
<li>Theming using <a href="http://go.microsoft.com/fwlink/?LinkID=398939">Bootstrap</a></li> |
|||
</ul> |
|||
</div> |
|||
<div class="col-md-3"> |
|||
<h2>New concepts</h2> |
|||
<ul> |
|||
<li><a href="http://go.microsoft.com/fwlink/?LinkId=518008">Conceptual overview of ASP.NET 5</a></li> |
|||
<li><a href="http://go.microsoft.com/fwlink/?LinkId=518008">Fundamentals in ASP.NET 5</a></li> |
|||
<li><a href="http://go.microsoft.com/fwlink/?LinkID=517849">Client-Side Development using npm, Bower and Gulp</a></li> |
|||
<li><a href="http://go.microsoft.com/fwlink/?LinkID=517850">Develop on different platforms</a></li> |
|||
</ul> |
|||
</div> |
|||
<div class="col-md-3"> |
|||
<h2>Customize app</h2> |
|||
<ul> |
|||
<li><a href="http://go.microsoft.com/fwlink/?LinkID=398600">Add Controllers and Views</a></li> |
|||
<li><a href="http://go.microsoft.com/fwlink/?LinkID=398602">Add Data using EntityFramework</a></li> |
|||
<li><a href="http://go.microsoft.com/fwlink/?LinkID=398603">Add Authentication using Identity</a></li> |
|||
<li><a href="http://go.microsoft.com/fwlink/?LinkID=517848">Manage client-side packages using Bower/ Gulp</a></li> |
|||
</ul> |
|||
</div> |
|||
<div class="col-md-3"> |
|||
<h2>Deploy</h2> |
|||
<ul> |
|||
<li><a href="http://go.microsoft.com/fwlink/?LinkID=517851">Run your app locally</a></li> |
|||
<li><a href="http://go.microsoft.com/fwlink/?LinkID=517852">Run your app on .NET Core</a></li> |
|||
<li><a href="http://go.microsoft.com/fwlink/?LinkID=517853">Run commands in your app</a></li> |
|||
<li><a href="http://go.microsoft.com/fwlink/?LinkID=398609">Publish to Microsoft Azure Web Apps</a></li> |
|||
</ul> |
|||
</div> |
|||
</div> |
|||
@ -0,0 +1,27 @@ |
|||
@model AddPhoneNumberViewModel |
|||
@{ |
|||
ViewData["Title"] = "Add Phone Number"; |
|||
} |
|||
|
|||
<h2>@ViewData["Title"].</h2> |
|||
<form asp-controller="Manage" asp-action="AddPhoneNumber" method="post" class="form-horizontal" role="form"> |
|||
<h4>Add a phone number.</h4> |
|||
<hr /> |
|||
<div asp-validation-summary="ValidationSummary.All" class="text-danger"></div> |
|||
<div class="form-group"> |
|||
<label asp-for="PhoneNumber" class="col-md-2 control-label"></label> |
|||
<div class="col-md-10"> |
|||
<input asp-for="PhoneNumber" class="form-control" /> |
|||
<span asp-validation-for="PhoneNumber" class="text-danger"></span> |
|||
</div> |
|||
</div> |
|||
<div class="form-group"> |
|||
<div class="col-md-offset-2 col-md-10"> |
|||
<button type="submit" class="btn btn-default">Send verification code</button> |
|||
</div> |
|||
</div> |
|||
</form> |
|||
|
|||
@section Scripts { |
|||
@{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); } |
|||
} |
|||
@ -0,0 +1,42 @@ |
|||
@model ChangePasswordViewModel |
|||
@{ |
|||
ViewData["Title"] = "Change Password"; |
|||
} |
|||
|
|||
<h2>@ViewData["Title"].</h2> |
|||
|
|||
<form asp-controller="Manage" asp-action="ChangePassword" method="post" class="form-horizontal" role="form"> |
|||
<h4>Change Password Form</h4> |
|||
<hr /> |
|||
<div asp-validation-summary="ValidationSummary.All" class="text-danger"></div> |
|||
<div class="form-group"> |
|||
<label asp-for="OldPassword" class="col-md-2 control-label"></label> |
|||
<div class="col-md-10"> |
|||
<input asp-for="OldPassword" class="form-control" /> |
|||
<span asp-validation-for="OldPassword" class="text-danger"></span> |
|||
</div> |
|||
</div> |
|||
<div class="form-group"> |
|||
<label asp-for="NewPassword" class="col-md-2 control-label"></label> |
|||
<div class="col-md-10"> |
|||
<input asp-for="NewPassword" class="form-control" /> |
|||
<span asp-validation-for="NewPassword" class="text-danger"></span> |
|||
</div> |
|||
</div> |
|||
<div class="form-group"> |
|||
<label asp-for="ConfirmPassword" class="col-md-2 control-label"></label> |
|||
<div class="col-md-10"> |
|||
<input asp-for="ConfirmPassword" class="form-control" /> |
|||
<span asp-validation-for="ConfirmPassword" class="text-danger"></span> |
|||
</div> |
|||
</div> |
|||
<div class="form-group"> |
|||
<div class="col-md-offset-2 col-md-10"> |
|||
<button type="submit" class="btn btn-default">Change password</button> |
|||
</div> |
|||
</div> |
|||
</form> |
|||
|
|||
@section Scripts { |
|||
@{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); } |
|||
} |
|||
@ -0,0 +1,79 @@ |
|||
@model IndexViewModel |
|||
@{ |
|||
ViewData["Title"] = "Manage your account"; |
|||
} |
|||
|
|||
<h2>@ViewData["Title"].</h2> |
|||
<p class="text-success">@ViewData["StatusMessage"]</p> |
|||
<div> |
|||
<h4>Change your account settings</h4> |
|||
<hr /> |
|||
<dl class="dl-horizontal"> |
|||
<dt>Password:</dt> |
|||
<dd> |
|||
[ |
|||
@if (Model.HasPassword) |
|||
{ |
|||
<a asp-controller="Manage" asp-action="ChangePassword">Change</a> |
|||
} |
|||
else |
|||
{ |
|||
<a asp-controller="Manage" asp-action="SetPassword">Create</a> |
|||
} |
|||
] |
|||
</dd> |
|||
<dt>External Logins:</dt> |
|||
<dd> |
|||
|
|||
@Model.Logins.Count [<a asp-controller="Manage" asp-action="ManageLogins">Manage</a>] |
|||
</dd> |
|||
|
|||
|
|||
<dt>Phone Number:</dt> |
|||
<dd> |
|||
<p> |
|||
Phone Numbers can used as a second factor of verification in two-factor authentication. |
|||
See <a href="http://go.microsoft.com/fwlink/?LinkID=532713">this article</a> |
|||
for details on setting up this ASP.NET application to support two-factor authentication using SMS. |
|||
</p> |
|||
@*@(Model.PhoneNumber ?? "None") [ |
|||
@if (Model.PhoneNumber != null) |
|||
{ |
|||
<a asp-controller="Manage" asp-action="AddPhoneNumber">Change</a> |
|||
@: | |
|||
<a asp-controller="Manage" asp-action="RemovePhoneNumber">Remove</a> |
|||
} |
|||
else |
|||
{ |
|||
<a asp-controller="Manage" asp-action="AddPhoneNumber">Add</a> |
|||
} |
|||
]*@ |
|||
</dd> |
|||
|
|||
<dt>Two-Factor Authentication:</dt> |
|||
<dd> |
|||
<p> |
|||
There are no two-factor authentication providers configured. See <a href="http://go.microsoft.com/fwlink/?LinkID=532713">this article</a> |
|||
for setting up this application to support two-factor authentication. |
|||
</p> |
|||
@*@if (Model.TwoFactor) |
|||
{ |
|||
<form asp-controller="Manage" asp-action="DisableTwoFactorAuthentication" method="post" class="form-horizontal" role="form"> |
|||
<text> |
|||
Enabled |
|||
<button type="submit" class="btn btn-link">Disable</button> |
|||
</text> |
|||
</form> |
|||
} |
|||
else |
|||
{ |
|||
<form asp-controller="Manage" asp-action="EnableTwoFactorAuthentication" method="post" class="form-horizontal" role="form"> |
|||
<text> |
|||
Disabled |
|||
<button type="submit" class="btn btn-link">Enable</button> |
|||
</text> |
|||
</form> |
|||
}*@ |
|||
</dd> |
|||
</dl> |
|||
</div> |
|||
@ -0,0 +1,54 @@ |
|||
@model ManageLoginsViewModel |
|||
@using Microsoft.AspNet.Http.Authentication |
|||
@{ |
|||
ViewData["Title"] = "Manage your external logins"; |
|||
} |
|||
|
|||
<h2>@ViewData["Title"].</h2> |
|||
|
|||
<p class="text-success">@ViewData["StatusMessage"]</p> |
|||
@if (Model.CurrentLogins.Count > 0) |
|||
{ |
|||
<h4>Registered Logins</h4> |
|||
<table class="table"> |
|||
<tbody> |
|||
@foreach (var account in Model.CurrentLogins) |
|||
{ |
|||
<tr> |
|||
<td>@account.LoginProvider</td> |
|||
<td> |
|||
@if ((bool)ViewData["ShowRemoveButton"]) |
|||
{ |
|||
<form asp-controller="Manage" asp-action="RemoveLogin" method="post" class="form-horizontal" role="form"> |
|||
<div> |
|||
<input asp-for="@account.LoginProvider" type="hidden" /> |
|||
<input asp-for="@account.ProviderKey" type="hidden" /> |
|||
<input type="submit" class="btn btn-default" value="Remove" title="Remove this @account.LoginProvider login from your account" /> |
|||
</div> |
|||
</form> |
|||
} |
|||
else |
|||
{ |
|||
@: |
|||
} |
|||
</td> |
|||
</tr> |
|||
} |
|||
</tbody> |
|||
</table> |
|||
} |
|||
@if (Model.OtherLogins.Count > 0) |
|||
{ |
|||
<h4>Add another service to log in.</h4> |
|||
<hr /> |
|||
<form asp-controller="Manage" asp-action="LinkLogin" method="post" class="form-horizontal" role="form"> |
|||
<div id="socialLoginList"> |
|||
<p> |
|||
@foreach (var provider in Model.OtherLogins) |
|||
{ |
|||
<button type="submit" class="btn btn-default" name="provider" value="@provider.AuthenticationScheme" title="Log in using your @provider.DisplayName account">@provider.AuthenticationScheme</button> |
|||
} |
|||
</p> |
|||
</div> |
|||
</form> |
|||
} |
|||
@ -0,0 +1,35 @@ |
|||
@model ICollection<Microsoft.AspNet.Identity.UserLoginInfo> |
|||
@{ |
|||
ViewData["Title"] = "Remove Login"; |
|||
} |
|||
|
|||
@if (Model.Count > 0) |
|||
{ |
|||
<h4>Registered Logins</h4> |
|||
<table class="table"> |
|||
<tbody> |
|||
@foreach (var account in Model) |
|||
{ |
|||
<tr> |
|||
<td>@account.LoginProvider</td> |
|||
<td> |
|||
@if ((bool)ViewData["ShowRemoveButton"]) |
|||
{ |
|||
<form asp-controller="Manage" asp-action="RemoveLogin" asp-route-returnurl="@ViewData["ReturnUrl"]" method="post" class="form-horizontal" role="form"> |
|||
<div> |
|||
<input asp-for="@account.LoginProvider" type="hidden" /> |
|||
<input asp-for="@account.ProviderKey" type="hidden" /> |
|||
<input type="submit" class="btn btn-default" value="Remove" title="Remove this @account.LoginProvider login from your account" /> |
|||
</div> |
|||
</form> |
|||
} |
|||
else |
|||
{ |
|||
@: |
|||
} |
|||
</td> |
|||
</tr> |
|||
} |
|||
</tbody> |
|||
</table> |
|||
} |
|||
@ -0,0 +1,38 @@ |
|||
@model SetPasswordViewModel |
|||
@{ |
|||
ViewData["Title"] = "Set Password"; |
|||
} |
|||
|
|||
<p class="text-info"> |
|||
You do not have a local username/password for this site. Add a local |
|||
account so you can log in without an external login. |
|||
</p> |
|||
|
|||
<form asp-controller="Manage" asp-action="SetPassword" asp-route-returnurl="@ViewData["ReturnUrl"]" method="post" class="form-horizontal" role="form"> |
|||
<h4>Set your password</h4> |
|||
<hr /> |
|||
<div asp-validation-summary="ValidationSummary.All" class="text-danger"></div> |
|||
<div class="form-group"> |
|||
<label asp-for="NewPassword" class="col-md-2 control-label"></label> |
|||
<div class="col-md-10"> |
|||
<input asp-for="NewPassword" class="form-control" /> |
|||
<span asp-validation-for="NewPassword" class="text-danger"></span> |
|||
</div> |
|||
</div> |
|||
<div class="form-group"> |
|||
<label asp-for="ConfirmPassword" class="col-md-2 control-label"></label> |
|||
<div class="col-md-10"> |
|||
<input asp-for="ConfirmPassword" class="form-control" /> |
|||
<span asp-validation-for="ConfirmPassword" class="text-danger"></span> |
|||
</div> |
|||
</div> |
|||
<div class="form-group"> |
|||
<div class="col-md-offset-2 col-md-10"> |
|||
<button type="submit" class="btn btn-default">Set password</button> |
|||
</div> |
|||
</div> |
|||
</form> |
|||
|
|||
@section Scripts { |
|||
@{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); } |
|||
} |
|||
@ -0,0 +1,30 @@ |
|||
@model VerifyPhoneNumberViewModel |
|||
@{ |
|||
ViewData["Title"] = "Verify Phone Number"; |
|||
} |
|||
|
|||
<h2>@ViewData["Title"].</h2> |
|||
|
|||
<form asp-controller="Manage" asp-action="VerifyPhoneNumber" asp-route-returnurl="@ViewData["ReturnUrl"]" method="post" class="form-horizontal" role="form"> |
|||
<input asp-for="PhoneNumber" type="hidden" /> |
|||
<h4>Add a phone number.</h4> |
|||
<h5>@ViewData["Status"]</h5> |
|||
<hr /> |
|||
<div asp-validation-summary="ValidationSummary.All" class="text-danger"></div> |
|||
<div class="form-group"> |
|||
<label asp-for="Code" class="col-md-2 control-label"></label> |
|||
<div class="col-md-10"> |
|||
<input asp-for="Code" class="form-control" /> |
|||
<span asp-validation-for="Code" class="text-danger"></span> |
|||
</div> |
|||
</div> |
|||
<div class="form-group"> |
|||
<div class="col-md-offset-2 col-md-10"> |
|||
<button type="submit" class="btn btn-default">Submit</button> |
|||
</div> |
|||
</div> |
|||
</form> |
|||
|
|||
@section Scripts { |
|||
@{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); } |
|||
} |
|||
@ -0,0 +1,6 @@ |
|||
@{ |
|||
ViewData["Title"] = "Error"; |
|||
} |
|||
|
|||
<h1 class="text-danger">Error.</h1> |
|||
<h2 class="text-danger">An error occurred while processing your request.</h2> |
|||
@ -0,0 +1,81 @@ |
|||
<!DOCTYPE html> |
|||
<html> |
|||
<head> |
|||
<meta charset="utf-8" /> |
|||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> |
|||
<title>@ViewData["Title"] - Mvc.Server</title> |
|||
|
|||
<environment names="Development"> |
|||
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" /> |
|||
<link rel="stylesheet" href="~/lib/bootstrap-touch-carousel/dist/css/bootstrap-touch-carousel.css" /> |
|||
<link rel="stylesheet" href="~/css/site.css" /> |
|||
</environment> |
|||
<environment names="Staging,Production"> |
|||
<link rel="stylesheet" href="https://ajax.aspnetcdn.com/ajax/bootstrap/3.0.0/css/bootstrap.min.css" |
|||
asp-fallback-href="~/lib/bootstrap/dist/css/bootstrap.min.css" |
|||
asp-fallback-test-class="hidden" asp-fallback-test-property="visibility" asp-fallback-test-value="hidden" /> |
|||
<link rel="stylesheet" href="https://ajax.aspnetcdn.com/ajax/bootstrap-touch-carousel/0.8.0/css/bootstrap-touch-carousel.css" |
|||
asp-fallback-href="~/lib/bootstrap-touch-carousel/css/bootstrap-touch-carousel.css" |
|||
asp-fallback-test-class="carousel-caption" asp-fallback-test-property="display" asp-fallback-test-value="none" /> |
|||
<link rel="stylesheet" href="~/css/site.css" asp-append-version="true" /> |
|||
</environment> |
|||
</head> |
|||
<body> |
|||
<div class="navbar navbar-inverse navbar-fixed-top"> |
|||
<div class="container"> |
|||
<div class="navbar-header"> |
|||
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse"> |
|||
<span class="icon-bar"></span> |
|||
<span class="icon-bar"></span> |
|||
<span class="icon-bar"></span> |
|||
</button> |
|||
<a asp-controller="Home" asp-action="Index" class="navbar-brand">Mvc.Server</a> |
|||
</div> |
|||
<div class="navbar-collapse collapse"> |
|||
<ul class="nav navbar-nav"> |
|||
<li><a asp-controller="Home" asp-action="Index">Home</a></li> |
|||
<li><a asp-controller="Home" asp-action="About">About</a></li> |
|||
<li><a asp-controller="Home" asp-action="Contact">Contact</a></li> |
|||
</ul> |
|||
@await Html.PartialAsync("_LoginPartial") |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<div class="container body-content"> |
|||
@RenderBody() |
|||
<hr /> |
|||
<footer> |
|||
<p>© 2015 - Mvc.Server</p> |
|||
</footer> |
|||
</div> |
|||
|
|||
<environment names="Development"> |
|||
<script src="~/lib/jquery/dist/jquery.js"></script> |
|||
<script src="~/lib/bootstrap/dist/js/bootstrap.js"></script> |
|||
<script src="~/lib/hammer.js/hammer.js"></script> |
|||
<script src="~/lib/bootstrap-touch-carousel/dist/js/bootstrap-touch-carousel.js"></script> |
|||
<script src="~/js/site.js" asp-append-version="true"></script> |
|||
</environment> |
|||
<environment names="Staging,Production"> |
|||
<script src="https://ajax.aspnetcdn.com/ajax/jquery/jquery-2.1.4.min.js" |
|||
asp-fallback-src="~/lib/jquery/dist/jquery.min.js" |
|||
asp-fallback-test="window.jQuery"> |
|||
</script> |
|||
<script src="https://ajax.aspnetcdn.com/ajax/bootstrap/3.0.0/bootstrap.min.js" |
|||
asp-fallback-src="~/lib/bootstrap/dist/js/bootstrap.min.js" |
|||
asp-fallback-test="window.jQuery && window.jQuery.fn && window.jQuery.fn.modal"> |
|||
</script> |
|||
<script src="https://ajax.aspnetcdn.com/ajax/hammer.js/2.0.4/hammer.min.js" |
|||
asp-fallback-src="~/lib/hammer.js/hammer.js" |
|||
asp-fallback-test="window.Hammer"> |
|||
</script> |
|||
<script src="https://ajax.aspnetcdn.com/ajax/bootstrap-touch-carousel/0.8.0/js/bootstrap-touch-carousel.js" |
|||
asp-fallback-src="~/lib/bootstrap-touch-carousel/dist/js/bootstrap-touch-carousel.js" |
|||
asp-fallback-test="window.Hammer && window.Hammer.Instance"> |
|||
</script> |
|||
<script src="~/js/site.js" asp-append-version="true"></script> |
|||
</environment> |
|||
|
|||
@RenderSection("scripts", required: false) |
|||
</body> |
|||
</html> |
|||
@ -0,0 +1,20 @@ |
|||
@using System.Security.Claims |
|||
|
|||
@if (User.Identity.IsAuthenticated) |
|||
{ |
|||
<form asp-controller="Account" asp-action="LogOff" method="post" id="logoutForm" class="navbar-right"> |
|||
<ul class="nav navbar-nav navbar-right"> |
|||
<li> |
|||
<a asp-controller="Manage" asp-action="Index" title="Manage">Hello @User.GetUserName()!</a> |
|||
</li> |
|||
<li><a href="javascript:document.getElementById('logoutForm').submit()">Log off</a></li> |
|||
</ul> |
|||
</form> |
|||
} |
|||
else |
|||
{ |
|||
<ul class="nav navbar-nav navbar-right"> |
|||
<li><a asp-controller="Account" asp-action="Register">Register</a></li> |
|||
<li><a asp-controller="Account" asp-action="Login">Log in</a></li> |
|||
</ul> |
|||
} |
|||
@ -0,0 +1,14 @@ |
|||
<environment names="Development"> |
|||
<script src="~/lib/jquery-validation/jquery.validate.js"></script> |
|||
<script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js"></script> |
|||
</environment> |
|||
<environment names="Staging,Production"> |
|||
<script src="https://ajax.aspnetcdn.com/ajax/jquery.validate/1.11.1/jquery.validate.min.js" |
|||
asp-fallback-src="~/lib/jquery-validation/jquery.validate.js" |
|||
asp-fallback-test="window.jquery && window.jquery.validator"> |
|||
</script> |
|||
<script src="https://ajax.aspnetcdn.com/ajax/mvc/5.2.3/jquery.validate.unobtrusive.min.js" |
|||
asp-fallback-src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js" |
|||
asp-fallback-test="window.jquery && window.jquery.validator && window.jquery.validator.unobtrusive"> |
|||
</script> |
|||
</environment> |
|||
@ -0,0 +1,6 @@ |
|||
@using Mvc.Server |
|||
@using Mvc.Server.Models |
|||
@using Mvc.Server.ViewModels.Account |
|||
@using Mvc.Server.ViewModels.Manage |
|||
@using Microsoft.AspNet.Identity |
|||
@addTagHelper "*, Microsoft.AspNet.Mvc.TagHelpers" |
|||
@ -0,0 +1,3 @@ |
|||
@{ |
|||
Layout = "_Layout"; |
|||
} |
|||
@ -0,0 +1,30 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
|
|||
<!-- For more information on using web.config transformation visit http://go.microsoft.com/fwlink/?LinkId=125889 --> |
|||
|
|||
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform"> |
|||
<!-- |
|||
In the example below, the "SetAttributes" transform will change the value of |
|||
"connectionString" to use "ReleaseSQLServer" only when the "Match" locator |
|||
finds an attribute "name" that has a value of "MyDB". |
|||
|
|||
<connectionStrings> |
|||
<add name="MyDB" |
|||
connectionString="Data Source=ReleaseSQLServer;Initial Catalog=MyReleaseDB;Integrated Security=True" |
|||
xdt:Transform="SetAttributes" xdt:Locator="Match(name)"/> |
|||
</connectionStrings> |
|||
--> |
|||
<system.web> |
|||
<!-- |
|||
In the example below, the "Replace" transform will replace the entire |
|||
<customErrors> section of your web.config file. |
|||
Note that because there is only one customErrors section under the |
|||
<system.web> node, there is no need to use the "xdt:Locator" attribute. |
|||
|
|||
<customErrors defaultRedirect="GenericError.htm" |
|||
mode="RemoteOnly" xdt:Transform="Replace"> |
|||
<error statusCode="500" redirect="InternalError.htm"/> |
|||
</customErrors> |
|||
--> |
|||
</system.web> |
|||
</configuration> |
|||
@ -0,0 +1,31 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
|
|||
<!-- For more information on using web.config transformation visit http://go.microsoft.com/fwlink/?LinkId=125889 --> |
|||
|
|||
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform"> |
|||
<!-- |
|||
In the example below, the "SetAttributes" transform will change the value of |
|||
"connectionString" to use "ReleaseSQLServer" only when the "Match" locator |
|||
finds an attribute "name" that has a value of "MyDB". |
|||
|
|||
<connectionStrings> |
|||
<add name="MyDB" |
|||
connectionString="Data Source=ReleaseSQLServer;Initial Catalog=MyReleaseDB;Integrated Security=True" |
|||
xdt:Transform="SetAttributes" xdt:Locator="Match(name)"/> |
|||
</connectionStrings> |
|||
--> |
|||
<system.web> |
|||
<compilation xdt:Transform="RemoveAttributes(debug)" /> |
|||
<!-- |
|||
In the example below, the "Replace" transform will replace the entire |
|||
<customErrors> section of your web.config file. |
|||
Note that because there is only one customErrors section under the |
|||
<system.web> node, there is no need to use the "xdt:Locator" attribute. |
|||
|
|||
<customErrors defaultRedirect="GenericError.htm" |
|||
mode="RemoteOnly" xdt:Transform="Replace"> |
|||
<error statusCode="500" redirect="InternalError.htm"/> |
|||
</customErrors> |
|||
--> |
|||
</system.web> |
|||
</configuration> |
|||
@ -0,0 +1,10 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<!-- |
|||
For more information on how to configure your ASP.NET application, please visit |
|||
http://go.microsoft.com/fwlink/?LinkId=169433 |
|||
--> |
|||
<configuration> |
|||
<system.webServer> |
|||
<modules runAllManagedModulesForAllRequests="true"/> |
|||
</system.webServer> |
|||
</configuration> |
|||
@ -0,0 +1,12 @@ |
|||
{ |
|||
"name": "ASP.NET", |
|||
"private": true, |
|||
"dependencies": { |
|||
"bootstrap": "3.0.0", |
|||
"bootstrap-touch-carousel": "0.8.0", |
|||
"hammer.js": "2.0.4", |
|||
"jquery": "2.1.4", |
|||
"jquery-validation": "1.11.1", |
|||
"jquery-validation-unobtrusive": "3.2.2" |
|||
} |
|||
} |
|||
@ -0,0 +1,7 @@ |
|||
{ |
|||
"Data": { |
|||
"DefaultConnection": { |
|||
"ConnectionString": "Server=(localdb)\\mssqllocaldb;Database=aspnet5-openiddict-sample-12340be6-0442-4622-b782-a7412bb7d045;Trusted_Connection=True;MultipleActiveResultSets=true" |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,45 @@ |
|||
/// <binding Clean='clean' />
|
|||
|
|||
var gulp = require("gulp"), |
|||
rimraf = require("rimraf"), |
|||
concat = require("gulp-concat"), |
|||
cssmin = require("gulp-cssmin"), |
|||
uglify = require("gulp-uglify"), |
|||
project = require("./project.json"); |
|||
|
|||
var paths = { |
|||
webroot: "./" + project.webroot + "/" |
|||
}; |
|||
|
|||
paths.js = paths.webroot + "js/**/*.js"; |
|||
paths.minJs = paths.webroot + "js/**/*.min.js"; |
|||
paths.css = paths.webroot + "css/**/*.css"; |
|||
paths.minCss = paths.webroot + "css/**/*.min.css"; |
|||
paths.concatJsDest = paths.webroot + "js/site.min.js"; |
|||
paths.concatCssDest = paths.webroot + "css/site.min.css"; |
|||
|
|||
gulp.task("clean:js", function (cb) { |
|||
rimraf(paths.concatJsDest, cb); |
|||
}); |
|||
|
|||
gulp.task("clean:css", function (cb) { |
|||
rimraf(paths.concatCssDest, cb); |
|||
}); |
|||
|
|||
gulp.task("clean", ["clean:js", "clean:css"]); |
|||
|
|||
gulp.task("min:js", function () { |
|||
gulp.src([paths.js, "!" + paths.minJs], { base: "." }) |
|||
.pipe(concat(paths.concatJsDest)) |
|||
.pipe(uglify()) |
|||
.pipe(gulp.dest(".")); |
|||
}); |
|||
|
|||
gulp.task("min:css", function () { |
|||
gulp.src([paths.css, "!" + paths.minCss]) |
|||
.pipe(concat(paths.concatCssDest)) |
|||
.pipe(cssmin()) |
|||
.pipe(gulp.dest(".")); |
|||
}); |
|||
|
|||
gulp.task("min", ["min:js", "min:css"]); |
|||
@ -0,0 +1,11 @@ |
|||
{ |
|||
"name": "ASP.NET", |
|||
"version": "0.0.0", |
|||
"devDependencies": { |
|||
"gulp": "3.8.11", |
|||
"gulp-concat": "2.5.2", |
|||
"gulp-cssmin": "0.1.7", |
|||
"gulp-uglify": "1.2.0", |
|||
"rimraf": "2.2.8" |
|||
} |
|||
} |
|||
@ -0,0 +1,48 @@ |
|||
{ |
|||
"webroot": "wwwroot", |
|||
|
|||
"version": "1.0.0-beta2-*", |
|||
|
|||
"dependencies": { |
|||
"Microsoft.AspNet.Authentication.Google": "1.0.0-*", |
|||
"Microsoft.AspNet.Authentication.JwtBearer": "1.0.0-*", |
|||
"Microsoft.AspNet.Authentication.Twitter": "1.0.0-*", |
|||
"Microsoft.AspNet.Diagnostics": "1.0.0-*", |
|||
"Microsoft.AspNet.Mvc.TagHelpers": "6.0.0-*", |
|||
"Microsoft.AspNet.Server.Kestrel": "1.0.0-*", |
|||
"Microsoft.AspNet.Server.WebListener": "1.0.0-*", |
|||
"Microsoft.AspNet.StaticFiles": "1.0.0-*", |
|||
|
|||
"Microsoft.Framework.Logging.Console": "1.0.0-*", |
|||
|
|||
"OpenIddict": "1.0.0-*" |
|||
}, |
|||
|
|||
"commands": { |
|||
"kestrel": "Microsoft.AspNet.Hosting --server=Microsoft.AspNet.Server.Kestrel --server.urls=http://localhost:54540", |
|||
"web": "Microsoft.AspNet.Hosting server=Microsoft.AspNet.Server.WebListener server.urls=http://localhost:54540" |
|||
}, |
|||
|
|||
"frameworks": { |
|||
"dnx451": { }, |
|||
"dnxcore50": { } |
|||
}, |
|||
|
|||
"exclude": [ |
|||
"wwwroot", |
|||
"node_modules", |
|||
"bower_components" |
|||
], |
|||
|
|||
"publishExclude": [ |
|||
"node_modules", |
|||
"bower_components", |
|||
"**.xproj", |
|||
"**.user", |
|||
"**.vspscc" |
|||
], |
|||
|
|||
"scripts": { |
|||
"prepublish": [ "npm install", "bower install", "gulp clean", "gulp min" ] |
|||
} |
|||
} |
|||
@ -0,0 +1,3 @@ |
|||
/// <autosync enabled="true" />
|
|||
/// <reference path="../gulpfile.js" />
|
|||
/// <reference path="js/site.js" />
|
|||
@ -0,0 +1,34 @@ |
|||
body { |
|||
padding-top: 50px; |
|||
padding-bottom: 20px; |
|||
} |
|||
|
|||
/* Wrapping element */ |
|||
/* Set some basic padding to keep content from hitting the edges */ |
|||
.body-content { |
|||
padding-left: 15px; |
|||
padding-right: 15px; |
|||
} |
|||
|
|||
/* Set widths on the form inputs since otherwise they're 100% wide */ |
|||
input, |
|||
select, |
|||
textarea { |
|||
max-width: 280px; |
|||
} |
|||
|
|||
/* Carousel */ |
|||
.carousel-caption { |
|||
z-index: 10 !important; |
|||
} |
|||
|
|||
.carousel-caption p { |
|||
font-size: 20px; |
|||
line-height: 1.4; |
|||
} |
|||
|
|||
@media (min-width: 768px) { |
|||
.carousel-caption { |
|||
z-index: 10 !important; |
|||
} |
|||
} |
|||
|
After Width: | Height: | Size: 31 KiB |
|
After Width: | Height: | Size: 8.1 KiB |
|
After Width: | Height: | Size: 8.4 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 12 KiB |
@ -0,0 +1 @@ |
|||
// Write your Javascript code.
|
|||
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue