diff --git a/docker-compose.override.yml b/docker-compose.override.yml
index e5cadd087..48fd03b99 100644
--- a/docker-compose.override.yml
+++ b/docker-compose.override.yml
@@ -21,11 +21,11 @@ services:
webspa:
environment:
- - CatalogUrl=http://catalog.api:5101
- - OrderingUrl=http://ordering.api:5102
+ - CatalogUrl=http://10.0.75.1:5101
+ - OrderingUrl=http://10.0.75.1:5102
#- IdentityUrl=http://13.88.8.119:5105 #Remote: VM Needs to have public access at 5105.
- IdentityUrl=http://10.0.75.1:5105 #Local: You need to open your local dev-machine firewall at range 5100-5105. at range 5100-5105.
- - BasketUrl=http://basket.api:5103
+ - BasketUrl=http://10.0.75.1:5103
ports:
- "5104:5104"
@@ -40,7 +40,7 @@ services:
catalog.api:
environment:
- ConnectionString=Server=sql.data;Database=Microsoft.eShopOnContainers.Services.CatalogDb;User Id=sa;Password=Pass@word
- - ExternalCatalogBaseUrl=http://10.0.75.1:5101 #Local
+ - ExternalCatalogBaseUrl=http://10.0.75.1:5101 #Local
#- ExternalCatalogBaseUrl=http://13.88.8.119:5101 #Remote
ports:
- "5101:5101"
diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/ViewModels/SettingsViewModel.cs b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/ViewModels/SettingsViewModel.cs
index bfbcc96d8..1fa5b54b6 100644
--- a/src/Mobile/eShopOnContainers/eShopOnContainers.Core/ViewModels/SettingsViewModel.cs
+++ b/src/Mobile/eShopOnContainers/eShopOnContainers.Core/ViewModels/SettingsViewModel.cs
@@ -93,8 +93,8 @@ namespace eShopOnContainers.Core.ViewModels
}
else
{
- Title = "Use Azure Services";
- Description = "Azure Services are real objects that required a valid internet connection";
+ Title = "Use Microservices/Containers from eShopOnContainers";
+ Description = "When enabling the use of microservices/containers the Xamarin.Forms app will try to use real services deployed as Docker containers in the specified base IP that will need to be reachable through the network";
}
}
diff --git a/src/Mobile/eShopOnContainers/eShopOnContainers.TestRunner.Droid/eShopOnContainers.TestRunner.Droid.csproj b/src/Mobile/eShopOnContainers/eShopOnContainers.TestRunner.Droid/eShopOnContainers.TestRunner.Droid.csproj
index ffa9c0b55..c9cb8a265 100644
--- a/src/Mobile/eShopOnContainers/eShopOnContainers.TestRunner.Droid/eShopOnContainers.TestRunner.Droid.csproj
+++ b/src/Mobile/eShopOnContainers/eShopOnContainers.TestRunner.Droid/eShopOnContainers.TestRunner.Droid.csproj
@@ -16,7 +16,7 @@
Resources\Resource.Designer.cs
Off
True
- v7.0
+ v6.0
Properties\AndroidManifest.xml
diff --git a/src/Services/Ordering/Ordering.API/Infrastructure/Auth/AuthorizationHeaderParameterOperationFilter.cs b/src/Services/Ordering/Ordering.API/Infrastructure/Auth/AuthorizationHeaderParameterOperationFilter.cs
new file mode 100644
index 000000000..94e2a48c2
--- /dev/null
+++ b/src/Services/Ordering/Ordering.API/Infrastructure/Auth/AuthorizationHeaderParameterOperationFilter.cs
@@ -0,0 +1,35 @@
+using Microsoft.AspNetCore.Mvc.Authorization;
+using Swashbuckle.Swagger.Model;
+using Swashbuckle.SwaggerGen.Generator;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace Microsoft.eShopOnContainers.Services.Ordering.API.Infrastructure.Auth
+{
+ public class AuthorizationHeaderParameterOperationFilter : IOperationFilter
+ {
+ public void Apply(Operation operation, OperationFilterContext context)
+ {
+ var filterPipeline = context.ApiDescription.ActionDescriptor.FilterDescriptors;
+ var isAuthorized = filterPipeline.Select(filterInfo => filterInfo.Filter).Any(filter => filter is AuthorizeFilter);
+ var allowAnonymous = filterPipeline.Select(filterInfo => filterInfo.Filter).Any(filter => filter is IAllowAnonymousFilter);
+
+ if (isAuthorized && !allowAnonymous)
+ {
+ if (operation.Parameters == null)
+ operation.Parameters = new List();
+
+ operation.Parameters.Add(new NonBodyParameter
+ {
+ Name = "Authorization",
+ In = "header",
+ Description = "access token",
+ Required = true,
+ Type = "string"
+ });
+ }
+ }
+ }
+}
diff --git a/src/Services/Ordering/Ordering.API/Startup.cs b/src/Services/Ordering/Ordering.API/Startup.cs
index a9883c764..05a7defbb 100644
--- a/src/Services/Ordering/Ordering.API/Startup.cs
+++ b/src/Services/Ordering/Ordering.API/Startup.cs
@@ -4,6 +4,7 @@
using Autofac;
using Autofac.Extensions.DependencyInjection;
using Infrastructure;
+ using Infrastructure.Auth;
using Infrastructure.AutofacModules;
using Infrastructure.Filters;
using Infrastructure.Services;
@@ -41,7 +42,6 @@
public IServiceProvider ConfigureServices(IServiceCollection services)
{
// Add framework services.
-
services.AddMvc(options =>
{
options.Filters.Add(typeof(HttpGlobalExceptionFilter));
@@ -57,6 +57,7 @@
services.AddSwaggerGen();
services.ConfigureSwaggerGen(options =>
{
+ options.OperationFilter();
options.DescribeAllEnumsAsStrings();
options.SingleApiVersion(new Swashbuckle.Swagger.Model.Info()
{
diff --git a/src/Web/WebMVC/Startup.cs b/src/Web/WebMVC/Startup.cs
index 49106f017..c6020eeeb 100644
--- a/src/Web/WebMVC/Startup.cs
+++ b/src/Web/WebMVC/Startup.cs
@@ -25,13 +25,13 @@ namespace Microsoft.eShopOnContainers.WebMVC
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) // Settings for the application
.AddEnvironmentVariables(); // override settings with environment variables set in compose.
-
- //if (env.IsDevelopment())
- //{
- // // For more details on using the user secret store see http://go.microsoft.com/fwlink/?LinkID=532709
- // builder.AddUserSecrets();
- //}
+
+ if (env.IsDevelopment())
+ {
+ // For more details on using the user secret store see http://go.microsoft.com/fwlink/?LinkID=532709
+ builder.AddUserSecrets();
+ }
Configuration = builder.Build();
}
diff --git a/src/Web/WebSPA/eShopOnContainers.WebSPA/AppSettings.cs b/src/Web/WebSPA/eShopOnContainers.WebSPA/AppSettings.cs
new file mode 100644
index 000000000..19e2b5cfe
--- /dev/null
+++ b/src/Web/WebSPA/eShopOnContainers.WebSPA/AppSettings.cs
@@ -0,0 +1,15 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace eShopOnContainers.WebSPA
+{
+ public class AppSettings
+ {
+ public string CatalogUrl { get; set; }
+ public string OrderingUrl { get; set; }
+ public string IdentityUrl { get; set; }
+ public string BasketUrl { get; set; }
+ }
+}
diff --git a/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/app.component.ts b/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/app.component.ts
index 22c9d76ab..00abe4ad4 100644
--- a/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/app.component.ts
+++ b/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/app.component.ts
@@ -5,6 +5,7 @@ import { Subscription } from 'rxjs/Subscription';
import { DataService } from './shared/services/data.service';
import { SecurityService } from './shared/services/security.service';
+import { ConfigurationService } from './shared/services/configuration.service';
/*
* App Component
@@ -20,13 +21,17 @@ export class AppComponent implements OnInit {
private Authenticated: boolean = false;
subscription: Subscription;
- constructor(private titleService: Title, private securityService: SecurityService) {
+ constructor(private titleService: Title, private securityService: SecurityService, private configurationService: ConfigurationService) {
this.Authenticated = this.securityService.IsAuthorized;
}
ngOnInit() {
console.log('app on init');
this.subscription = this.securityService.authenticationChallenge$.subscribe(res => this.Authenticated = res);
+
+ //Get configuration from server environment variables:
+ console.log('configuration');
+ this.configurationService.load();
}
public setTitle(newTitle: string) {
diff --git a/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/basket/basket-status/basket-status.component.ts b/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/basket/basket-status/basket-status.component.ts
index a9617978f..0680fefa0 100644
--- a/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/basket/basket-status/basket-status.component.ts
+++ b/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/basket/basket-status/basket-status.component.ts
@@ -4,6 +4,7 @@ import { Subscription } from 'rxjs/Subscription';
import { BasketService } from '../basket.service';
import { BasketWrapperService } from '../../shared/services/basket.wrapper.service';
import { SecurityService } from '../../shared/services/security.service';
+import { ConfigurationService } from '../../shared/services/configuration.service';
@Component({
selector: 'esh-basket-status',
@@ -17,7 +18,7 @@ export class BasketStatusComponent implements OnInit {
badge: number = 0;
- constructor(private service: BasketService, private basketEvents: BasketWrapperService, private authService: SecurityService) { }
+ constructor(private service: BasketService, private basketEvents: BasketWrapperService, private authService: SecurityService, private configurationService: ConfigurationService) { }
ngOnInit() {
// Subscribe to Add Basket Observable:
@@ -25,7 +26,8 @@ export class BasketStatusComponent implements OnInit {
item => {
this.service.setBasket(item).subscribe(res => {
this.service.getBasket().subscribe(basket => {
- this.badge = basket.items.length;
+ if (basket)
+ this.badge = basket.items.length;
});
});
});
@@ -33,20 +35,30 @@ export class BasketStatusComponent implements OnInit {
// Subscribe to Drop Basket Observable:
this.basketDroppedSubscription = this.service.basketDroped$.subscribe(res => {
this.badge = 0;
- console.log('dropped event fired');
});
// Subscribe to login and logout observable
this.authSubscription = this.authService.authenticationChallenge$.subscribe(res => {
this.service.getBasket().subscribe(basket => {
- this.badge = basket.items.length;
+ if (basket != null)
+ this.badge = basket.items.length;
});
});
// Init:
- this.service.getBasket().subscribe(basket => {
- this.badge = basket.items.length;
- });
+ if (this.configurationService.isReady) {
+ this.service.getBasket().subscribe(basket => {
+ if (basket != null)
+ this.badge = basket.items.length;
+ });
+ } else {
+ this.configurationService.settingsLoaded$.subscribe(x => {
+ this.service.getBasket().subscribe(basket => {
+ if (basket != null)
+ this.badge = basket.items.length;
+ });
+ });
+ }
}
}
diff --git a/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/basket/basket.service.ts b/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/basket/basket.service.ts
index 0227b7a2d..4417eaad5 100644
--- a/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/basket/basket.service.ts
+++ b/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/basket/basket.service.ts
@@ -7,6 +7,8 @@ import { SecurityService } from '../shared/services/security.service';
import { IBasket } from '../shared/models/basket.model';
import { IBasketItem } from '../shared/models/basketItem.model';
import { BasketWrapperService } from '../shared/services/basket.wrapper.service';
+import { ConfigurationService } from '../shared/services/configuration.service';
+import { StorageService } from '../shared/services/storage.service';
import 'rxjs/Rx';
import { Observable } from 'rxjs/Observable';
@@ -14,11 +16,11 @@ import 'rxjs/add/observable/throw';
import { Observer } from 'rxjs/Observer';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
-import { Subject } from 'rxjs/Subject';
+import { Subject } from 'rxjs/Subject';
@Injectable()
export class BasketService {
- private basketUrl: string = 'http://eshopcontainers:5103';
+ private basketUrl: string = '';
basket: IBasket = {
buyerId: '',
items: []
@@ -28,16 +30,23 @@ export class BasketService {
private basketDropedSource = new Subject();
basketDroped$ = this.basketDropedSource.asObservable();
- constructor(private service: DataService, private authService: SecurityService, private basketEvents: BasketWrapperService, private router: Router) {
+ constructor(private service: DataService, private authService: SecurityService, private basketEvents: BasketWrapperService, private router: Router, private configurationService: ConfigurationService, private storageService: StorageService) {
this.basket.items = [];
-
+
// Init:
if (this.authService.IsAuthorized) {
if (this.authService.UserData) {
this.basket.buyerId = this.authService.UserData.sub;
- this.getBasket().subscribe(basket => {
- this.basket = basket;
- });
+ if (this.configurationService.isReady) {
+ this.basketUrl = this.configurationService.serverSettings.basketUrl;
+ this.loadData();
+ }
+ else {
+ this.configurationService.settingsLoaded$.subscribe(x => {
+ this.basketUrl = this.configurationService.serverSettings.basketUrl;
+ this.loadData();
+ });
+ }
}
}
@@ -45,7 +54,7 @@ export class BasketService {
this.dropBasket();
});
}
-
+
setBasket(item): Observable {
this.basket.items.push(item);
return this.service.post(this.basketUrl + '/', this.basket).map((response: Response) => {
@@ -55,12 +64,24 @@ export class BasketService {
getBasket(): Observable {
return this.service.get(this.basketUrl + '/' + this.basket.buyerId).map((response: Response) => {
+ if (response.status === 204) {
+ return null;
+ }
+
return response.json();
});
}
dropBasket() {
+ this.basket.items = [];
this.service.delete(this.basketUrl + '/' + this.basket.buyerId);
this.basketDropedSource.next();
}
+
+ private loadData() {
+ this.getBasket().subscribe(basket => {
+ if (basket != null)
+ this.basket.items = basket.items;
+ });
+ }
}
\ No newline at end of file
diff --git a/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/catalog/catalog.component.ts b/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/catalog/catalog.component.ts
index 5ae78fd9c..db6a4c7be 100644
--- a/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/catalog/catalog.component.ts
+++ b/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/catalog/catalog.component.ts
@@ -1,5 +1,6 @@
import { Component, OnInit } from '@angular/core';
import { CatalogService } from './catalog.service';
+import { ConfigurationService } from '../shared/services/configuration.service';
import { ICatalog } from '../shared/models/catalog.model';
import { ICatalogItem } from '../shared/models/catalogItem.model';
import { ICatalogType } from '../shared/models/catalogType.model';
@@ -20,9 +21,19 @@ export class CatalogComponent implements OnInit {
typeSelected: number;
paginationInfo: IPager;
- constructor(private service: CatalogService, private basketService: BasketWrapperService) { }
+ constructor(private service: CatalogService, private basketService: BasketWrapperService, private configurationService: ConfigurationService) { }
ngOnInit() {
+ if (this.configurationService.isReady) {
+ this.loadData();
+ }else{
+ this.configurationService.settingsLoaded$.subscribe(x => {
+ this.loadData();
+ });
+ }
+ }
+
+ loadData() {
this.getBrands();
this.getCatalog(10, 0);
this.getTypes();
diff --git a/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/catalog/catalog.service.ts b/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/catalog/catalog.service.ts
index f79840179..bdcb9d664 100644
--- a/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/catalog/catalog.service.ts
+++ b/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/catalog/catalog.service.ts
@@ -2,6 +2,7 @@ import { Injectable } from '@angular/core';
import { Response } from '@angular/http';
import { DataService } from '../shared/services/data.service';
+import { ConfigurationService } from '../shared/services/configuration.service';
import { ICatalog } from '../shared/models/catalog.model';
import { ICatalogBrand } from '../shared/models/catalogBrand.model';
import { ICatalogType } from '../shared/models/catalogType.model';
@@ -14,11 +15,16 @@ import 'rxjs/add/operator/map';
@Injectable()
export class CatalogService {
- private catalogUrl: string = 'http://eshopcontainers:5101/api/v1/catalog/items';
- private brandUrl: string = 'http://eshopcontainers:5101/api/v1/catalog/catalogbrands';
- private typesUrl: string = 'http://eshopcontainers:5101/api/v1/catalog/catalogtypes';
-
- constructor(private service: DataService) {
+ private catalogUrl: string = '';
+ private brandUrl: string = '';
+ private typesUrl: string = '';
+
+ constructor(private service: DataService, private configurationService: ConfigurationService) {
+ this.configurationService.settingsLoaded$.subscribe(x => {
+ this.catalogUrl = this.configurationService.serverSettings.catalogUrl + '/api/v1/catalog/items';
+ this.brandUrl = this.configurationService.serverSettings.catalogUrl + '/api/v1/catalog/catalogbrands';
+ this.typesUrl = this.configurationService.serverSettings.catalogUrl + '/api/v1/catalog/catalogtypes';
+ });
}
getCatalog(pageIndex: number, pageSize: number, brand: number, type: number): Observable {
@@ -45,4 +51,4 @@ export class CatalogService {
return response.json();
});
};
-}
\ No newline at end of file
+}
diff --git a/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/orders/orders.component.ts b/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/orders/orders.component.ts
index 218b692f3..78d52a132 100644
--- a/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/orders/orders.component.ts
+++ b/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/orders/orders.component.ts
@@ -1,6 +1,7 @@
import { Component, OnInit } from '@angular/core';
import { OrdersService } from './orders.service';
import { IOrder } from '../shared/models/order.model';
+import { ConfigurationService } from '../shared/services/configuration.service';
@Component({
selector: 'esh-orders',
@@ -10,10 +11,16 @@ import { IOrder } from '../shared/models/order.model';
export class OrdersComponent implements OnInit {
orders: IOrder[];
- constructor(private service: OrdersService) { }
+ constructor(private service: OrdersService, private configurationService: ConfigurationService) { }
ngOnInit() {
- this.getOrders();
+ if (this.configurationService.isReady) {
+ this.getOrders()
+ } else {
+ this.configurationService.settingsLoaded$.subscribe(x => {
+ this.getOrders();
+ });
+ }
}
diff --git a/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/orders/orders.service.ts b/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/orders/orders.service.ts
index 8d0b4d91a..20899b9a9 100644
--- a/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/orders/orders.service.ts
+++ b/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/orders/orders.service.ts
@@ -5,6 +5,7 @@ import { DataService } from '../shared/services/data.service';
import { IOrder } from '../shared/models/order.model';
import { IOrderItem } from '../shared/models/orderItem.model';
import { SecurityService } from '../shared/services/security.service';
+import { ConfigurationService } from '../shared/services/configuration.service';
import { BasketWrapperService } from '../shared/services/basket.wrapper.service';
import 'rxjs/Rx';
@@ -16,13 +17,18 @@ import 'rxjs/add/operator/map';
@Injectable()
export class OrdersService {
- private ordersUrl: string = 'http://eshopcontainers:5102/api/v1/orders';
+ private ordersUrl: string = '';
+
+ constructor(private service: DataService, private basketService: BasketWrapperService, private identityService: SecurityService, private configurationService: ConfigurationService) {
+ if (this.configurationService.isReady)
+ this.ordersUrl = this.configurationService.serverSettings.orderingUrl;
+ else
+ this.configurationService.settingsLoaded$.subscribe(x => this.ordersUrl = this.configurationService.serverSettings.orderingUrl);
- constructor(private service: DataService, private basketService: BasketWrapperService, private identityService: SecurityService) {
}
getOrders(): Observable {
- let url = this.ordersUrl;
+ let url = this.ordersUrl + '/api/v1/orders';
return this.service.get(url).map((response: Response) => {
return response.json();
@@ -30,7 +36,7 @@ export class OrdersService {
}
getOrder(id: number): Observable {
- let url = `${this.ordersUrl}/${id}`;
+ let url = this.ordersUrl + '/api/v1/orders/' + id;
return this.service.get(url).map((response: Response) => {
return response.json();
@@ -38,7 +44,7 @@ export class OrdersService {
}
postOrder(item): Observable {
- return this.service.post(this.ordersUrl + '/new', item).map((response: Response) => {
+ return this.service.post(this.ordersUrl + '/api/v1/orders/new', item).map((response: Response) => {
return true;
});
}
diff --git a/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/models/configuration.model.ts b/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/models/configuration.model.ts
new file mode 100644
index 000000000..74efe89a4
--- /dev/null
+++ b/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/models/configuration.model.ts
@@ -0,0 +1,6 @@
+export interface IConfiguration {
+ catalogUrl: string,
+ orderingUrl: string,
+ identityUrl: string,
+ basketUrl: string
+}
\ No newline at end of file
diff --git a/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/services/configuration.service.ts b/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/services/configuration.service.ts
new file mode 100644
index 000000000..bfe672e5e
--- /dev/null
+++ b/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/services/configuration.service.ts
@@ -0,0 +1,38 @@
+import { Injectable } from '@angular/core';
+import { Http, Response, RequestOptionsArgs, RequestMethod, Headers } from '@angular/http';
+import { IConfiguration } from '../models/configuration.model';
+import { StorageService } from './storage.service';
+
+import 'rxjs/Rx';
+import { Observable } from 'rxjs/Observable';
+import 'rxjs/add/observable/throw';
+import { Observer } from 'rxjs/Observer';
+import 'rxjs/add/operator/map';
+import { Subject } from 'rxjs/Subject';
+
+
+@Injectable()
+export class ConfigurationService {
+ serverSettings: IConfiguration;
+ // observable that is fired when settings are loaded from server
+ private settingsLoadedSource = new Subject();
+ settingsLoaded$ = this.settingsLoadedSource.asObservable();
+ isReady: boolean = false;
+
+ constructor(private http: Http, private storageService: StorageService) { }
+
+ load() {
+ let url = "http://localhost:5104/Home/Configuration";
+ this.http.get(url).subscribe((response: Response) => {
+ console.log('server settings loaded');
+ this.serverSettings = response.json();
+ console.log(this.serverSettings);
+ this.storageService.store('basketUrl', this.serverSettings.basketUrl);
+ this.storageService.store('catalogUrl', this.serverSettings.catalogUrl);
+ this.storageService.store('identityUrl', this.serverSettings.identityUrl);
+ this.storageService.store('orderingUrl', this.serverSettings.orderingUrl);
+ this.isReady = true;
+ this.settingsLoadedSource.next();
+ });
+ }
+}
diff --git a/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/services/security.service.ts b/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/services/security.service.ts
index c3e15806d..47e70a60a 100644
--- a/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/services/security.service.ts
+++ b/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/services/security.service.ts
@@ -5,58 +5,66 @@ import { Observable } from 'rxjs/Observable';
import { Subject } from 'rxjs/Subject';
import { Router } from '@angular/router';
import { ActivatedRoute } from '@angular/router';
+import { ConfigurationService } from './configuration.service';
+import { StorageService } from './storage.service';
@Injectable()
export class SecurityService {
private actionUrl: string;
private headers: Headers;
- private storage: any;
+ private storage: StorageService;
private authenticationSource = new Subject();
authenticationChallenge$ = this.authenticationSource.asObservable();
+ private authorityUrl = '';
- constructor(private _http: Http, private _router: Router, private route: ActivatedRoute) {
+ constructor(private _http: Http, private _router: Router, private route: ActivatedRoute, private _configurationService: ConfigurationService, private _storageService: StorageService) {
this.headers = new Headers();
this.headers.append('Content-Type', 'application/json');
this.headers.append('Accept', 'application/json');
- this.storage = sessionStorage; // localStorage;
+ this.storage = _storageService;
- if (this.retrieve('IsAuthorized') !== '') {
- this.IsAuthorized = this.retrieve('IsAuthorized');
+ this._configurationService.settingsLoaded$.subscribe(x => {
+ this.authorityUrl = this._configurationService.serverSettings.identityUrl
+ this.storage.store('IdentityUrl', this.authorityUrl);
+ });
+
+ if (this.storage.retrieve('IsAuthorized') !== '') {
+ this.IsAuthorized = this.storage.retrieve('IsAuthorized');
this.authenticationSource.next(true);
- this.UserData = this.retrieve('userData');
+ this.UserData = this.storage.retrieve('userData');
}
}
public IsAuthorized: boolean;
public GetToken(): any {
- return this.retrieve('authorizationData');
+ return this.storage.retrieve('authorizationData');
}
public ResetAuthorizationData() {
- this.store('authorizationData', '');
- this.store('authorizationDataIdToken', '');
+ this.storage.store('authorizationData', '');
+ this.storage.store('authorizationDataIdToken', '');
this.IsAuthorized = false;
- this.store('IsAuthorized', false);
+ this.storage.store('IsAuthorized', false);
}
public UserData: any;
public SetAuthorizationData(token: any, id_token: any) {
- if (this.retrieve('authorizationData') !== '') {
- this.store('authorizationData', '');
+ if (this.storage.retrieve('authorizationData') !== '') {
+ this.storage.store('authorizationData', '');
}
- this.store('authorizationData', token);
- this.store('authorizationDataIdToken', id_token);
+ this.storage.store('authorizationData', token);
+ this.storage.store('authorizationDataIdToken', id_token);
this.IsAuthorized = true;
- this.store('IsAuthorized', true);
+ this.storage.store('IsAuthorized', true);
this.getUserData()
.subscribe(data => {
this.UserData = data;
- this.store('userData', data);
+ this.storage.store('userData', data);
// emit observable
this.authenticationSource.next(true);
window.location.href = 'http://localhost:5104';
@@ -70,7 +78,7 @@ export class SecurityService {
public Authorize() {
this.ResetAuthorizationData();
- let authorizationUrl = 'http://10.0.75.1:5105/connect/authorize';
+ let authorizationUrl = this.authorityUrl + '/connect/authorize';
let client_id = 'js';
let redirect_uri = 'http://localhost:5104/';
let response_type = 'id_token token';
@@ -78,8 +86,8 @@ export class SecurityService {
let nonce = 'N' + Math.random() + '' + Date.now();
let state = Date.now() + '' + Math.random();
- this.store('authStateControl', state);
- this.store('authNonce', nonce);
+ this.storage.store('authStateControl', state);
+ this.storage.store('authNonce', nonce);
let url =
authorizationUrl + '?' +
@@ -112,7 +120,7 @@ export class SecurityService {
if (!result.error) {
- if (result.state !== this.retrieve('authStateControl')) {
+ if (result.state !== this.storage.retrieve('authStateControl')) {
console.log('AuthorizedCallback incorrect state');
} else {
@@ -123,11 +131,11 @@ export class SecurityService {
console.log(dataIdToken);
// validate nonce
- if (dataIdToken.nonce !== this.retrieve('authNonce')) {
+ if (dataIdToken.nonce !== this.storage.retrieve('authNonce')) {
console.log('AuthorizedCallback incorrect nonce');
} else {
- this.store('authNonce', '');
- this.store('authStateControl', '');
+ this.storage.store('authNonce', '');
+ this.storage.store('authStateControl', '');
authResponseIsValid = true;
console.log('AuthorizedCallback state and nonce validated, returning access token');
@@ -142,8 +150,8 @@ export class SecurityService {
}
public Logoff() {
- let authorizationUrl = 'http://10.0.75.1:5105/connect/endsession';
- let id_token_hint = this.retrieve('authorizationDataIdToken');
+ let authorizationUrl = this.authorityUrl + '/connect/endsession';
+ let id_token_hint = this.storage.retrieve('authorizationDataIdToken');
let post_logout_redirect_uri = 'http://localhost:5104/';
let url =
@@ -197,23 +205,26 @@ export class SecurityService {
return data;
}
- private retrieve(key: string): any {
- let item = this.storage.getItem(key);
+ //private retrieve(key: string): any {
+ // let item = this.storage.getItem(key);
- if (item && item !== 'undefined') {
- return JSON.parse(this.storage.getItem(key));
- }
+ // if (item && item !== 'undefined') {
+ // return JSON.parse(this.storage.getItem(key));
+ // }
- return;
- }
+ // return;
+ //}
- private store(key: string, value: any) {
- this.storage.setItem(key, JSON.stringify(value));
- }
+ //private store(key: string, value: any) {
+ // this.storage.setItem(key, JSON.stringify(value));
+ //}
private getUserData = (): Observable => {
this.setHeaders();
- return this._http.get('http://10.0.75.1:5105/connect/userinfo', {
+ if (this.authorityUrl === '')
+ this.authorityUrl = this.storage.retrieve('IdentityUrl');
+
+ return this._http.get(this.authorityUrl + '/connect/userinfo', {
headers: this.headers,
body: ''
}).map(res => res.json());
diff --git a/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/services/storage.service.ts b/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/services/storage.service.ts
new file mode 100644
index 000000000..e11bd96be
--- /dev/null
+++ b/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/services/storage.service.ts
@@ -0,0 +1,24 @@
+import { Injectable } from '@angular/core';
+
+@Injectable()
+export class StorageService {
+ private storage: any;
+
+ constructor() {
+ this.storage = sessionStorage; // localStorage;
+ }
+
+ public retrieve(key: string): any {
+ let item = this.storage.getItem(key);
+
+ if (item && item !== 'undefined') {
+ return JSON.parse(this.storage.getItem(key));
+ }
+
+ return;
+ }
+
+ public store(key: string, value: any) {
+ this.storage.setItem(key, JSON.stringify(value));
+ }
+}
diff --git a/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/shared.module.ts b/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/shared.module.ts
index 4b6e60a40..64441396f 100644
--- a/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/shared.module.ts
+++ b/src/Web/WebSPA/eShopOnContainers.WebSPA/Client/modules/shared/shared.module.ts
@@ -9,6 +9,8 @@ import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
import { DataService } from './services/data.service';
import { BasketWrapperService} from './services/basket.wrapper.service';
import { SecurityService } from './services/security.service';
+import { ConfigurationService } from './services/configuration.service';
+import { StorageService } from './services/storage.service';
// Components:
import { Pager } from './components/pager/pager';
@@ -52,7 +54,9 @@ export class SharedModule {
// Providers
DataService,
BasketWrapperService,
- SecurityService
+ SecurityService,
+ ConfigurationService,
+ StorageService
]
};
}
diff --git a/src/Web/WebSPA/eShopOnContainers.WebSPA/Program.cs b/src/Web/WebSPA/eShopOnContainers.WebSPA/Program.cs
index 40099c4e9..ffad0461e 100644
--- a/src/Web/WebSPA/eShopOnContainers.WebSPA/Program.cs
+++ b/src/Web/WebSPA/eShopOnContainers.WebSPA/Program.cs
@@ -8,14 +8,8 @@ namespace eShopConContainers.WebSPA
{
public static void Main(string[] args)
{
- var config = new ConfigurationBuilder()
- .SetBasePath(Directory.GetCurrentDirectory())
- //.AddJsonFile("hosting.json", optional: true)
- .Build();
-
var host = new WebHostBuilder()
.UseKestrel()
- .UseConfiguration(config)
.UseContentRoot(Directory.GetCurrentDirectory())
.UseUrls("http://0.0.0.0:5104")
.UseIISIntegration()
diff --git a/src/Web/WebSPA/eShopOnContainers.WebSPA/Server/Controllers/HomeController.cs b/src/Web/WebSPA/eShopOnContainers.WebSPA/Server/Controllers/HomeController.cs
index c70a67769..ee980e334 100644
--- a/src/Web/WebSPA/eShopOnContainers.WebSPA/Server/Controllers/HomeController.cs
+++ b/src/Web/WebSPA/eShopOnContainers.WebSPA/Server/Controllers/HomeController.cs
@@ -3,16 +3,20 @@
using System.Linq;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
+using Microsoft.Extensions.Options;
+using eShopOnContainers.WebSPA;
namespace eShopConContainers.WebSPA.Server.Controllers
{
public class HomeController : Controller
{
private readonly IHostingEnvironment _env;
+ private readonly IOptions _settings;
- public HomeController(IHostingEnvironment env)
+ public HomeController(IHostingEnvironment env, IOptions settings)
{
_env = env;
+ _settings = settings;
}
public IActionResult Index()
@@ -31,5 +35,9 @@ namespace eShopConContainers.WebSPA.Server.Controllers
return file.Name;
}
+ public IActionResult Configuration()
+ {
+ return Json(_settings.Value);
+ }
}
}
diff --git a/src/Web/WebSPA/eShopOnContainers.WebSPA/Startup.cs b/src/Web/WebSPA/eShopOnContainers.WebSPA/Startup.cs
index 705ba34f2..907e32d49 100644
--- a/src/Web/WebSPA/eShopOnContainers.WebSPA/Startup.cs
+++ b/src/Web/WebSPA/eShopOnContainers.WebSPA/Startup.cs
@@ -8,6 +8,7 @@ using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json.Serialization;
+using eShopOnContainers.WebSPA;
namespace eShopConContainers.WebSPA
{
@@ -33,11 +34,13 @@ namespace eShopConContainers.WebSPA
Configuration = builder.Build();
}
- public static IConfigurationRoot Configuration { get; set; }
+ public static IConfigurationRoot Configuration { get; set;}
// This method gets called by the runtime. Use this method to add services to the container.
// For more information on how to configure your application, visit http://go.microsoft.com/fwlink/?LinkID=398940
public void ConfigureServices(IServiceCollection services)
{
+ services.Configure(Configuration);
+
services.AddAntiforgery(options => options.HeaderName = "X-XSRF-TOKEN");
services.AddMvc()
diff --git a/src/Web/WebSPA/eShopOnContainers.WebSPA/appsettings.json b/src/Web/WebSPA/eShopOnContainers.WebSPA/appsettings.json
index 23bef8a13..ea2fed9ea 100644
--- a/src/Web/WebSPA/eShopOnContainers.WebSPA/appsettings.json
+++ b/src/Web/WebSPA/eShopOnContainers.WebSPA/appsettings.json
@@ -1,4 +1,8 @@
{
+ "CatalogUrl": "http://localhost:5101",
+ "OrderingUrl": "http://localhost:5102",
+ "BasketUrl": "http://localhost:5103",
+ "IdentityUrl": "http://localhost:5105",
"Logging": {
"IncludeScopes": false,
"LogLevel": {
diff --git a/src/Web/WebSPA/eShopOnContainers.WebSPA/project.json b/src/Web/WebSPA/eShopOnContainers.WebSPA/project.json
index 42bacd71b..57b813c07 100644
--- a/src/Web/WebSPA/eShopOnContainers.WebSPA/project.json
+++ b/src/Web/WebSPA/eShopOnContainers.WebSPA/project.json
@@ -27,6 +27,7 @@
"Microsoft.Extensions.Logging": "1.0.0",
"Microsoft.Extensions.Logging.Console": "1.0.0",
"Microsoft.Extensions.Logging.Debug": "1.0.0",
+ "Microsoft.Extensions.Options.ConfigurationExtensions": "1.0.0",
"Microsoft.VisualStudio.Web.CodeGeneration.Tools": {
"version": "1.0.0-preview2-final",
"type": "build"
@@ -101,11 +102,9 @@
]
},
"scripts": {
- //"prepublish": [
- // "npm install",
- // "node node_modules/webpack/bin/webpack.js --config config/webpack.config.vendor.js",
- // "node node_modules/webpack/bin/webpack.js --config config/webpack.config.js"
- //],
+ "prepublish": [
+ "npm run build:prod"
+ ],
"postpublish": [
"dotnet publish-iis --publish-folder %publish:OutputPath% --framework %publish:FullTargetFramework%"
]