start of caching, csrf interceptor, and device service
This commit is contained in:
parent
03c6fb2f82
commit
05f01a5d94
|
@ -9,6 +9,7 @@ import { MatButtonToggleModule } from '@angular/material/button-toggle';
|
||||||
import { MatCardModule } from '@angular/material/card';
|
import { MatCardModule } from '@angular/material/card';
|
||||||
import { FlexLayoutModule } from '@angular/flex-layout';
|
import { FlexLayoutModule } from '@angular/flex-layout';
|
||||||
|
|
||||||
|
import { httpInterceptorProviders } from './http-interceptors';
|
||||||
import { AppRoutingModule } from './app-routing.module';
|
import { AppRoutingModule } from './app-routing.module';
|
||||||
import { AppComponent } from './app.component';
|
import { AppComponent } from './app.component';
|
||||||
|
|
||||||
|
@ -28,6 +29,7 @@ import { InMemoryConfigDataService } from './in-memory-config-data.service';
|
||||||
import { deviceID } from './api-utils';
|
import { deviceID } from './api-utils';
|
||||||
import { environment } from '../environments/environment';
|
import { environment } from '../environments/environment';
|
||||||
import { ChartItemComponent } from './charts/chart-item/chart-item.component';
|
import { ChartItemComponent } from './charts/chart-item/chart-item.component';
|
||||||
|
import { CSRFInterceptor } from './http-interceptors/csrf-intercepor';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [
|
declarations: [
|
||||||
|
@ -61,7 +63,7 @@ import { ChartItemComponent } from './charts/chart-item/chart-item.component';
|
||||||
[] : HttpClientInMemoryWebApiModule.forRoot(InMemoryConfigDataService,
|
[] : HttpClientInMemoryWebApiModule.forRoot(InMemoryConfigDataService,
|
||||||
{ dataEncapsulation: false, delay: 200 }),
|
{ dataEncapsulation: false, delay: 200 }),
|
||||||
],
|
],
|
||||||
providers: [],
|
providers: [httpInterceptorProviders],
|
||||||
bootstrap: [AppComponent]
|
bootstrap: [AppComponent]
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@ export class FolderChartComponent implements OnInit {
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
for (let state in Folder.StateType) {
|
for (let state in Folder.StateType) {
|
||||||
console.log(state);
|
// console.log(state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { deviceID } from './api-utils';
|
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
|
@ -8,14 +7,6 @@ export class CookieService {
|
||||||
|
|
||||||
constructor() { }
|
constructor() { }
|
||||||
|
|
||||||
getCSRFHeader(): any {
|
|
||||||
const dID: String = deviceID();
|
|
||||||
const csrfCookie = 'CSRF-Token-' + dID
|
|
||||||
const csrfHeader = {};
|
|
||||||
csrfHeader['X-CSRF-Token-' + dID] = this.getCookie(csrfCookie);
|
|
||||||
return csrfHeader;
|
|
||||||
}
|
|
||||||
|
|
||||||
getCookie(name: string): string {
|
getCookie(name: string): string {
|
||||||
let ca: Array<string> = document.cookie.split(';');
|
let ca: Array<string> = document.cookie.split(';');
|
||||||
let caLen: number = ca.length;
|
let caLen: number = ca.length;
|
||||||
|
|
|
@ -13,25 +13,25 @@ import Folder from './folder'
|
||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
})
|
})
|
||||||
export class DbStatusService {
|
export class DbStatusService {
|
||||||
private folderStatus: Object = {};
|
|
||||||
private headers: HttpHeaders;
|
|
||||||
private dbStatusUrl = environment.production ? apiURL + 'rest/db/status' : 'api/dbStatus';
|
private dbStatusUrl = environment.production ? apiURL + 'rest/db/status' : 'api/dbStatus';
|
||||||
|
private statuses: Map<string, Folder.Status>;
|
||||||
|
|
||||||
constructor(private http: HttpClient, private cookieService: CookieService) {
|
constructor(private http: HttpClient, private cookieService: CookieService) {
|
||||||
this.headers = new HttpHeaders(this.cookieService.getCSRFHeader())
|
this.statuses = new Map();
|
||||||
}
|
}
|
||||||
|
|
||||||
getFolderStatus(id: string): Observable<Folder.Status> {
|
getFolderStatus(id: string): Observable<Folder.Status> {
|
||||||
let httpOptions: { headers: HttpHeaders } |
|
// First check to see if we have a cached value
|
||||||
{ headers: HttpHeaders, params: HttpParams };
|
if (this.statuses.has(id)) {
|
||||||
|
return of(this.statuses.get(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
let httpOptions: { params: HttpParams };
|
||||||
if (id) {
|
if (id) {
|
||||||
httpOptions = {
|
httpOptions = {
|
||||||
headers: this.headers,
|
|
||||||
params: new HttpParams().set('folder', id)
|
params: new HttpParams().set('folder', id)
|
||||||
};
|
};
|
||||||
} else {
|
} else { }
|
||||||
httpOptions = { headers: this.headers };
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.http
|
return this.http
|
||||||
.get<Folder.Status>(this.dbStatusUrl, httpOptions)
|
.get<Folder.Status>(this.dbStatusUrl, httpOptions)
|
||||||
|
@ -41,13 +41,13 @@ export class DbStatusService {
|
||||||
// Remove from array in developement
|
// Remove from array in developement
|
||||||
// in-memory-web-api returns arrays
|
// in-memory-web-api returns arrays
|
||||||
if (!environment.production) {
|
if (!environment.production) {
|
||||||
console.log("status res!", res);
|
|
||||||
const a: any = res as any;
|
const a: any = res as any;
|
||||||
if (a.length > 0) {
|
if (a.length > 0) {
|
||||||
return res[0];
|
res = res[0];
|
||||||
}
|
}
|
||||||
return {};
|
|
||||||
}
|
}
|
||||||
|
// cache result
|
||||||
|
this.statuses.set(id, res)
|
||||||
return res;
|
return res;
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
import { TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { DeviceService } from './device.service';
|
||||||
|
|
||||||
|
describe('DeviceService', () => {
|
||||||
|
let service: DeviceService;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
TestBed.configureTestingModule({});
|
||||||
|
service = TestBed.inject(DeviceService);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be created', () => {
|
||||||
|
expect(service).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,9 @@
|
||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class DeviceService {
|
||||||
|
|
||||||
|
constructor() { }
|
||||||
|
}
|
|
@ -26,7 +26,7 @@ export class FolderService {
|
||||||
startIndex = startIndex + 1;
|
startIndex = startIndex + 1;
|
||||||
this.dbStatusService.getFolderStatus(folder.id).subscribe(
|
this.dbStatusService.getFolderStatus(folder.id).subscribe(
|
||||||
status => {
|
status => {
|
||||||
folder["status"] = status;
|
folder.status = status;
|
||||||
observer.next(folder);
|
observer.next(folder);
|
||||||
|
|
||||||
// recursively get the status of the next folder
|
// recursively get the status of the next folder
|
||||||
|
@ -41,6 +41,7 @@ export class FolderService {
|
||||||
*/
|
*/
|
||||||
getAll(): Observable<Folder> {
|
getAll(): Observable<Folder> {
|
||||||
const folderObservable: Observable<Folder> = new Observable((observer) => {
|
const folderObservable: Observable<Folder> = new Observable((observer) => {
|
||||||
|
|
||||||
this.systemConfigService.getFolders().subscribe(
|
this.systemConfigService.getFolders().subscribe(
|
||||||
folders => {
|
folders => {
|
||||||
this.folders = folders;
|
this.folders = folders;
|
||||||
|
@ -54,4 +55,3 @@ export class FolderService {
|
||||||
return folderObservable
|
return folderObservable
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { deviceID } from '../api-utils';
|
||||||
|
import {
|
||||||
|
HttpInterceptor, HttpHandler, HttpRequest, HttpHeaders
|
||||||
|
} from '@angular/common/http';
|
||||||
|
|
||||||
|
import { CookieService } from '../cookie.service';
|
||||||
|
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class CSRFInterceptor implements HttpInterceptor {
|
||||||
|
|
||||||
|
constructor(private cookieService: CookieService) { }
|
||||||
|
|
||||||
|
intercept(req: HttpRequest<any>, next: HttpHandler) {
|
||||||
|
const dID: String = deviceID();
|
||||||
|
const csrfCookie = 'CSRF-Token-' + dID
|
||||||
|
|
||||||
|
// Clone the request and replace the original headers with
|
||||||
|
// cloned headers, updated with the CSRF information.
|
||||||
|
const csrfReq = req.clone({
|
||||||
|
headers: req.headers.set('X-CSRF-Token-' + dID,
|
||||||
|
this.cookieService.getCookie(csrfCookie))
|
||||||
|
});
|
||||||
|
|
||||||
|
// send cloned request with header to the next handler.
|
||||||
|
return next.handle(csrfReq);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
/* "Barrel" of Http Interceptors */
|
||||||
|
import { HTTP_INTERCEPTORS } from '@angular/common/http';
|
||||||
|
import { CSRFInterceptor } from './csrf-intercepor';
|
||||||
|
|
||||||
|
/** Http interceptor providers in outside-in order */
|
||||||
|
export const httpInterceptorProviders = [
|
||||||
|
{ provide: HTTP_INTERCEPTORS, useClass: CSRFInterceptor, multi: true },
|
||||||
|
];
|
|
@ -1,6 +1,6 @@
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { config } from './mock/mock-config'
|
import { config } from './mocks/mock-config'
|
||||||
import { dbStatus } from './mock/mock-db-status'
|
import { dbStatus } from './mocks/mock-db-status'
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
|
|
|
@ -20,17 +20,14 @@ export class SystemConfigService {
|
||||||
private devicesSubject: Subject<Device[]> = new Subject();
|
private devicesSubject: Subject<Device[]> = new Subject();
|
||||||
|
|
||||||
private systemConfigUrl = environment.production ? apiURL + 'rest/system/config' : 'api/config';
|
private systemConfigUrl = environment.production ? apiURL + 'rest/system/config' : 'api/config';
|
||||||
private httpOptions: any;
|
|
||||||
|
|
||||||
private checkInterval: number = 100;
|
private checkInterval: number = 100;
|
||||||
|
|
||||||
constructor(private http: HttpClient, private cookieService: CookieService) {
|
constructor(private http: HttpClient) { }
|
||||||
this.httpOptions = { headers: new HttpHeaders(this.cookieService.getCSRFHeader()) };
|
|
||||||
}
|
|
||||||
|
|
||||||
getSystemConfig(): Observable<any> {
|
getSystemConfig(): Observable<any> {
|
||||||
return this.http
|
return this.http
|
||||||
.get(this.systemConfigUrl, this.httpOptions)
|
.get(this.systemConfigUrl)
|
||||||
.pipe(
|
.pipe(
|
||||||
retry(apiRetry),
|
retry(apiRetry),
|
||||||
map(res => {
|
map(res => {
|
||||||
|
|
Loading…
Reference in New Issue