Add helper classes.
- Add error state matcher for forms. - Add custom validator for forms. - Add error interceptor for incoming responses. - Add unsafe key store for holding private keys.
This commit is contained in:
parent
2f8806b8ce
commit
8636cbdf99
7
src/app/_helpers/custom-error-state-matcher.spec.ts
Normal file
7
src/app/_helpers/custom-error-state-matcher.spec.ts
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
import { CustomErrorStateMatcher } from './custom-error-state-matcher';
|
||||||
|
|
||||||
|
describe('CustomErrorStateMatcher', () => {
|
||||||
|
it('should create an instance', () => {
|
||||||
|
expect(new CustomErrorStateMatcher()).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
9
src/app/_helpers/custom-error-state-matcher.ts
Normal file
9
src/app/_helpers/custom-error-state-matcher.ts
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import {ErrorStateMatcher} from '@angular/material/core';
|
||||||
|
import {FormControl, FormGroupDirective, NgForm} from '@angular/forms';
|
||||||
|
|
||||||
|
export class CustomErrorStateMatcher implements ErrorStateMatcher{
|
||||||
|
isErrorState(control: FormControl | null, form: FormGroupDirective | NgForm | null): boolean {
|
||||||
|
const isSubmitted = form && form.submitted;
|
||||||
|
return !!(control && control.invalid && (control.dirty || control.touched || isSubmitted));
|
||||||
|
}
|
||||||
|
}
|
7
src/app/_helpers/custom.validator.spec.ts
Normal file
7
src/app/_helpers/custom.validator.spec.ts
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
import { Custom.Validator } from './custom.validator';
|
||||||
|
|
||||||
|
describe('Custom.Validator', () => {
|
||||||
|
it('should create an instance', () => {
|
||||||
|
expect(new Custom.Validator()).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
22
src/app/_helpers/custom.validator.ts
Normal file
22
src/app/_helpers/custom.validator.ts
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
import {AbstractControl, ValidationErrors} from '@angular/forms';
|
||||||
|
|
||||||
|
export class CustomValidator {
|
||||||
|
static passwordMatchValidator(control: AbstractControl): void {
|
||||||
|
const password: string = control.get('password').value;
|
||||||
|
const confirmPassword: string = control.get('confirmPassword').value;
|
||||||
|
if (password !== confirmPassword) {
|
||||||
|
control.get('confirmPassword').setErrors({ NoPasswordMatch: true });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static patternValidator(regex: RegExp, error: ValidationErrors): ValidationErrors | null {
|
||||||
|
return (control: AbstractControl): { [key: string]: any } => {
|
||||||
|
if (!control.value) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const valid = regex.test(control.value);
|
||||||
|
return valid ? null : error;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
16
src/app/_helpers/error.interceptor.spec.ts
Normal file
16
src/app/_helpers/error.interceptor.spec.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import { TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { ErrorInterceptor } from './error.interceptor';
|
||||||
|
|
||||||
|
describe('ErrorInterceptor', () => {
|
||||||
|
beforeEach(() => TestBed.configureTestingModule({
|
||||||
|
providers: [
|
||||||
|
ErrorInterceptor
|
||||||
|
]
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should be created', () => {
|
||||||
|
const interceptor: ErrorInterceptor = TestBed.inject(ErrorInterceptor);
|
||||||
|
expect(interceptor).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
25
src/app/_helpers/error.interceptor.ts
Normal file
25
src/app/_helpers/error.interceptor.ts
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import {
|
||||||
|
HttpRequest,
|
||||||
|
HttpHandler,
|
||||||
|
HttpEvent,
|
||||||
|
HttpInterceptor
|
||||||
|
} from '@angular/common/http';
|
||||||
|
import {Observable, throwError} from 'rxjs';
|
||||||
|
import {catchError} from 'rxjs/operators';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class ErrorInterceptor implements HttpInterceptor {
|
||||||
|
|
||||||
|
constructor() {}
|
||||||
|
|
||||||
|
intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> {
|
||||||
|
return next.handle(request).pipe(catchError(err => {
|
||||||
|
if ([401, 403].indexOf(err.status) !== -1) {
|
||||||
|
location.reload(true);
|
||||||
|
}
|
||||||
|
const error = err.error.message || err.statusText;
|
||||||
|
return throwError(error);
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
4
src/app/_helpers/index.ts
Normal file
4
src/app/_helpers/index.ts
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
export * from './custom.validator';
|
||||||
|
export * from './error.interceptor';
|
||||||
|
export * from './custom-error-state-matcher';
|
||||||
|
export * from './unsafe-key-store';
|
7
src/app/_helpers/unsafe-key-store.spec.ts
Normal file
7
src/app/_helpers/unsafe-key-store.spec.ts
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
import { UnsafeKeyStore } from './unsafe-key-store';
|
||||||
|
|
||||||
|
describe('UnsafeKeyStore', () => {
|
||||||
|
it('should create an instance', () => {
|
||||||
|
expect(new UnsafeKeyStore()).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
32
src/app/_helpers/unsafe-key-store.ts
Normal file
32
src/app/_helpers/unsafe-key-store.ts
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
import * as openpgp from '../../assets/js/openpgp.min.js';
|
||||||
|
|
||||||
|
export function UnsafeKeyStore(): void {
|
||||||
|
this.key = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
UnsafeKeyStore.prototype.set = async function(privateKeyArmored): Promise<void> {
|
||||||
|
this.key = (await openpgp.key.readArmored(privateKeyArmored)).keys[0];
|
||||||
|
console.log('set pgp key', this.key.getKeyId().toHex());
|
||||||
|
};
|
||||||
|
|
||||||
|
UnsafeKeyStore.prototype.fingerprint = function(): any {
|
||||||
|
return this.key.keyPacket.fingerprint;
|
||||||
|
};
|
||||||
|
|
||||||
|
UnsafeKeyStore.prototype.keyid = function(): any {
|
||||||
|
return this.key.getKeyId();
|
||||||
|
};
|
||||||
|
|
||||||
|
UnsafeKeyStore.prototype.sign = async function(plainText): Promise<any> {
|
||||||
|
if (!this.key.isDecrypted()) {
|
||||||
|
const password = window.prompt('password');
|
||||||
|
await this.key.decrypt(password);
|
||||||
|
}
|
||||||
|
const opts = {
|
||||||
|
message: openpgp.message.fromText(plainText),
|
||||||
|
privateKeys: [this.key],
|
||||||
|
detached: true,
|
||||||
|
};
|
||||||
|
const signatureObject = await openpgp.sign(opts);
|
||||||
|
return signatureObject.signature;
|
||||||
|
};
|
Loading…
Reference in New Issue
Block a user