Improvements in identity, securice basket api, login-logout from mvc application and consume securiced basket.
This commit is contained in:
parent
a939fe7a51
commit
0a344f6cdc
@ -14,7 +14,6 @@ services:
|
||||
ports:
|
||||
- "5100:80"
|
||||
depends_on:
|
||||
- catalog.api
|
||||
- identity.service
|
||||
- basket.api
|
||||
|
||||
@ -31,14 +30,13 @@ services:
|
||||
ports:
|
||||
- "5104:80"
|
||||
depends_on:
|
||||
- catalog.api
|
||||
- basket.api
|
||||
- identity.service
|
||||
|
||||
catalog.api:
|
||||
image: eshop/catalog.api
|
||||
environment:
|
||||
- ConnectionString=Server=catalog.data;Initial Catalog=CatalogData;User Id=sa;Password=Pass@word
|
||||
- ConnectionString=Server=catalog.data;Database=CatalogDB;User Id=sa;Password=Pass@word
|
||||
expose:
|
||||
- "80"
|
||||
ports:
|
||||
@ -77,6 +75,7 @@ services:
|
||||
image: eshop/identity
|
||||
environment:
|
||||
- Spa:http://webspa
|
||||
- ConnectionString=Server=identity.data;Database=aspnet-Microsoft.eShopOnContainers.WebMVC;User Id=sa;Password=Pass@word
|
||||
expose:
|
||||
- "80"
|
||||
ports:
|
||||
|
||||
@ -4,6 +4,7 @@ using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.eShopOnContainers.Services.Basket.API.Model;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
|
||||
namespace Microsoft.eShopOnContainers.Services.Basket.API.Controllers
|
||||
{
|
||||
@ -12,6 +13,7 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API.Controllers
|
||||
//If this is the case we should also investigate changing the serialization format used for Redis,
|
||||
//using a HashSet instead of a simple string.
|
||||
[Route("/")]
|
||||
[Authorize]
|
||||
public class BasketController : Controller
|
||||
{
|
||||
private IBasketRepository _repository;
|
||||
|
||||
@ -17,6 +17,7 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API
|
||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||
.UseIISIntegration()
|
||||
.UseStartup<Startup>()
|
||||
.UseUrls("http://localhost:5008")
|
||||
.Build();
|
||||
|
||||
host.Run();
|
||||
|
||||
@ -47,6 +47,15 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API
|
||||
return ConnectionMultiplexer.Connect(ips.First().ToString());
|
||||
});
|
||||
|
||||
services.AddCors(options =>
|
||||
{
|
||||
options.AddPolicy("CorsPolicy",
|
||||
builder => builder.AllowAnyOrigin()
|
||||
.AllowAnyMethod()
|
||||
.AllowAnyHeader()
|
||||
.AllowCredentials());
|
||||
});
|
||||
|
||||
services.AddTransient<IBasketRepository, RedisBasketRepository>();
|
||||
}
|
||||
|
||||
@ -56,9 +65,12 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API
|
||||
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
|
||||
loggerFactory.AddDebug();
|
||||
|
||||
// Use frameworks
|
||||
app.UseCors("CorsPolicy");
|
||||
|
||||
app.UseIdentityServerAuthentication(new IdentityServerAuthenticationOptions
|
||||
{
|
||||
Authority = Configuration.GetValue("IdentityUrl", "http://localhost:5000"),
|
||||
Authority = "http://localhost:5000",
|
||||
ScopeName = "basket",
|
||||
RequireHttpsMetadata = false
|
||||
});
|
||||
|
||||
@ -7,6 +7,6 @@
|
||||
"Microsoft": "Information"
|
||||
}
|
||||
},
|
||||
"identityUrl": "http://localhost:5105",
|
||||
"identityUrl": "http://localhost:5000",
|
||||
"ConnectionString": "127.0.0.1"
|
||||
}
|
||||
|
||||
@ -49,11 +49,9 @@ namespace eShopOnContainers.Identity.Configuration
|
||||
ClientName = "eShop SPA OpenId Client",
|
||||
AllowedGrantTypes = GrantTypes.Implicit,
|
||||
AllowAccessTokensViaBrowser = true,
|
||||
|
||||
RedirectUris = { "http://localhost:5003/callback.html" },
|
||||
PostLogoutRedirectUris = { "http://localhost:5003/index.html" },
|
||||
AllowedCorsOrigins = { "http://localhost:5003" },
|
||||
|
||||
AllowedScopes =
|
||||
{
|
||||
StandardScopes.OpenId.Name,
|
||||
@ -68,11 +66,9 @@ namespace eShopOnContainers.Identity.Configuration
|
||||
ClientName = "eShop Xamarin OpenId Client",
|
||||
AllowedGrantTypes = GrantTypes.Implicit,
|
||||
AllowAccessTokensViaBrowser = true,
|
||||
|
||||
RedirectUris = { "http://localhost:5003/callback.html" },
|
||||
PostLogoutRedirectUris = { "http://localhost:5003/index.html" },
|
||||
AllowedCorsOrigins = { "http://localhost:5003" },
|
||||
|
||||
AllowedScopes =
|
||||
{
|
||||
StandardScopes.OpenId.Name,
|
||||
@ -90,9 +86,7 @@ namespace eShopOnContainers.Identity.Configuration
|
||||
new Secret("secret".Sha256())
|
||||
},
|
||||
ClientUri = "http://localhost:2114",
|
||||
|
||||
AllowedGrantTypes = GrantTypes.HybridAndClientCredentials,
|
||||
|
||||
RedirectUris = new List<string>
|
||||
{
|
||||
"http://localhost:2114/signin-oidc"
|
||||
|
||||
@ -19,6 +19,10 @@ using IdentityServer4.Stores;
|
||||
using eShopOnContainers.Identity.Services;
|
||||
using eShopOnContainers.Identity.Models;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using eShopOnContainers.Identity.Models.AccountViewModels;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.AspNetCore.Authentication;
|
||||
|
||||
namespace IdentityServer4.Quickstart.UI.Controllers
|
||||
{
|
||||
@ -34,6 +38,7 @@ namespace IdentityServer4.Quickstart.UI.Controllers
|
||||
private readonly IIdentityServerInteractionService _interaction;
|
||||
private readonly IClientStore _clientStore;
|
||||
private readonly ILogger _logger;
|
||||
private readonly UserManager<ApplicationUser> _userManager;
|
||||
|
||||
public AccountController(
|
||||
|
||||
@ -41,12 +46,14 @@ namespace IdentityServer4.Quickstart.UI.Controllers
|
||||
ILoginService<ApplicationUser> loginService,
|
||||
IIdentityServerInteractionService interaction,
|
||||
IClientStore clientStore,
|
||||
ILoggerFactory loggerFactory)
|
||||
ILoggerFactory loggerFactory,
|
||||
UserManager<ApplicationUser> userManager)
|
||||
{
|
||||
_loginService = loginService;
|
||||
_interaction = interaction;
|
||||
_clientStore = clientStore;
|
||||
_logger = loggerFactory.CreateLogger<AccountController>();
|
||||
_userManager = userManager;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -64,12 +71,6 @@ namespace IdentityServer4.Quickstart.UI.Controllers
|
||||
|
||||
var vm = await BuildLoginViewModelAsync(returnUrl, context);
|
||||
|
||||
if (vm.EnableLocalLogin == false && vm.ExternalProviders.Count() == 1)
|
||||
{
|
||||
// only one option for logging in
|
||||
return ExternalLogin(vm.ExternalProviders.First().AuthenticationScheme, returnUrl);
|
||||
}
|
||||
|
||||
return View(vm);
|
||||
}
|
||||
|
||||
@ -78,11 +79,11 @@ namespace IdentityServer4.Quickstart.UI.Controllers
|
||||
/// </summary>
|
||||
[HttpPost]
|
||||
[ValidateAntiForgeryToken]
|
||||
public async Task<IActionResult> Login(LoginInputModel model)
|
||||
public async Task<IActionResult> Login(LoginViewModel model)
|
||||
{
|
||||
if (ModelState.IsValid)
|
||||
{
|
||||
var user = await _loginService.FindByUsername(model.Username);
|
||||
var user = await _loginService.FindByUsername(model.Email);
|
||||
// validate username/password against in-memory store
|
||||
if (await _loginService.ValidateCredentials(user, model.Password))
|
||||
{
|
||||
@ -92,7 +93,7 @@ namespace IdentityServer4.Quickstart.UI.Controllers
|
||||
AuthenticationProperties props = null;
|
||||
// only set explicit expiration here if persistent.
|
||||
// otherwise we reply upon expiration configured in cookie middleware.
|
||||
if (model.RememberLogin)
|
||||
if (model.RememberMe)
|
||||
{
|
||||
props = new AuthenticationProperties
|
||||
{
|
||||
@ -101,7 +102,6 @@ namespace IdentityServer4.Quickstart.UI.Controllers
|
||||
};
|
||||
};
|
||||
|
||||
//await HttpContext.Authentication.SignInAsync(, user.UserName, props);
|
||||
await _loginService.SignIn(user);
|
||||
|
||||
// make sure the returnUrl is still valid, and if yes - redirect back to authorize endpoint
|
||||
@ -123,14 +123,6 @@ namespace IdentityServer4.Quickstart.UI.Controllers
|
||||
|
||||
async Task<LoginViewModel> BuildLoginViewModelAsync(string returnUrl, AuthorizationRequest context)
|
||||
{
|
||||
var providers = HttpContext.Authentication.GetAuthenticationSchemes()
|
||||
.Where(x => x.DisplayName != null)
|
||||
.Select(x => new ExternalProvider
|
||||
{
|
||||
DisplayName = x.DisplayName,
|
||||
AuthenticationScheme = x.AuthenticationScheme
|
||||
});
|
||||
|
||||
var allowLocal = true;
|
||||
if (context?.ClientId != null)
|
||||
{
|
||||
@ -138,29 +130,22 @@ namespace IdentityServer4.Quickstart.UI.Controllers
|
||||
if (client != null)
|
||||
{
|
||||
allowLocal = client.EnableLocalLogin;
|
||||
|
||||
if (client.IdentityProviderRestrictions != null && client.IdentityProviderRestrictions.Any())
|
||||
{
|
||||
providers = providers.Where(provider => client.IdentityProviderRestrictions.Contains(provider.AuthenticationScheme));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new LoginViewModel
|
||||
{
|
||||
EnableLocalLogin = allowLocal,
|
||||
ReturnUrl = returnUrl,
|
||||
Username = context?.LoginHint,
|
||||
ExternalProviders = providers.ToArray()
|
||||
Email = context?.LoginHint,
|
||||
};
|
||||
}
|
||||
|
||||
async Task<LoginViewModel> BuildLoginViewModelAsync(LoginInputModel model)
|
||||
async Task<LoginViewModel> BuildLoginViewModelAsync(LoginViewModel model)
|
||||
{
|
||||
var context = await _interaction.GetAuthorizationContextAsync(model.ReturnUrl);
|
||||
var vm = await BuildLoginViewModelAsync(model.ReturnUrl, context);
|
||||
vm.Username = model.Username;
|
||||
vm.RememberLogin = model.RememberLogin;
|
||||
vm.Email = model.Email;
|
||||
vm.RememberMe = model.RememberMe;
|
||||
return vm;
|
||||
}
|
||||
|
||||
@ -329,5 +314,62 @@ namespace IdentityServer4.Quickstart.UI.Controllers
|
||||
|
||||
return Redirect("~/");
|
||||
}
|
||||
|
||||
// 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)
|
||||
{
|
||||
ViewData["ReturnUrl"] = returnUrl;
|
||||
if (ModelState.IsValid)
|
||||
{
|
||||
var user = new ApplicationUser
|
||||
{
|
||||
UserName = model.Email,
|
||||
Email = model.Email,
|
||||
CardHolderName = model.User.CardHolderName,
|
||||
CardNumber = model.User.CardNumber,
|
||||
CardType = model.User.CardType,
|
||||
City = model.User.City,
|
||||
Country = model.User.Country,
|
||||
Expiration = model.User.Expiration,
|
||||
LastName = model.User.LastName,
|
||||
Name = model.User.Name,
|
||||
Street = model.User.Street,
|
||||
State = model.User.State,
|
||||
ZipCode = model.User.ZipCode,
|
||||
PhoneNumber = model.User.PhoneNumber,
|
||||
SecurityNumber = model.User.SecurityNumber
|
||||
};
|
||||
var result = await _userManager.CreateAsync(user, model.Password);
|
||||
if (result.Errors.Count() > 0)
|
||||
{
|
||||
AddErrors(result);
|
||||
// If we got this far, something failed, redisplay form
|
||||
return View(model);
|
||||
}
|
||||
}
|
||||
|
||||
return RedirectToAction("index", "home");
|
||||
}
|
||||
|
||||
private void AddErrors(IdentityResult result)
|
||||
{
|
||||
foreach (var error in result.Errors)
|
||||
{
|
||||
ModelState.AddModelError(string.Empty, error.Description);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -10,6 +10,7 @@ using System.Threading.Tasks;
|
||||
using IdentityServer4.Models;
|
||||
using IdentityServer4.Stores;
|
||||
using IdentityServer4.Quickstart.UI.Models;
|
||||
using eShopOnContainers.Identity.Models.AccountViewModels;
|
||||
|
||||
namespace IdentityServer4.Quickstart.UI.Controllers
|
||||
{
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace IdentityServer4.Quickstart.UI.Models
|
||||
namespace eShopOnContainers.Identity.Models.AccountViewModels
|
||||
{
|
||||
public class ConsentInputModel
|
||||
{
|
||||
@ -6,7 +6,7 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using IdentityServer4.Models;
|
||||
|
||||
namespace IdentityServer4.Quickstart.UI.Models
|
||||
namespace eShopOnContainers.Identity.Models.AccountViewModels
|
||||
{
|
||||
public class ConsentViewModel : ConsentInputModel
|
||||
{
|
||||
@ -2,7 +2,7 @@
|
||||
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.
|
||||
|
||||
|
||||
namespace IdentityServer4.Quickstart.UI.Models
|
||||
namespace eShopOnContainers.Identity.Models.AccountViewModels
|
||||
{
|
||||
public class LoggedOutViewModel
|
||||
{
|
||||
@ -1,8 +1,8 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
// Copyright (c) Brock Allen & Dominick Baier. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.
|
||||
|
||||
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace eShopOnContainers.Identity.Models.AccountViewModels
|
||||
{
|
||||
@ -18,5 +18,6 @@ namespace eShopOnContainers.Identity.Models.AccountViewModels
|
||||
|
||||
[Display(Name = "Remember me?")]
|
||||
public bool RememberMe { get; set; }
|
||||
public string ReturnUrl { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2,7 +2,7 @@
|
||||
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.
|
||||
|
||||
|
||||
namespace IdentityServer4.Quickstart.UI.Models
|
||||
namespace eShopOnContainers.Identity.Models.AccountViewModels
|
||||
{
|
||||
public class LogoutViewModel
|
||||
{
|
||||
@ -23,5 +23,7 @@ namespace eShopOnContainers.Identity.Models.AccountViewModels
|
||||
[Display(Name = "Confirm password")]
|
||||
[Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
|
||||
public string ConfirmPassword { get; set; }
|
||||
|
||||
public ApplicationUser User { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,20 @@
|
||||
// Copyright (c) Brock Allen & Dominick Baier. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.
|
||||
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace eShopOnContainers.Identity.Models.AccountViewModels
|
||||
{
|
||||
//public class _LoginViewModel : LoginViewModel
|
||||
//{
|
||||
// public bool EnableLocalLogin { get; set; }
|
||||
// public IEnumerable<ExternalProvider> ExternalProviders { get; set; }
|
||||
//}
|
||||
|
||||
//public class ExternalProvider
|
||||
//{
|
||||
// public string DisplayName { get; set; }
|
||||
// public string AuthenticationScheme { get; set; }
|
||||
//}
|
||||
}
|
||||
@ -1,18 +0,0 @@
|
||||
// Copyright (c) Brock Allen & Dominick Baier. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.
|
||||
|
||||
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace IdentityServer4.Quickstart.UI.Models
|
||||
{
|
||||
public class LoginInputModel
|
||||
{
|
||||
[Required]
|
||||
public string Username { get; set; }
|
||||
[Required]
|
||||
public string Password { get; set; }
|
||||
public bool RememberLogin { get; set; }
|
||||
public string ReturnUrl { get; set; }
|
||||
}
|
||||
}
|
||||
@ -1,20 +0,0 @@
|
||||
// Copyright (c) Brock Allen & Dominick Baier. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.
|
||||
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace IdentityServer4.Quickstart.UI.Models
|
||||
{
|
||||
public class LoginViewModel : LoginInputModel
|
||||
{
|
||||
public bool EnableLocalLogin { get; set; }
|
||||
public IEnumerable<ExternalProvider> ExternalProviders { get; set; }
|
||||
}
|
||||
|
||||
public class ExternalProvider
|
||||
{
|
||||
public string DisplayName { get; set; }
|
||||
public string AuthenticationScheme { get; set; }
|
||||
}
|
||||
}
|
||||
@ -62,7 +62,7 @@ namespace eShopOnContainers.Identity
|
||||
.AddInMemoryScopes(Config.GetScopes())
|
||||
.AddInMemoryClients(Config.GetClients())
|
||||
.AddAspNetIdentity<ApplicationUser>()
|
||||
.Services.AddTransient<IProfileService, ProfileService>();
|
||||
.Services.AddTransient<IProfileService, ProfileService>();
|
||||
|
||||
//Configuration Settings:
|
||||
services.AddOptions();
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
@model IdentityServer4.Quickstart.UI.Models.LoggedOutViewModel
|
||||
@model eShopOnContainers.Identity.Models.AccountViewModels.LoggedOutViewModel
|
||||
|
||||
<div class="page-header">
|
||||
<h1>
|
||||
|
||||
@ -1,83 +1,56 @@
|
||||
@model IdentityServer4.Quickstart.UI.Models.LoginViewModel
|
||||
@using System.Collections.Generic
|
||||
@using Microsoft.AspNetCore.Http
|
||||
@using Microsoft.AspNetCore.Http.Authentication
|
||||
@model eShopOnContainers.Identity.Models.AccountViewModels.LoginViewModel
|
||||
|
||||
<div class="login-page">
|
||||
<div class="page-header">
|
||||
<h1>Login</h1>
|
||||
</div>
|
||||
|
||||
@Html.Partial("_ValidationSummary")
|
||||
|
||||
@{
|
||||
ViewData["Title"] = "Log in";
|
||||
}
|
||||
<div class="brand-header-block">
|
||||
<ul class="container">
|
||||
<li><a asp-area="" asp-controller="Account" asp-action="Register">REGISTER</a></li>
|
||||
<li class="active" style="margin-right: 65px;">LOGIN</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="container account-login-container">
|
||||
<div class="row">
|
||||
|
||||
@if (Model.EnableLocalLogin)
|
||||
{
|
||||
<div class="col-sm-6">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title">Local Login</h3>
|
||||
<div class="col-md-12">
|
||||
<section>
|
||||
<form asp-controller="Account" asp-action="Login" asp-route-returnurl="@ViewData["ReturnUrl"]" method="post" class="form-horizontal">
|
||||
<input type="hidden" asp-for="ReturnUrl" />
|
||||
<h4>ARE YOU REGISTERED?</h4>
|
||||
<div asp-validation-summary="All" class="text-danger"></div>
|
||||
<div class="form-group">
|
||||
<label asp-for="Email" class="control-label form-label"></label>
|
||||
<input asp-for="Email" class="form-control form-input form-input-center" />
|
||||
<span asp-validation-for="Email" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
|
||||
<form asp-route="Login">
|
||||
<input type="hidden" asp-for="ReturnUrl" />
|
||||
|
||||
<fieldset>
|
||||
<div class="form-group">
|
||||
<label asp-for="Username"></label>
|
||||
<input class="form-control" placeholder="Username" asp-for="Username" autofocus>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="Password"></label>
|
||||
<input type="password" class="form-control" placeholder="Password" asp-for="Password" autocomplete="off">
|
||||
</div>
|
||||
<div class="form-group login-remember">
|
||||
<label asp-for="RememberLogin">
|
||||
<input asp-for="RememberLogin">
|
||||
<strong>Remember My Login</strong>
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<button class="btn btn-primary">Login</button>
|
||||
</div>
|
||||
</fieldset>
|
||||
</form>
|
||||
<div class="form-group">
|
||||
<label asp-for="Password" class="control-label form-label"></label>
|
||||
<input asp-for="Password" class="form-control form-input form-input-center" />
|
||||
<span asp-validation-for="Password" class="text-danger"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
@if (Model.ExternalProviders.Any())
|
||||
{
|
||||
<div class="col-md-6 col-sm-6 external-providers">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title">External Login</h3>
|
||||
<div class="form-group">
|
||||
<div class="checkbox">
|
||||
<label asp-for="RememberMe">
|
||||
<input asp-for="RememberMe" />
|
||||
@Html.DisplayNameFor(m => m.RememberMe)
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<ul class="list-inline">
|
||||
@foreach (var provider in Model.ExternalProviders)
|
||||
{
|
||||
<li>
|
||||
<a class="btn btn-default"
|
||||
asp-action="ExternalLogin"
|
||||
asp-route-provider="@provider.AuthenticationScheme"
|
||||
asp-route-returnUrl="@Model.ReturnUrl">
|
||||
@provider.DisplayName
|
||||
</a>
|
||||
</li>
|
||||
}
|
||||
</ul>
|
||||
<div class="form-group">
|
||||
<button type="submit" class="btn btn-default btn-brand btn-brand-big"> LOG IN </button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
@if (!Model.EnableLocalLogin && !Model.ExternalProviders.Any())
|
||||
{
|
||||
<div class="alert alert-warning">
|
||||
<strong>Invalid login request</strong>
|
||||
There are no login schemes configured for this client.
|
||||
</div>
|
||||
}
|
||||
<p>
|
||||
<a asp-action="Register" asp-route-returnurl="@ViewData["ReturnUrl"]" class="text">Register as a new user?</a>
|
||||
</p>
|
||||
</form>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@section Scripts {
|
||||
@{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); }
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
@model IdentityServer4.Quickstart.UI.Models.LogoutViewModel
|
||||
@model eShopOnContainers.Identity.Models.AccountViewModels.LogoutViewModel
|
||||
|
||||
<div class="logout-page">
|
||||
<div class="page-header">
|
||||
|
||||
@ -1,42 +1,107 @@
|
||||
@model RegisterViewModel
|
||||
@using eShopOnContainers.Identity.Models.AccountViewModels
|
||||
@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">
|
||||
<h4>Create a new account.</h4>
|
||||
<hr />
|
||||
<div asp-validation-summary="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 class="brand-header-block">
|
||||
<ul class="container">
|
||||
<li class="active">REGISTER</li>
|
||||
<li style="margin-right: 65px;"><a asp-area="" asp-controller="Account" asp-action="Login">LOGIN</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="container register-container">
|
||||
<form asp-controller="Account" asp-action="Register" asp-route-returnurl="@ViewData["ReturnUrl"]" method="post" class="form-horizontal">
|
||||
<h4 class="order-create-section-title">CREATE NEW ACCOUNT</h4>
|
||||
<div asp-validation-summary="All" class="text-danger"></div>
|
||||
<div class="row">
|
||||
<div class="form-group col-sm-6">
|
||||
<label asp-for="User.Name" class="control-label form-label">NAME</label>
|
||||
<input asp-for="User.Name" class="form-control form-input" />
|
||||
<span asp-validation-for="User.Name" class="text-danger" />
|
||||
</div>
|
||||
<div class="form-group col-sm-6">
|
||||
<label asp-for="User.LastName" class="control-label form-label">LAST NAME</label>
|
||||
<input asp-for="User.LastName" class="form-control form-input" />
|
||||
<span asp-validation-for="User.LastName" class="text-danger" />
|
||||
</div>
|
||||
<div class="form-group col-sm-6">
|
||||
<label asp-for="User.Street" class="control-label form-label">ADDRESS</label>
|
||||
<input asp-for="User.Street" class="form-control form-input" />
|
||||
<span asp-validation-for="User.Street" class="text-danger" />
|
||||
</div>
|
||||
<div class="form-group col-sm-6">
|
||||
<label asp-for="User.City" class="control-label form-label"></label>
|
||||
<input asp-for="User.City" class="form-control form-input" />
|
||||
<span asp-validation-for="User.City" class="text-danger" />
|
||||
</div>
|
||||
<div class="form-group col-sm-6">
|
||||
<label asp-for="User.State" class="control-label form-label"></label>
|
||||
<input asp-for="User.State" class="form-control form-input" />
|
||||
<span asp-validation-for="User.State" class="text-danger" />
|
||||
</div>
|
||||
<div class="form-group col-sm-6">
|
||||
<label asp-for="User.Country" class="control-label form-label"></label>
|
||||
<input asp-for="User.Country" class="form-control form-input" />
|
||||
<span asp-validation-for="User.Country" class="text-danger" />
|
||||
</div>
|
||||
<div class="form-group col-sm-6">
|
||||
<label asp-for="User.ZipCode" class="control-label form-label">POSTCODE</label>
|
||||
<input asp-for="User.ZipCode" class="form-control form-input" />
|
||||
<span asp-validation-for="User.ZipCode" class="text-danger" />
|
||||
</div>
|
||||
<div class="form-group col-sm-6">
|
||||
<label asp-for="User.PhoneNumber" class="control-label form-label">PHONE NUMBER</label>
|
||||
<input asp-for="User.PhoneNumber" class="form-control form-input" />
|
||||
<span asp-validation-for="User.PhoneNumber" class="text-danger" />
|
||||
</div>
|
||||
<div class="form-group col-sm-6">
|
||||
<label asp-for="User.CardNumber" class="control-label form-label">Card Number</label>
|
||||
<input asp-for="User.CardNumber" class="form-control form-input" />
|
||||
<span asp-validation-for="User.CardNumber" class="text-danger" />
|
||||
</div>
|
||||
<div class="form-group col-sm-6">
|
||||
<label asp-for="User.CardHolderName" class="control-label form-label">Cardholder Name</label>
|
||||
<input asp-for="User.CardHolderName" class="form-control form-input" />
|
||||
<span asp-validation-for="User.CardHolderName" class="text-danger" />
|
||||
</div>
|
||||
<div class="form-group col-sm-3">
|
||||
<label asp-for="User.Expiration" class="control-label form-label">Expiration Date</label>
|
||||
<input asp-for="User.Expiration" placeholder="MM/YY" class="form-control form-input form-input-small" />
|
||||
<span asp-validation-for="User.Expiration" class="text-danger" />
|
||||
</div>
|
||||
<div class="form-group col-sm-3">
|
||||
<label asp-for="User.SecurityNumber" class="control-label form-label">Security Code</label>
|
||||
<input asp-for="User.SecurityNumber" class="form-control form-input form-input-small" />
|
||||
<span asp-validation-for="User.SecurityNumber" class="text-danger" />
|
||||
</div>
|
||||
</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>
|
||||
<br /><br />
|
||||
<div class="row">
|
||||
<div class="form-group col-sm-6">
|
||||
<label asp-for="Email" class="control-label form-label"></label>
|
||||
<input asp-for="Email" class="form-control form-input" />
|
||||
<span asp-validation-for="Email" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group col-sm-offset-6"></div>
|
||||
<div class="form-group col-sm-6">
|
||||
<label asp-for="Password" class="control-label form-label"></label>
|
||||
<input asp-for="Password" class="form-control form-input" />
|
||||
<span asp-validation-for="Password" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group col-sm-6">
|
||||
<label asp-for="ConfirmPassword" class="control-label form-label"></label>
|
||||
<input asp-for="ConfirmPassword" class="form-control form-input" />
|
||||
<span asp-validation-for="ConfirmPassword" class="text-danger"></span>
|
||||
</div>
|
||||
</div>
|
||||
<br /><br />
|
||||
<div class="form-group">
|
||||
<button type="submit" class="btn btn-default btn-brand"> Register </button>
|
||||
</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>
|
||||
|
||||
<br /><br />
|
||||
</form>
|
||||
</div>
|
||||
@section Scripts {
|
||||
@{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); }
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,49 @@
|
||||
@*@model eShopOnContainers.Identity.Models.AccountViewModels.LoginViewModel
|
||||
|
||||
<div class="login-page">
|
||||
<div class="page-header">
|
||||
<h1>Login</h1>
|
||||
</div>
|
||||
|
||||
@Html.Partial("_ValidationSummary")
|
||||
|
||||
<div class="row">
|
||||
|
||||
@if (Model.EnableLocalLogin)
|
||||
{
|
||||
<div class="col-sm-6">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title">Local Login</h3>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
|
||||
<form asp-route="Login">
|
||||
<input type="hidden" asp-for="ReturnUrl" />
|
||||
|
||||
<fieldset>
|
||||
<div class="form-group">
|
||||
<label asp-for="Username"></label>
|
||||
<input class="form-control" placeholder="Username" asp-for="Username" autofocus>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="Password"></label>
|
||||
<input type="password" class="form-control" placeholder="Password" asp-for="Password" autocomplete="off">
|
||||
</div>
|
||||
<div class="form-group login-remember">
|
||||
<label asp-for="RememberLogin">
|
||||
<input asp-for="RememberLogin">
|
||||
<strong>Remember My Login</strong>
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<button class="btn btn-primary">Login</button>
|
||||
</div>
|
||||
</fieldset>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>*@
|
||||
@ -1,4 +1,4 @@
|
||||
@model IdentityServer4.Quickstart.UI.Models.ConsentViewModel
|
||||
@model eShopOnContainers.Identity.Models.AccountViewModels.ConsentViewModel
|
||||
|
||||
<div class="page-consent">
|
||||
<div class="row page-header">
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
@model IdentityServer4.Quickstart.UI.Models.ScopeViewModel
|
||||
@model eShopOnContainers.Identity.Models.AccountViewModels.ScopeViewModel
|
||||
|
||||
<li class="list-group-item">
|
||||
<label>
|
||||
|
||||
@ -8,6 +8,7 @@
|
||||
<link rel="shortcut icon" type="image/x-icon" href="~/favicon.ico" />
|
||||
<link rel="stylesheet" href="~/lib/bootstrap/css/bootstrap.css" />
|
||||
<link rel="stylesheet" href="~/css/site.css" />
|
||||
<link rel="stylesheet" href="~/css/sitemvc.css" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="navbar navbar-inverse navbar-fixed-top">
|
||||
@ -26,7 +27,9 @@
|
||||
</span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<a asp-action="Register" asp-controller="Account">Register User</a>
|
||||
</div>
|
||||
@if (User.Identity.IsAuthenticated)
|
||||
{
|
||||
<ul class="nav navbar-nav">
|
||||
@ -34,8 +37,6 @@
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">@User.Identity.Name <b class="caret"></b></a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a asp-action="Logout" asp-controller="Account">Logout</a></li>
|
||||
@*<li class="divider"></li>
|
||||
<li><a asp-route="Login" asp-route-id="@ViewContext.HttpContext.Request.Query["id"]">Login With Different Account</a></li>*@
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
@ -5,7 +5,8 @@
|
||||
"outputFileName": "wwwroot/css/site.min.css",
|
||||
// An array of relative input file paths. Globbing patterns supported
|
||||
"inputFiles": [
|
||||
"wwwroot/css/site.css"
|
||||
"wwwroot/css/site.css",
|
||||
"wwwroot/css/sitemvc.css"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
@ -55,3 +55,870 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: Montserrat;
|
||||
font-weight: 400;
|
||||
src: url("/fonts/Montserrat-Regular.eot?") format("eot"),url("/fonts/Montserrat-Regular.woff") format("woff"),url("/fonts/Montserrat-Regular.ttf") format("truetype"),url("/fonts/Montserrat-Regular.svg#Montserrat") format("svg")
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: Montserrat;
|
||||
font-weight: 700;
|
||||
src: url("/fonts/Montserrat-Bold.eot?") format("eot"),url("/fonts/Montserrat-Bold.woff") format("woff"),url("/fonts/Montserrat-Bold.ttf") format("truetype"),url("/fonts/Montserrat-Bold.svg#Montserrat") format("svg")
|
||||
}
|
||||
|
||||
body {
|
||||
padding-top: 80px;
|
||||
/*padding-bottom: 20px;*/
|
||||
font-family: Montserrat,sans-serif;
|
||||
min-width:480px;
|
||||
}
|
||||
|
||||
.mt-15 {
|
||||
margin-top:15px;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
.select-filter {
|
||||
background-color: transparent;
|
||||
padding: 10px;
|
||||
margin: 10px;
|
||||
margin-right: 20px;
|
||||
color: white;
|
||||
padding-top: 20px;
|
||||
padding-bottom: 3px;
|
||||
min-width: 140px;
|
||||
border-color: #37c7ca;
|
||||
max-height: 43px;
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
|
||||
.select-filter option {
|
||||
background-color: #00a69c;
|
||||
}
|
||||
|
||||
select::-ms-expand {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.select-filter-wrapper {
|
||||
z-index: 0;
|
||||
display:inline-block;
|
||||
margin-left: -10px;
|
||||
}
|
||||
|
||||
.select-filter-wrapper::before {
|
||||
content: attr(data-name);
|
||||
opacity: 0.5;
|
||||
z-index: 1;
|
||||
text-transform: uppercase;
|
||||
position: absolute;
|
||||
font-size: 10px;
|
||||
margin-top: 15px;
|
||||
margin-left: 21px;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.select-filter-arrow {
|
||||
position: absolute;
|
||||
margin-left: 130px;
|
||||
margin-top: 40px;
|
||||
}
|
||||
|
||||
.btn-brand-small-filter {
|
||||
margin-top: 10px;
|
||||
position: absolute;
|
||||
margin-left: 15px;
|
||||
}
|
||||
|
||||
/* Carousel */
|
||||
.carousel-caption p {
|
||||
font-size: 20px;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.layout-cart-image {
|
||||
height: 36px;
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
.layout-cart-badge {
|
||||
position: absolute;
|
||||
margin-top: 2px;
|
||||
margin-left: 14px;
|
||||
background-color: #83d01b;
|
||||
padding: 1px;
|
||||
color: white;
|
||||
border-radius: 50%;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
font-size: 12px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* buttons and links extension to use brackets: [ click me ] */
|
||||
.btn-bracketed:hover:before {
|
||||
display: inline-block;
|
||||
content: "[";
|
||||
padding-right: 0.5em;
|
||||
color: chartreuse;
|
||||
}
|
||||
|
||||
.btn-bracketed:hover:after {
|
||||
display: inline-block;
|
||||
content: "]";
|
||||
padding-left: 0.5em;
|
||||
color: chartreuse;
|
||||
}
|
||||
|
||||
.btn-brand {
|
||||
background-color: #83D01B;
|
||||
color: white;
|
||||
padding: 10px 20px 10px 20px;
|
||||
border-radius: 0px;
|
||||
border: none;
|
||||
width: 255px;
|
||||
display: inline-block;
|
||||
text-align: center;
|
||||
text-transform: uppercase;
|
||||
height: 45px;
|
||||
font-size: 16px;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.btn-brand::before {
|
||||
content: '['
|
||||
}
|
||||
|
||||
.btn-brand::after {
|
||||
content: ']'
|
||||
}
|
||||
|
||||
.btn-brand:hover:before {
|
||||
padding-right: 5px;
|
||||
}
|
||||
|
||||
.btn-brand:hover:after {
|
||||
padding-left: 5px;
|
||||
}
|
||||
|
||||
.btn-brand-big {
|
||||
width: 360px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.btn-brand-small {
|
||||
width: 45px;
|
||||
}
|
||||
|
||||
.btn-brand-small::before {
|
||||
content: '';
|
||||
}
|
||||
|
||||
.btn-brand-small::after {
|
||||
content: '';
|
||||
}
|
||||
|
||||
.btn-brand-small:hover:before {
|
||||
content: '';
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.btn-brand-small:hover:after {
|
||||
content: '';
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.btn-brand-dark {
|
||||
background-color: #00a69c;
|
||||
}
|
||||
|
||||
.btn-brand:hover {
|
||||
color: white;
|
||||
background-color: #83D01B;
|
||||
text-decoration:none;
|
||||
}
|
||||
|
||||
.btn-brand-dark:hover {
|
||||
background-color: #00a69c;
|
||||
}
|
||||
|
||||
.btn-cart {
|
||||
float: right;
|
||||
margin-top: 40px;
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
|
||||
.btn-catalog-apply {
|
||||
padding:0;
|
||||
}
|
||||
|
||||
.form-label {
|
||||
text-transform: uppercase;
|
||||
font-weight: normal!important;
|
||||
text-align: left;
|
||||
margin-bottom: 10px !important;
|
||||
color: #404040;
|
||||
}
|
||||
|
||||
.form-input {
|
||||
border-radius: 0;
|
||||
padding: 10px;
|
||||
height: 45px;
|
||||
}
|
||||
|
||||
.form-input-small {
|
||||
max-width: 100px!important;
|
||||
}
|
||||
|
||||
.form-select {
|
||||
border-radius: 0;
|
||||
padding: 10px;
|
||||
height: 45px;
|
||||
width: 150px;
|
||||
}
|
||||
|
||||
/* Make .svg files in the carousel display properly in older browsers */
|
||||
.carousel-inner .item img[src$=".svg"] {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.navbar-inverse {
|
||||
background-color: #FFF;
|
||||
border-color: #FFF;
|
||||
}
|
||||
|
||||
/*.navbar-inverse li {
|
||||
margin-top: 10px;
|
||||
}*/
|
||||
|
||||
.btn-login {
|
||||
border: 1px solid #00A69C;
|
||||
height: 36px!important;
|
||||
margin-right: 10px;
|
||||
margin-top: 10px;
|
||||
background-color: white;
|
||||
color: #00a69c;
|
||||
text-transform:uppercase;
|
||||
max-width: 140px;
|
||||
width: 140px;
|
||||
padding-top:8px!important;
|
||||
}
|
||||
|
||||
.btn-login {
|
||||
font-weight:normal!important;
|
||||
}
|
||||
|
||||
.btn-login::before {
|
||||
content: '[';
|
||||
}
|
||||
|
||||
.btn-login::after {
|
||||
content: ']';
|
||||
}
|
||||
|
||||
.btn-login:hover:before {
|
||||
content: '[ ';
|
||||
}
|
||||
|
||||
.btn-login:hover:after {
|
||||
content: ' ]';
|
||||
}
|
||||
|
||||
.navbar-inverse li a {
|
||||
height: 30px;
|
||||
padding: 5px 20px;
|
||||
color: #00A69C !important;
|
||||
}
|
||||
|
||||
.navbar-brand {
|
||||
margin-top: 20px;
|
||||
background-image: url(../images/brand.PNG);
|
||||
width: 201px;
|
||||
height: 44px;
|
||||
margin-left: 0px !important;
|
||||
}
|
||||
|
||||
.nav > li > a {
|
||||
color: white;
|
||||
}
|
||||
|
||||
.nav > li > a:hover, .nav > li > a:focus {
|
||||
background-color: #00A69C;
|
||||
font-weight: bolder;
|
||||
}
|
||||
|
||||
.container-fluid {
|
||||
padding-left: 0px;
|
||||
padding-right: 0px;
|
||||
}
|
||||
|
||||
.home-banner {
|
||||
width: 100%;
|
||||
margin-right: 0px;
|
||||
margin-left: 0px;
|
||||
background-image: url(../images/main_banner.png);
|
||||
background-size: cover;
|
||||
height: 258px;
|
||||
background-position: center;
|
||||
}
|
||||
|
||||
.home-banner-text {
|
||||
margin-top: 70px;
|
||||
}
|
||||
|
||||
.home-catalog-container {
|
||||
min-height: 400px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.home-catalog-filter-container {
|
||||
background-color: #00A69C;
|
||||
height:63px;
|
||||
}
|
||||
|
||||
.home-catalog-filter-container li a {
|
||||
padding-top: 5px !important;
|
||||
}
|
||||
|
||||
.home-catalog-filter-brands::before {
|
||||
content: 'BRAND';
|
||||
color: white;
|
||||
font-size: x-small;
|
||||
opacity: 0.5;
|
||||
margin: 10px 0px 0px 15px;
|
||||
}
|
||||
|
||||
.home-catalog-filter-types::before {
|
||||
content: 'TYPES';
|
||||
color: white;
|
||||
font-size: x-small;
|
||||
opacity: 0.5;
|
||||
margin: 10px 0px 0px 15px;
|
||||
}
|
||||
|
||||
.home-catalog-item {
|
||||
margin-top: 10px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.home-catalog-item-image {
|
||||
width: 100%;
|
||||
object-fit: cover;
|
||||
/* max-width: 320px; */
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.home-catalog-item-image-addCart {
|
||||
background-color: #83D01B;
|
||||
color: white;
|
||||
display: inline-block;
|
||||
height: 43px;
|
||||
padding: 10px 20px 10px 20px;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
margin-top: 10px;
|
||||
margin-left: 60px;
|
||||
margin-right: 60px;
|
||||
font-size: 16px;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.home-catalog-item-image-addCart:hover {
|
||||
color: white;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
|
||||
.home-catalog-item-image:hover:after {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.home-catalog-item-title {
|
||||
text-align: center;
|
||||
text-transform: uppercase;
|
||||
font-weight: 300;
|
||||
font-size: 16px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.home-catalog-item-price {
|
||||
text-align: center;
|
||||
font-weight: 900;
|
||||
font-size: 28px;
|
||||
}
|
||||
|
||||
.home-catalog-item-price::before {
|
||||
content: '$';
|
||||
}
|
||||
|
||||
.home-catalog-noResults {
|
||||
text-align:center;
|
||||
margin-top: 100px;
|
||||
}
|
||||
|
||||
.container .nav .navbar-nav .col-sm-6 ::before {
|
||||
content: 'BRAND';
|
||||
}
|
||||
|
||||
.validation-summary-errors li {
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
footer {
|
||||
background-color: black;
|
||||
height: 150px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
footer .brand {
|
||||
margin-top: 25px;
|
||||
background-image: url(../images/brand_dark.PNG);
|
||||
max-width: 231px;
|
||||
height: 52px;
|
||||
margin-left: 0px !important;
|
||||
}
|
||||
|
||||
footer .text {
|
||||
text-align: right;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
color: #83D01B;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.text {
|
||||
color: #83D01B;
|
||||
}
|
||||
|
||||
.text:hover {
|
||||
color: #83D01B;
|
||||
}
|
||||
|
||||
form .col-md-4 {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.brand-header-block {
|
||||
background-color: #00A69C;
|
||||
height: 63px;
|
||||
}
|
||||
|
||||
.brand-header-block li {
|
||||
list-style: none;
|
||||
display: inline;
|
||||
opacity: 0.5;
|
||||
margin-top: 25px;
|
||||
margin-left: 10px;
|
||||
float: right;
|
||||
cursor: pointer;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.brand-header-block li a {
|
||||
color: white;
|
||||
}
|
||||
|
||||
.brand-header-block li a:hover {
|
||||
text-decoration:none;
|
||||
}
|
||||
|
||||
.brand-header-block .active {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.brand-header-block .active::before {
|
||||
content: '[ ';
|
||||
color: greenyellow;
|
||||
}
|
||||
|
||||
.brand-header-block .active::after {
|
||||
content: ' ]';
|
||||
color: greenyellow;
|
||||
}
|
||||
|
||||
.brand-header-back {
|
||||
float: left!important;
|
||||
margin-top: 20px!important;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.account-login-container {
|
||||
min-height: 70vh;
|
||||
text-align: center;
|
||||
padding-top: 40px;
|
||||
}
|
||||
|
||||
.account-register-container {
|
||||
min-height: 70vh;
|
||||
text-align: center !important;
|
||||
align-content: center;
|
||||
}
|
||||
|
||||
.cart-index-container {
|
||||
min-height: 70vh;
|
||||
padding-top: 40px;
|
||||
margin-bottom: 30px;
|
||||
min-width: 992px;
|
||||
}
|
||||
|
||||
.register-container {
|
||||
min-height: 70vh;
|
||||
padding-top: 40px;
|
||||
margin-bottom: 30px;
|
||||
padding-left: 30px;
|
||||
}
|
||||
|
||||
.order-create-container {
|
||||
min-height: 70vh;
|
||||
padding-top: 40px;
|
||||
margin-bottom: 30px;
|
||||
padding-left: 30px;
|
||||
min-width: 995px;
|
||||
}
|
||||
|
||||
.cart-product-column {
|
||||
max-width: 120px;
|
||||
text-transform: uppercase;
|
||||
vertical-align: middle!important;
|
||||
}
|
||||
|
||||
.order-create-container .cart-product-column {
|
||||
max-width: 130px;
|
||||
}
|
||||
|
||||
.cart-product-column-name {
|
||||
width: 220px;
|
||||
}
|
||||
|
||||
.cart-subtotal-label {
|
||||
font-size: 12px;
|
||||
color: #404040;
|
||||
margin-top:10px;
|
||||
}
|
||||
|
||||
.cart-subtotal-value {
|
||||
font-size: 20px;
|
||||
color: #00a69c;
|
||||
}
|
||||
|
||||
.cart-total-label {
|
||||
font-size: 14px;
|
||||
color: #404040;
|
||||
margin-top:10px;
|
||||
}
|
||||
|
||||
.cart-total-value {
|
||||
font-size: 28px;
|
||||
color: #00a69c;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.cart-product-image {
|
||||
max-width: 210px;
|
||||
}
|
||||
|
||||
.cart-section-total {
|
||||
margin-bottom: 5px;
|
||||
margin-left: 175px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.cart-product-column input {
|
||||
width: 70px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.cart-refresh-button {
|
||||
margin-top:0;
|
||||
background-image: url('../images/refresh.svg');
|
||||
color: white;
|
||||
font-size: 8px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
background-color:transparent;
|
||||
border:none;
|
||||
margin-top: 25px;
|
||||
margin-left:15px;
|
||||
}
|
||||
|
||||
.cart-refresh-button:hover {
|
||||
background-color:transparent;
|
||||
}
|
||||
|
||||
.cart-totals {
|
||||
border-bottom:none!important;
|
||||
}
|
||||
|
||||
.input-validation-error {
|
||||
border: 1px solid #fb0d0d;
|
||||
}
|
||||
|
||||
.text-danger {
|
||||
color: #fb0d0d;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.cart {
|
||||
border: none !important;
|
||||
}
|
||||
|
||||
.form-horizontal h4 {
|
||||
margin-top: 30px;
|
||||
}
|
||||
|
||||
.form-horizontal .form-group {
|
||||
margin-right: 0px!important;
|
||||
}
|
||||
|
||||
.form-control:focus {
|
||||
border-color: #83d01b;
|
||||
}
|
||||
|
||||
.form-input-center {
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.order-index-container {
|
||||
min-height: 70vh;
|
||||
padding-top: 40px;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.order-index-container .table tbody tr {
|
||||
border-bottom:none;
|
||||
}
|
||||
|
||||
.order-index-container .table tbody tr td {
|
||||
border-top:none;
|
||||
padding-top:10px;
|
||||
padding-bottom:10px;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.order-index-container .table tbody tr:nth-child(even) {
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
.order-create-section-title {
|
||||
margin-left: -15px;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.order-create-section-items {
|
||||
margin-left: -45px;
|
||||
width: 102%;
|
||||
}
|
||||
|
||||
.order-detail-button {
|
||||
|
||||
}
|
||||
|
||||
.order-detail-button a {
|
||||
color: #83d01b;
|
||||
}
|
||||
|
||||
.order-detail-container {
|
||||
min-height: 70vh;
|
||||
padding-top: 40px;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.order-detail-container .table tbody tr:first-child td{
|
||||
border-top:none;
|
||||
}
|
||||
|
||||
.order-detail-container .table tr{
|
||||
border-bottom:none;
|
||||
}
|
||||
|
||||
.order-detail-section {
|
||||
margin-top: 50px;
|
||||
}
|
||||
|
||||
.order-detail-container .table {
|
||||
margin-left: -7px;
|
||||
}
|
||||
|
||||
.order-section-total {
|
||||
margin-bottom: 5px;
|
||||
margin-left: 40px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.fr {
|
||||
float:right!important;
|
||||
}
|
||||
|
||||
.down-arrow {
|
||||
background-image: url('../images/arrow-down.png');
|
||||
height: 7px;
|
||||
width: 10px;
|
||||
display: inline-block;
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
.logout-icon {
|
||||
background-image: url('../images/logout.PNG');
|
||||
display: inline-block;
|
||||
height:19px;
|
||||
width:19px;
|
||||
margin-left: 15px;
|
||||
}
|
||||
|
||||
.myorders-icon {
|
||||
background-image: url('../images/my_orders.PNG');
|
||||
display: inline-block;
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
margin-left: 15px;
|
||||
}
|
||||
|
||||
.login-user {
|
||||
position: absolute!important;
|
||||
top: 30px;
|
||||
right: 65px;
|
||||
cursor:pointer;
|
||||
}
|
||||
|
||||
.login-user-dropdown {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.login-user-dropdown-content {
|
||||
display: none;
|
||||
position: absolute;
|
||||
background-color: #FFFFFF;
|
||||
min-width: 160px;
|
||||
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
|
||||
/*left: 100px;*/
|
||||
right: 0px;
|
||||
}
|
||||
|
||||
.login-user-dropdown-content a {
|
||||
color: black;
|
||||
padding: 12px 16px;
|
||||
text-decoration: none;
|
||||
display: block;
|
||||
text-align:right;
|
||||
text-transform:uppercase;
|
||||
}
|
||||
|
||||
.login-user:hover .login-user-dropdown-content {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.down-arrow:hover > .login-user-dropdown-content {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.login-user-dropdown-content a:hover {
|
||||
color: #83d01b;
|
||||
}
|
||||
|
||||
.es-header {
|
||||
min-height: 80px!important;
|
||||
}
|
||||
|
||||
.es-pager-bottom {
|
||||
margin-top: 40px;
|
||||
}
|
||||
|
||||
.es-pager-top {
|
||||
margin-bottom: 20px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.es-pager-top ul {
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.es-pager-bottom ul {
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.page-item {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.next {
|
||||
position: absolute;
|
||||
right: 15px;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.previous {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.is-disabled{
|
||||
cursor: not-allowed;
|
||||
opacity: .5;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.table tr {
|
||||
border-bottom:1px solid #ddd;
|
||||
}
|
||||
|
||||
.table th {
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
|
||||
.navbar-nav {
|
||||
margin-top: 10px;
|
||||
margin-bottom: 7.5px;
|
||||
margin-right: -10px;
|
||||
float: right;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 1195px) {
|
||||
.cart-product-column-name {
|
||||
display:none;
|
||||
}
|
||||
}
|
||||
|
||||
/* Hide/rearrange for smaller screens */
|
||||
@media screen and (max-width: 767px) {
|
||||
/* Hide captions */
|
||||
.carousel-caption {
|
||||
display: none;
|
||||
}
|
||||
|
||||
footer .text {
|
||||
text-align: left;
|
||||
margin-top: -15px;
|
||||
}
|
||||
|
||||
.cart-product-column-brand {
|
||||
display:none;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (min-width: 992px) {
|
||||
.form-input {
|
||||
width: 360px;
|
||||
max-width: 360px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
File diff suppressed because one or more lines are too long
@ -0,0 +1 @@
|
||||
|
||||
1
src/Services/Identity/eShopOnContainers.Identity/wwwroot/css/sitemvc.min.css
vendored
Normal file
1
src/Services/Identity/eShopOnContainers.Identity/wwwroot/css/sitemvc.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because it is too large
Load Diff
|
After Width: | Height: | Size: 111 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
|
After Width: | Height: | Size: 104 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1,4 +1,4 @@
|
||||
{
|
||||
//"ConnectionString": "Server=tcp:ordering.data;Database=Microsoft.eShopOnContainers.Services.OrderingDb;User Id=sa;Password=Pass@word;"
|
||||
//"ConnectionString": "Server=ordering.data;Database=Microsoft.eShopOnContainers.Services.OrderingDb;User Id=sa;Password=Pass@word;"
|
||||
"ConnectionString": "Server=tcp:127.0.0.1,5432;Database=Microsoft.eShopOnContainers.Services.OrderingDb;User Id=sa;Password=Pass@word;"
|
||||
}
|
||||
|
||||
@ -1,18 +1,9 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Security.Claims;
|
||||
using System.Threading.Tasks;
|
||||
using System.Security.Claims;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.eShopOnContainers.WebMVC.Models;
|
||||
using Microsoft.eShopOnContainers.WebMVC.Models.AccountViewModels;
|
||||
using Microsoft.eShopOnContainers.WebMVC.Services;
|
||||
using System.Net.Http;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Microsoft.eShopOnContainers.WebMVC.Extensions;
|
||||
using Microsoft.AspNetCore.Http.Authentication;
|
||||
|
||||
namespace Microsoft.eShopOnContainers.WebMVC.Controllers
|
||||
{
|
||||
@ -45,456 +36,9 @@ namespace Microsoft.eShopOnContainers.WebMVC.Controllers
|
||||
return Redirect("/");
|
||||
}
|
||||
|
||||
[Authorize]
|
||||
public async Task<ActionResult> CallApi()
|
||||
public IActionResult Signout()
|
||||
{
|
||||
var token = (User as ClaimsPrincipal).FindFirst("access_token").Value;
|
||||
|
||||
var client = new HttpClient();
|
||||
client.SetBearerToken(token);
|
||||
|
||||
var result = await client.GetStringAsync("apiuri");
|
||||
ViewBag.Json = JArray.Parse(result.ToString());
|
||||
|
||||
return View();
|
||||
return new SignOutResult("oidc", new AuthenticationProperties { RedirectUri = "/" });
|
||||
}
|
||||
|
||||
|
||||
public async Task<ActionResult> Signout()
|
||||
{
|
||||
await Request.HttpContext.Authentication.SignOutAsync("oidc");
|
||||
return Redirect("/");
|
||||
}
|
||||
|
||||
public async Task SignoutCleanup(string sid)
|
||||
{
|
||||
var cp = (ClaimsPrincipal)User;
|
||||
var sidClaim = cp.FindFirst("sid");
|
||||
if (sidClaim != null && sidClaim.Value == sid)
|
||||
{
|
||||
await Request.HttpContext.Authentication.SignOutAsync("Cookies");
|
||||
}
|
||||
}
|
||||
|
||||
//private readonly UserManager<ApplicationUser> _userManager;
|
||||
//private readonly SignInManager<ApplicationUser> _signInManager;
|
||||
//private readonly ILogger _logger;
|
||||
|
||||
//public AccountController(
|
||||
// UserManager<ApplicationUser> userManager,
|
||||
// SignInManager<ApplicationUser> signInManager,
|
||||
// ILoggerFactory loggerFactory)
|
||||
//{
|
||||
// _userManager = userManager;
|
||||
// _signInManager = signInManager;
|
||||
// _logger = loggerFactory.CreateLogger<AccountController>();
|
||||
//}
|
||||
|
||||
////
|
||||
//// 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)
|
||||
//{
|
||||
// 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)
|
||||
// {
|
||||
// _logger.LogInformation(1, "User logged in.");
|
||||
// return RedirectToLocal(returnUrl);
|
||||
// }
|
||||
// if (result.RequiresTwoFactor)
|
||||
// {
|
||||
// return RedirectToAction(nameof(SendCode), new { ReturnUrl = returnUrl, RememberMe = model.RememberMe });
|
||||
// }
|
||||
// if (result.IsLockedOut)
|
||||
// {
|
||||
// _logger.LogWarning(2, "User account locked out.");
|
||||
// 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)
|
||||
//{
|
||||
// ViewData["ReturnUrl"] = returnUrl;
|
||||
// if (ModelState.IsValid)
|
||||
// {
|
||||
// var user = new ApplicationUser
|
||||
// {
|
||||
// UserName = model.Email,
|
||||
// Email = model.Email,
|
||||
// CardHolderName = model.User.CardHolderName,
|
||||
// CardNumber = model.User.CardNumber,
|
||||
// CardType = model.User.CardType,
|
||||
// City = model.User.City,
|
||||
// Country = model.User.Country,
|
||||
// Expiration = model.User.Expiration,
|
||||
// LastName = model.User.LastName,
|
||||
// Name = model.User.Name,
|
||||
// Street = model.User.Street,
|
||||
// State = model.User.State,
|
||||
// ZipCode = model.User.ZipCode,
|
||||
// PhoneNumber = model.User.PhoneNumber,
|
||||
// SecurityNumber = model.User.SecurityNumber
|
||||
// };
|
||||
// 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: HttpContext.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);
|
||||
// _logger.LogInformation(3, "User created a new account with password.");
|
||||
// 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();
|
||||
// _logger.LogInformation(4, "User logged out.");
|
||||
// return RedirectToAction(nameof(CatalogController.Index), "Catalog");
|
||||
//}
|
||||
|
||||
////
|
||||
//// POST: /Account/ExternalLogin
|
||||
//[HttpPost]
|
||||
//[AllowAnonymous]
|
||||
//[ValidateAntiForgeryToken]
|
||||
//public IActionResult ExternalLogin(string provider, string returnUrl = null)
|
||||
//{
|
||||
// // Request a redirect to the external login provider.
|
||||
// var redirectUrl = Url.Action("ExternalLoginCallback", "Account", new { ReturnUrl = returnUrl });
|
||||
// var properties = _signInManager.ConfigureExternalAuthenticationProperties(provider, redirectUrl);
|
||||
// return Challenge(properties, provider);
|
||||
//}
|
||||
|
||||
////
|
||||
//// GET: /Account/ExternalLoginCallback
|
||||
//[HttpGet]
|
||||
//[AllowAnonymous]
|
||||
//public async Task<IActionResult> ExternalLoginCallback(string returnUrl = null, string remoteError = null)
|
||||
//{
|
||||
// if (remoteError != null)
|
||||
// {
|
||||
// ModelState.AddModelError(string.Empty, $"Error from external provider: {remoteError}");
|
||||
// return View(nameof(Login));
|
||||
// }
|
||||
// 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)
|
||||
// {
|
||||
// _logger.LogInformation(5, "User logged in with {Name} provider.", info.LoginProvider);
|
||||
// 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.Principal.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 (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);
|
||||
// _logger.LogInformation(6, "User created an account using {Name} provider.", info.LoginProvider);
|
||||
// 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: HttpContext.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 });
|
||||
//}
|
||||
|
||||
////
|
||||
//// 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)
|
||||
// {
|
||||
// _logger.LogWarning(7, "User account locked out.");
|
||||
// return View("Lockout");
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// ModelState.AddModelError(string.Empty, "Invalid code.");
|
||||
// return View(model);
|
||||
// }
|
||||
//}
|
||||
|
||||
//#region Helpers
|
||||
|
||||
//private void AddErrors(IdentityResult result)
|
||||
//{
|
||||
// foreach (var error in result.Errors)
|
||||
// {
|
||||
// ModelState.AddModelError(string.Empty, error.Description);
|
||||
// }
|
||||
//}
|
||||
|
||||
//private Task<ApplicationUser> GetCurrentUserAsync()
|
||||
//{
|
||||
// return _userManager.GetUserAsync(HttpContext.User);
|
||||
//}
|
||||
|
||||
//private IActionResult RedirectToLocal(string returnUrl)
|
||||
//{
|
||||
// if (Url.IsLocalUrl(returnUrl))
|
||||
// {
|
||||
// return Redirect(returnUrl);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// return RedirectToAction(nameof(CatalogController.Index), "Catalog");
|
||||
// }
|
||||
//}
|
||||
|
||||
//#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@ -6,6 +6,7 @@ using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.eShopOnContainers.WebMVC.Services;
|
||||
using Microsoft.eShopOnContainers.WebMVC.Models;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Authentication;
|
||||
|
||||
namespace Microsoft.eShopOnContainers.WebMVC.Controllers
|
||||
{
|
||||
|
||||
@ -7,6 +7,8 @@ using Microsoft.AspNetCore.Http;
|
||||
using System.Net.Http;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Newtonsoft.Json;
|
||||
using Microsoft.AspNetCore.Authentication;
|
||||
using Microsoft.eShopOnContainers.WebMVC.Extensions;
|
||||
|
||||
namespace Microsoft.eShopOnContainers.WebMVC.Services
|
||||
{
|
||||
@ -15,16 +17,23 @@ namespace Microsoft.eShopOnContainers.WebMVC.Services
|
||||
private readonly IOptions<AppSettings> _settings;
|
||||
private HttpClient _apiClient;
|
||||
private readonly string _remoteServiceBaseUrl;
|
||||
private IHttpContextAccessor _httpContextAccesor;
|
||||
|
||||
public BasketService(IOptions<AppSettings> settings)
|
||||
public BasketService(IOptions<AppSettings> settings, IHttpContextAccessor httpContextAccesor)
|
||||
{
|
||||
_settings = settings;
|
||||
_remoteServiceBaseUrl = _settings.Value.BasketUrl;
|
||||
_httpContextAccesor = httpContextAccesor;
|
||||
}
|
||||
|
||||
public async Task<Basket> GetBasket(ApplicationUser user)
|
||||
{
|
||||
var context = _httpContextAccesor.HttpContext;
|
||||
var token = await context.Authentication.GetTokenAsync("access_token");
|
||||
|
||||
_apiClient = new HttpClient();
|
||||
_apiClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token);
|
||||
|
||||
var basketUrl = $"{_remoteServiceBaseUrl}/{user.Id.ToString()}";
|
||||
var dataString = await _apiClient.GetStringAsync(basketUrl);
|
||||
var response = JsonConvert.DeserializeObject<Basket>(dataString);
|
||||
@ -41,7 +50,12 @@ namespace Microsoft.eShopOnContainers.WebMVC.Services
|
||||
|
||||
public async Task<Basket> UpdateBasket(Basket basket)
|
||||
{
|
||||
var context = _httpContextAccesor.HttpContext;
|
||||
var token = await context.Authentication.GetTokenAsync("access_token");
|
||||
|
||||
_apiClient = new HttpClient();
|
||||
_apiClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token);
|
||||
|
||||
var basketUrl = _remoteServiceBaseUrl;
|
||||
StringContent content = new StringContent(JsonConvert.SerializeObject(basket), System.Text.Encoding.UTF8, "application/json");
|
||||
var response = await _apiClient.PostAsync(basketUrl, content);
|
||||
@ -106,7 +120,11 @@ namespace Microsoft.eShopOnContainers.WebMVC.Services
|
||||
|
||||
public async Task CleanBasket(ApplicationUser user)
|
||||
{
|
||||
var context = _httpContextAccesor.HttpContext;
|
||||
var token = await context.Authentication.GetTokenAsync("access_token");
|
||||
|
||||
_apiClient = new HttpClient();
|
||||
_apiClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token);
|
||||
var basketUrl = $"{_remoteServiceBaseUrl}/{user.Id.ToString()}";
|
||||
var response = await _apiClient.DeleteAsync(basketUrl);
|
||||
|
||||
|
||||
@ -11,6 +11,7 @@ using Microsoft.eShopOnContainers.WebMVC.Models;
|
||||
using Microsoft.eShopOnContainers.WebMVC.Services;
|
||||
using System.IdentityModel.Tokens.Jwt;
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
|
||||
namespace Microsoft.eShopOnContainers.WebMVC
|
||||
{
|
||||
@ -38,17 +39,11 @@ namespace Microsoft.eShopOnContainers.WebMVC
|
||||
// This method gets called by the runtime. Use this method to add services to the container.
|
||||
public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
// Add framework services.
|
||||
//services.AddDbContext<ApplicationDbContext>(options =>
|
||||
// options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
|
||||
|
||||
//services.AddIdentity<ApplicationUser, IdentityRole>()
|
||||
// .AddEntityFrameworkStores<ApplicationDbContext>()
|
||||
// .AddDefaultTokenProviders();
|
||||
|
||||
services.AddMvc();
|
||||
|
||||
// Add application services.
|
||||
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
|
||||
|
||||
services.AddTransient<ICatalogService, CatalogService>();
|
||||
services.AddSingleton<IOrderingService, OrderingService>(); //CCE: Once services are integrated, a singleton is not needed we can left transient.
|
||||
services.AddTransient<IBasketService, BasketService>();
|
||||
@ -83,8 +78,6 @@ namespace Microsoft.eShopOnContainers.WebMVC
|
||||
AutomaticAuthenticate = true,
|
||||
});
|
||||
|
||||
//app.UseIdentity();
|
||||
|
||||
var oidcOptions = new OpenIdConnectOptions
|
||||
{
|
||||
AuthenticationScheme = "oidc",
|
||||
@ -96,27 +89,16 @@ namespace Microsoft.eShopOnContainers.WebMVC
|
||||
ResponseType = "code id_token",
|
||||
SaveTokens = true,
|
||||
GetClaimsFromUserInfoEndpoint = true,
|
||||
RequireHttpsMetadata = false,
|
||||
|
||||
//TokenValidationParameters = new TokenValidationParameters
|
||||
//{
|
||||
// NameClaimType = "name",
|
||||
// RoleClaimType = "role"
|
||||
//}
|
||||
RequireHttpsMetadata = false,
|
||||
};
|
||||
|
||||
oidcOptions.Scope.Clear();
|
||||
oidcOptions.Scope.Add("openid");
|
||||
oidcOptions.Scope.Add("profile");
|
||||
oidcOptions.Scope.Add("orders");
|
||||
oidcOptions.Scope.Add("basket");
|
||||
|
||||
app.UseOpenIdConnectAuthentication(oidcOptions);
|
||||
app.UseJwtBearerAuthentication(new JwtBearerOptions
|
||||
{
|
||||
Authority = "http://localhost:5000/", // base address of your OIDC server.
|
||||
Audience = "http://localhost:5000/", // base address of your API.
|
||||
RequireHttpsMetadata = false
|
||||
});
|
||||
|
||||
app.UseMvc(routes =>
|
||||
{
|
||||
|
||||
@ -31,6 +31,7 @@ namespace Microsoft.eShopOnContainers.WebMVC.ViewComponents
|
||||
{
|
||||
var basket = await _cartSvc.GetBasket(user);
|
||||
return basket.Items.Count;
|
||||
return await Task<int>.Run(()=> { return 0; });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
|
||||
@if(Context.User.Identity.IsAuthenticated)
|
||||
{
|
||||
<form asp-area="" asp-controller="Account" asp-action="LogOff" method="post" id="logoutForm" class="navbar-right">
|
||||
<form asp-area="" asp-controller="Account" asp-action="SignOut" method="post" id="logoutForm" class="navbar-right">
|
||||
<div class="nav navbar-nav navbar-right mt-15">
|
||||
@await Component.InvokeAsync("Cart", new { user = UserManager.Parse(User) })
|
||||
<div class="fr login-user">
|
||||
|
||||
@ -4,9 +4,9 @@
|
||||
//"DefaultConnection": "Server=identity.data;Database=aspnet-Microsoft.eShopOnContainers.WebMVC;User Id=sa;Password=Pass@word"
|
||||
},
|
||||
"CatalogUrl": "http://localhost:5101",
|
||||
"OrderingUrl": "http://localhost:2446",
|
||||
"OrderingUrl": "http://localhost:5102",
|
||||
"BasketUrl": "http://localhost:5103",
|
||||
"IdentityUrl": "http://localhost:5000",
|
||||
"IdentityUrl": "http://localhost:5105",
|
||||
"Logging": {
|
||||
"IncludeScopes": false,
|
||||
"LogLevel": {
|
||||
|
||||
@ -18,6 +18,7 @@ namespace eShopConContainers.WebSPA
|
||||
.UseConfiguration(config)
|
||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||
.UseIISIntegration()
|
||||
.UseUrls("http://localhost:1250/")
|
||||
.UseStartup<Startup>()
|
||||
.Build();
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user