mirror of
https://github.com/octoleo/syncthing.git
synced 2024-12-28 21:02:45 +00:00
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 { FlexLayoutModule } from '@angular/flex-layout';
|
||||
|
||||
import { httpInterceptorProviders } from './http-interceptors';
|
||||
import { AppRoutingModule } from './app-routing.module';
|
||||
import { AppComponent } from './app.component';
|
||||
|
||||
@ -28,6 +29,7 @@ import { InMemoryConfigDataService } from './in-memory-config-data.service';
|
||||
import { deviceID } from './api-utils';
|
||||
import { environment } from '../environments/environment';
|
||||
import { ChartItemComponent } from './charts/chart-item/chart-item.component';
|
||||
import { CSRFInterceptor } from './http-interceptors/csrf-intercepor';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
@ -61,7 +63,7 @@ import { ChartItemComponent } from './charts/chart-item/chart-item.component';
|
||||
[] : HttpClientInMemoryWebApiModule.forRoot(InMemoryConfigDataService,
|
||||
{ dataEncapsulation: false, delay: 200 }),
|
||||
],
|
||||
providers: [],
|
||||
providers: [httpInterceptorProviders],
|
||||
bootstrap: [AppComponent]
|
||||
})
|
||||
|
||||
|
@ -21,7 +21,7 @@ export class FolderChartComponent implements OnInit {
|
||||
|
||||
ngOnInit(): void {
|
||||
for (let state in Folder.StateType) {
|
||||
console.log(state);
|
||||
// console.log(state);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { deviceID } from './api-utils';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
@ -8,14 +7,6 @@ export class CookieService {
|
||||
|
||||
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 {
|
||||
let ca: Array<string> = document.cookie.split(';');
|
||||
let caLen: number = ca.length;
|
||||
|
@ -13,25 +13,25 @@ import Folder from './folder'
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class DbStatusService {
|
||||
private folderStatus: Object = {};
|
||||
private headers: HttpHeaders;
|
||||
private dbStatusUrl = environment.production ? apiURL + 'rest/db/status' : 'api/dbStatus';
|
||||
private statuses: Map<string, Folder.Status>;
|
||||
|
||||
constructor(private http: HttpClient, private cookieService: CookieService) {
|
||||
this.headers = new HttpHeaders(this.cookieService.getCSRFHeader())
|
||||
this.statuses = new Map();
|
||||
}
|
||||
|
||||
getFolderStatus(id: string): Observable<Folder.Status> {
|
||||
let httpOptions: { headers: HttpHeaders } |
|
||||
{ headers: HttpHeaders, params: HttpParams };
|
||||
// First check to see if we have a cached value
|
||||
if (this.statuses.has(id)) {
|
||||
return of(this.statuses.get(id));
|
||||
}
|
||||
|
||||
let httpOptions: { params: HttpParams };
|
||||
if (id) {
|
||||
httpOptions = {
|
||||
headers: this.headers,
|
||||
params: new HttpParams().set('folder', id)
|
||||
};
|
||||
} else {
|
||||
httpOptions = { headers: this.headers };
|
||||
}
|
||||
} else { }
|
||||
|
||||
return this.http
|
||||
.get<Folder.Status>(this.dbStatusUrl, httpOptions)
|
||||
@ -41,13 +41,13 @@ export class DbStatusService {
|
||||
// Remove from array in developement
|
||||
// in-memory-web-api returns arrays
|
||||
if (!environment.production) {
|
||||
console.log("status res!", res);
|
||||
const a: any = res as any;
|
||||
if (a.length > 0) {
|
||||
return res[0];
|
||||
res = res[0];
|
||||
}
|
||||
return {};
|
||||
}
|
||||
// cache result
|
||||
this.statuses.set(id, res)
|
||||
return res;
|
||||
})
|
||||
);
|
||||
|
16
src/app/device.service.spec.ts
Normal file
16
src/app/device.service.spec.ts
Normal file
@ -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();
|
||||
});
|
||||
});
|
9
src/app/device.service.ts
Normal file
9
src/app/device.service.ts
Normal file
@ -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;
|
||||
this.dbStatusService.getFolderStatus(folder.id).subscribe(
|
||||
status => {
|
||||
folder["status"] = status;
|
||||
folder.status = status;
|
||||
observer.next(folder);
|
||||
|
||||
// recursively get the status of the next folder
|
||||
@ -41,6 +41,7 @@ export class FolderService {
|
||||
*/
|
||||
getAll(): Observable<Folder> {
|
||||
const folderObservable: Observable<Folder> = new Observable((observer) => {
|
||||
|
||||
this.systemConfigService.getFolders().subscribe(
|
||||
folders => {
|
||||
this.folders = folders;
|
||||
@ -53,5 +54,4 @@ export class FolderService {
|
||||
});
|
||||
return folderObservable
|
||||
}
|
||||
}
|
||||
|
||||
}
|
29
src/app/http-interceptors/csrf-intercepor.ts
Normal file
29
src/app/http-interceptors/csrf-intercepor.ts
Normal file
@ -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);
|
||||
}
|
||||
}
|
8
src/app/http-interceptors/index.ts
Normal file
8
src/app/http-interceptors/index.ts
Normal file
@ -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 { config } from './mock/mock-config'
|
||||
import { dbStatus } from './mock/mock-db-status'
|
||||
import { config } from './mocks/mock-config'
|
||||
import { dbStatus } from './mocks/mock-db-status'
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
|
@ -20,17 +20,14 @@ export class SystemConfigService {
|
||||
private devicesSubject: Subject<Device[]> = new Subject();
|
||||
|
||||
private systemConfigUrl = environment.production ? apiURL + 'rest/system/config' : 'api/config';
|
||||
private httpOptions: any;
|
||||
|
||||
private checkInterval: number = 100;
|
||||
|
||||
constructor(private http: HttpClient, private cookieService: CookieService) {
|
||||
this.httpOptions = { headers: new HttpHeaders(this.cookieService.getCSRFHeader()) };
|
||||
}
|
||||
constructor(private http: HttpClient) { }
|
||||
|
||||
getSystemConfig(): Observable<any> {
|
||||
return this.http
|
||||
.get(this.systemConfigUrl, this.httpOptions)
|
||||
.get(this.systemConfigUrl)
|
||||
.pipe(
|
||||
retry(apiRetry),
|
||||
map(res => {
|
||||
|
Loading…
Reference in New Issue
Block a user