From 1f775f669c5a79830d4682dfd9586660af19569e Mon Sep 17 00:00:00 2001 From: griest024 Date: Thu, 10 Oct 2024 12:09:05 -0400 Subject: [PATCH] feat(auth): support in-memory backend delegate (#3181) --- .../in-memory/src/backend/auth.service.ts | 7 ++++++- .../in-memory/src/collection-name.const.ts | 1 + .../src/drivers/auth-driver.module.ts | 5 +++++ .../src/drivers/auth/auth.service.spec.ts | 9 +++++++- .../src/drivers/auth/auth.service.ts | 17 ++++++++++----- .../src/drivers/login/login.service.spec.ts | 21 ++++++++++++------- .../src/drivers/login/login.service.ts | 19 +++++++++++------ .../drivers/register/register.service.spec.ts | 13 +++++++++--- .../src/drivers/register/register.service.ts | 14 ++++++++----- .../drivers/reset-password/service.spec.ts | 19 +++++++++++------ .../src/drivers/reset-password/service.ts | 16 ++++++++------ 11 files changed, 101 insertions(+), 40 deletions(-) create mode 100644 libs/auth/driver/in-memory/src/collection-name.const.ts diff --git a/libs/auth/driver/in-memory/src/backend/auth.service.ts b/libs/auth/driver/in-memory/src/backend/auth.service.ts index d94bb1d5b8..4cd70a4e42 100644 --- a/libs/auth/driver/in-memory/src/backend/auth.service.ts +++ b/libs/auth/driver/in-memory/src/backend/auth.service.ts @@ -5,6 +5,9 @@ import { STATUS, } from 'angular-in-memory-web-api'; +import { DaffInMemorySingleRouteableBackend } from '@daffodil/driver/in-memory'; + +import { DAFF_AUTH_IN_MEMORY_COLLECTION_NAME } from '../collection-name.const'; import { DaffInMemoryDbCustomer } from '../models/db-customer.type'; /** @@ -13,7 +16,9 @@ import { DaffInMemoryDbCustomer } from '../models/db-customer.type'; @Injectable({ providedIn: 'root', }) -export class DaffInMemoryBackendAuthService implements InMemoryDbService { +export class DaffInMemoryBackendAuthService implements InMemoryDbService, DaffInMemorySingleRouteableBackend { + readonly collectionName = DAFF_AUTH_IN_MEMORY_COLLECTION_NAME; + customers: Record = {}; private generateToken(): string { diff --git a/libs/auth/driver/in-memory/src/collection-name.const.ts b/libs/auth/driver/in-memory/src/collection-name.const.ts new file mode 100644 index 0000000000..b154657a4f --- /dev/null +++ b/libs/auth/driver/in-memory/src/collection-name.const.ts @@ -0,0 +1 @@ +export const DAFF_AUTH_IN_MEMORY_COLLECTION_NAME = 'auth'; diff --git a/libs/auth/driver/in-memory/src/drivers/auth-driver.module.ts b/libs/auth/driver/in-memory/src/drivers/auth-driver.module.ts index e3244e2a0e..a00467f65e 100644 --- a/libs/auth/driver/in-memory/src/drivers/auth-driver.module.ts +++ b/libs/auth/driver/in-memory/src/drivers/auth-driver.module.ts @@ -10,11 +10,13 @@ import { DaffAuthDriver, DaffResetPasswordDriver, } from '@daffodil/auth/driver'; +import { provideDaffInMemoryBackends } from '@daffodil/driver/in-memory'; import { DaffInMemoryAuthService } from './auth/auth.service'; import { DaffInMemoryLoginService } from './login/login.service'; import { DaffInMemoryRegisterService } from './register/register.service'; import { DaffInMemoryResetPasswordService } from './reset-password/service'; +import { DaffInMemoryBackendAuthService } from '../backend/auth.service'; @NgModule({ imports: [ @@ -42,6 +44,9 @@ export class DaffAuthInMemoryDriverModule { provide: DaffResetPasswordDriver, useExisting: DaffInMemoryResetPasswordService, }, + provideDaffInMemoryBackends( + DaffInMemoryBackendAuthService, + ), ], }; } diff --git a/libs/auth/driver/in-memory/src/drivers/auth/auth.service.spec.ts b/libs/auth/driver/in-memory/src/drivers/auth/auth.service.spec.ts index 0d94404bb7..a2351a5ad5 100644 --- a/libs/auth/driver/in-memory/src/drivers/auth/auth.service.spec.ts +++ b/libs/auth/driver/in-memory/src/drivers/auth/auth.service.spec.ts @@ -7,6 +7,7 @@ import { provideHttpClientTesting, } from '@angular/common/http/testing'; import { TestBed } from '@angular/core/testing'; +import { InMemoryBackendConfig } from 'angular-in-memory-web-api'; import { DaffAuthToken } from '@daffodil/auth'; import { DaffAuthTokenFactory } from '@daffodil/auth/testing'; @@ -26,6 +27,12 @@ describe('@daffodil/auth/driver/in-memory | AuthService', () => { imports: [], providers: [ DaffInMemoryAuthService, + { + provide: InMemoryBackendConfig, + useValue: { + apiBase: 'api', + }, + }, provideHttpClient(withInterceptorsFromDi()), provideHttpClientTesting(), ], @@ -52,7 +59,7 @@ describe('@daffodil/auth/driver/in-memory | AuthService', () => { done(); }); - const req = httpMock.expectOne(`${service.url}check`); + const req = httpMock.expectOne(`${service['url']}/check`); expect(req.request.method).toBe('POST'); req.flush({}); diff --git a/libs/auth/driver/in-memory/src/drivers/auth/auth.service.ts b/libs/auth/driver/in-memory/src/drivers/auth/auth.service.ts index a42ae9ea2b..d9af5f6e12 100644 --- a/libs/auth/driver/in-memory/src/drivers/auth/auth.service.ts +++ b/libs/auth/driver/in-memory/src/drivers/auth/auth.service.ts @@ -1,9 +1,13 @@ import { HttpClient } from '@angular/common/http'; import { Injectable } from '@angular/core'; +import { InMemoryBackendConfig } from 'angular-in-memory-web-api'; import { Observable } from 'rxjs'; import { map } from 'rxjs/operators'; import { DaffAuthServiceInterface } from '@daffodil/auth/driver'; +import { DaffInMemoryDriverBase } from '@daffodil/driver/in-memory'; + +import { DAFF_AUTH_IN_MEMORY_COLLECTION_NAME } from '../../collection-name.const'; /** * @inheritdoc @@ -11,13 +15,16 @@ import { DaffAuthServiceInterface } from '@daffodil/auth/driver'; @Injectable({ providedIn: 'root', }) -export class DaffInMemoryAuthService implements DaffAuthServiceInterface { - url = '/api/auth/'; - - constructor(private http: HttpClient) {} +export class DaffInMemoryAuthService extends DaffInMemoryDriverBase implements DaffAuthServiceInterface { + constructor( + private http: HttpClient, + config: InMemoryBackendConfig, + ) { + super(config, DAFF_AUTH_IN_MEMORY_COLLECTION_NAME); + } check(): Observable { - return this.http.post(`${this.url}check`, {}).pipe( + return this.http.post(`${this.url}/check`, {}).pipe( map(() => undefined), ); } diff --git a/libs/auth/driver/in-memory/src/drivers/login/login.service.spec.ts b/libs/auth/driver/in-memory/src/drivers/login/login.service.spec.ts index 5ba9d35146..e0daecba1d 100644 --- a/libs/auth/driver/in-memory/src/drivers/login/login.service.spec.ts +++ b/libs/auth/driver/in-memory/src/drivers/login/login.service.spec.ts @@ -7,6 +7,7 @@ import { provideHttpClientTesting, } from '@angular/common/http/testing'; import { TestBed } from '@angular/core/testing'; +import { InMemoryBackendConfig } from 'angular-in-memory-web-api'; import { DaffAuthToken, @@ -20,7 +21,7 @@ import { import { DaffInMemoryLoginService } from './login.service'; describe('@daffodil/auth/driver/in-memory | LoginService', () => { - let loginService; + let service; let httpMock: HttpTestingController; let registrationFactory: DaffAccountRegistrationFactory; @@ -37,13 +38,19 @@ describe('@daffodil/auth/driver/in-memory | LoginService', () => { imports: [], providers: [ DaffInMemoryLoginService, + { + provide: InMemoryBackendConfig, + useValue: { + apiBase: 'api', + }, + }, provideHttpClient(withInterceptorsFromDi()), provideHttpClientTesting(), ], }); httpMock = TestBed.inject(HttpTestingController); - loginService = TestBed.inject(DaffInMemoryLoginService); + service = TestBed.inject(DaffInMemoryLoginService); registrationFactory = TestBed.inject(DaffAccountRegistrationFactory); mockRegistration = registrationFactory.create(); @@ -55,7 +62,7 @@ describe('@daffodil/auth/driver/in-memory | LoginService', () => { }); it('should be created', () => { - expect(loginService).toBeTruthy(); + expect(service).toBeTruthy(); }); describe('login | getting a token', () => { @@ -64,12 +71,12 @@ describe('@daffodil/auth/driver/in-memory | LoginService', () => { }); it('should send a post request and return an AuthToken', done => { - loginService.login({ email, password }).subscribe(auth => { + service.login({ email, password }).subscribe(auth => { expect(auth).toEqual(mockAuth); done(); }); - const req = httpMock.expectOne(`${loginService.url}login`); + const req = httpMock.expectOne(`${service.url}/login`); expect(req.request.method).toBe('POST'); expect(req.request.body).toEqual({ email, password }); @@ -83,12 +90,12 @@ describe('@daffodil/auth/driver/in-memory | LoginService', () => { }); it('should send a post request and return an empty Observable', done => { - loginService.logout().subscribe(resp => { + service.logout().subscribe(resp => { expect(resp).toBeUndefined(); done(); }); - const req = httpMock.expectOne(`${loginService.url}logout`); + const req = httpMock.expectOne(`${service.url}/logout`); expect(req.request.method).toBe('POST'); req.flush({ success: true }); diff --git a/libs/auth/driver/in-memory/src/drivers/login/login.service.ts b/libs/auth/driver/in-memory/src/drivers/login/login.service.ts index c7c02b9747..a11b5f05b8 100644 --- a/libs/auth/driver/in-memory/src/drivers/login/login.service.ts +++ b/libs/auth/driver/in-memory/src/drivers/login/login.service.ts @@ -1,5 +1,6 @@ import { HttpClient } from '@angular/common/http'; import { Injectable } from '@angular/core'; +import { InMemoryBackendConfig } from 'angular-in-memory-web-api'; import { Observable, of, @@ -12,6 +13,9 @@ import { DaffAuthToken, } from '@daffodil/auth'; import { DaffLoginServiceInterface } from '@daffodil/auth/driver'; +import { DaffInMemoryDriverBase } from '@daffodil/driver/in-memory'; + +import { DAFF_AUTH_IN_MEMORY_COLLECTION_NAME } from '../../collection-name.const'; /** * @inheritdoc @@ -19,17 +23,20 @@ import { DaffLoginServiceInterface } from '@daffodil/auth/driver'; @Injectable({ providedIn: 'root', }) -export class DaffInMemoryLoginService implements DaffLoginServiceInterface { - url = '/api/auth/'; - - constructor(private http: HttpClient) {} +export class DaffInMemoryLoginService extends DaffInMemoryDriverBase implements DaffLoginServiceInterface { + constructor( + private http: HttpClient, + config: InMemoryBackendConfig, + ) { + super(config, DAFF_AUTH_IN_MEMORY_COLLECTION_NAME); + } login(request: DaffLoginInfo): Observable { - return this.http.post(`${this.url}login`, request); + return this.http.post(`${this.url}/login`, request); } logout(): Observable { - return this.http.post<{success: boolean}>(`${this.url}logout`, {}).pipe( + return this.http.post<{success: boolean}>(`${this.url}/logout`, {}).pipe( switchMap(({ success }) => success ? of(undefined) : throwError(() => new Error('Logout failed'))), ); } diff --git a/libs/auth/driver/in-memory/src/drivers/register/register.service.spec.ts b/libs/auth/driver/in-memory/src/drivers/register/register.service.spec.ts index 3eece42946..bbcb2a6526 100644 --- a/libs/auth/driver/in-memory/src/drivers/register/register.service.spec.ts +++ b/libs/auth/driver/in-memory/src/drivers/register/register.service.spec.ts @@ -7,6 +7,7 @@ import { provideHttpClientTesting, } from '@angular/common/http/testing'; import { TestBed } from '@angular/core/testing'; +import { InMemoryBackendConfig } from 'angular-in-memory-web-api'; import { of } from 'rxjs'; import { @@ -42,6 +43,12 @@ describe('@daffodil/auth/driver/in-memory | DaffInMemoryRegisterService', () => provide: DaffInMemoryLoginService, useValue: loginServiceSpy, }, + { + provide: InMemoryBackendConfig, + useValue: { + apiBase: 'api', + }, + }, provideHttpClient(withInterceptorsFromDi()), provideHttpClientTesting(), ], @@ -78,7 +85,7 @@ describe('@daffodil/auth/driver/in-memory | DaffInMemoryRegisterService', () => it('should send a post request', () => { service.register(mockRegistration).subscribe(auth => {}); - const req = httpMock.expectOne(`${service.url}register`); + const req = httpMock.expectOne(`${service['url']}/register`); expect(req.request.method).toBe('POST'); expect(req.request.body).toEqual(mockRegistration); @@ -92,7 +99,7 @@ describe('@daffodil/auth/driver/in-memory | DaffInMemoryRegisterService', () => done(); }); - const req = httpMock.expectOne(`${service.url}register`); + const req = httpMock.expectOne(`${service['url']}/register`); req.flush({}); }); @@ -106,7 +113,7 @@ describe('@daffodil/auth/driver/in-memory | DaffInMemoryRegisterService', () => it('should send a post request', () => { service.registerOnly(mockRegistration).subscribe(auth => {}); - const req = httpMock.expectOne(`${service.url}register`); + const req = httpMock.expectOne(`${service['url']}/register`); expect(req.request.method).toBe('POST'); expect(req.request.body).toEqual(mockRegistration); diff --git a/libs/auth/driver/in-memory/src/drivers/register/register.service.ts b/libs/auth/driver/in-memory/src/drivers/register/register.service.ts index bd7380bda7..fe1b28130d 100644 --- a/libs/auth/driver/in-memory/src/drivers/register/register.service.ts +++ b/libs/auth/driver/in-memory/src/drivers/register/register.service.ts @@ -1,5 +1,6 @@ import { HttpClient } from '@angular/common/http'; import { Injectable } from '@angular/core'; +import { InMemoryBackendConfig } from 'angular-in-memory-web-api'; import { Observable } from 'rxjs'; import { map, @@ -8,7 +9,9 @@ import { import { DaffAccountRegistration } from '@daffodil/auth'; import { DaffRegisterServiceInterface } from '@daffodil/auth/driver'; +import { DaffInMemoryDriverBase } from '@daffodil/driver/in-memory'; +import { DAFF_AUTH_IN_MEMORY_COLLECTION_NAME } from '../../collection-name.const'; import { DaffInMemoryLoginService } from '../login/login.service'; /** @@ -17,13 +20,14 @@ import { DaffInMemoryLoginService } from '../login/login.service'; @Injectable({ providedIn: 'root', }) -export class DaffInMemoryRegisterService implements DaffRegisterServiceInterface { - url = '/api/auth/'; - +export class DaffInMemoryRegisterService extends DaffInMemoryDriverBase implements DaffRegisterServiceInterface { constructor( private http: HttpClient, private loginService: DaffInMemoryLoginService, - ) {} + config: InMemoryBackendConfig, + ) { + super(config, DAFF_AUTH_IN_MEMORY_COLLECTION_NAME); + } register(registration: DaffAccountRegistration): Observable { return this.registerOnly(registration).pipe( @@ -33,6 +37,6 @@ export class DaffInMemoryRegisterService implements DaffRegisterServiceInterface } registerOnly(registration: DaffAccountRegistration): Observable { - return this.http.post(`${this.url}register`, registration); + return this.http.post(`${this.url}/register`, registration); } } diff --git a/libs/auth/driver/in-memory/src/drivers/reset-password/service.spec.ts b/libs/auth/driver/in-memory/src/drivers/reset-password/service.spec.ts index 43fb8ac97f..3098f9c90d 100644 --- a/libs/auth/driver/in-memory/src/drivers/reset-password/service.spec.ts +++ b/libs/auth/driver/in-memory/src/drivers/reset-password/service.spec.ts @@ -7,6 +7,7 @@ import { provideHttpClientTesting, } from '@angular/common/http/testing'; import { TestBed } from '@angular/core/testing'; +import { InMemoryBackendConfig } from 'angular-in-memory-web-api'; import { of } from 'rxjs'; import { @@ -42,6 +43,12 @@ describe('@daffodil/auth/driver/in-memory | DaffInMemoryResetPasswordService', ( provide: DaffInMemoryLoginService, useValue: loginServiceSpy, }, + { + provide: InMemoryBackendConfig, + useValue: { + apiBase: 'api', + }, + }, provideHttpClient(withInterceptorsFromDi()), provideHttpClientTesting(), ], @@ -78,7 +85,7 @@ describe('@daffodil/auth/driver/in-memory | DaffInMemoryResetPasswordService', ( it('should send a post request', () => { service.resetPassword(mockResetInfo).subscribe(auth => {}); - const req = httpMock.expectOne(`${service.url}resetPassword`); + const req = httpMock.expectOne(`${service['url']}/resetPassword`); expect(req.request.method).toBe('POST'); expect(req.request.body).toEqual(mockResetInfo); @@ -92,7 +99,7 @@ describe('@daffodil/auth/driver/in-memory | DaffInMemoryResetPasswordService', ( done(); }); - const req = httpMock.expectOne(`${service.url}resetPassword`); + const req = httpMock.expectOne(`${service['url']}/resetPassword`); req.flush({}); }); @@ -106,7 +113,7 @@ describe('@daffodil/auth/driver/in-memory | DaffInMemoryResetPasswordService', ( it('should send a post request', () => { service.resetPasswordOnly(mockResetInfo).subscribe(auth => {}); - const req = httpMock.expectOne(`${service.url}resetPassword`); + const req = httpMock.expectOne(`${service['url']}/resetPassword`); expect(req.request.method).toBe('POST'); expect(req.request.body).toEqual(mockResetInfo); @@ -119,7 +126,7 @@ describe('@daffodil/auth/driver/in-memory | DaffInMemoryResetPasswordService', ( done(); }); - const req = httpMock.expectOne(`${service.url}resetPassword`); + const req = httpMock.expectOne(`${service['url']}/resetPassword`); req.flush({}); }); @@ -133,7 +140,7 @@ describe('@daffodil/auth/driver/in-memory | DaffInMemoryResetPasswordService', ( it('should send a post request', () => { service.sendResetEmail(mockResetInfo.email).subscribe(auth => {}); - const req = httpMock.expectOne(`${service.url}sendResetEmail`); + const req = httpMock.expectOne(`${service['url']}/sendResetEmail`); expect(req.request.method).toBe('POST'); @@ -145,7 +152,7 @@ describe('@daffodil/auth/driver/in-memory | DaffInMemoryResetPasswordService', ( done(); }); - const req = httpMock.expectOne(`${service.url}sendResetEmail`); + const req = httpMock.expectOne(`${service['url']}/sendResetEmail`); req.flush({}); }); diff --git a/libs/auth/driver/in-memory/src/drivers/reset-password/service.ts b/libs/auth/driver/in-memory/src/drivers/reset-password/service.ts index 3bd773c05b..11abbbaaf9 100644 --- a/libs/auth/driver/in-memory/src/drivers/reset-password/service.ts +++ b/libs/auth/driver/in-memory/src/drivers/reset-password/service.ts @@ -1,5 +1,6 @@ import { HttpClient } from '@angular/common/http'; import { Injectable } from '@angular/core'; +import { InMemoryBackendConfig } from 'angular-in-memory-web-api'; import { Observable } from 'rxjs'; import { map, @@ -8,7 +9,9 @@ import { import { DaffAuthResetPasswordInfo } from '@daffodil/auth'; import { DaffResetPasswordServiceInterface } from '@daffodil/auth/driver'; +import { DaffInMemoryDriverBase } from '@daffodil/driver/in-memory'; +import { DAFF_AUTH_IN_MEMORY_COLLECTION_NAME } from '../../collection-name.const'; import { DaffInMemoryLoginService } from '../login/login.service'; /** @@ -17,13 +20,14 @@ import { DaffInMemoryLoginService } from '../login/login.service'; @Injectable({ providedIn: 'root', }) -export class DaffInMemoryResetPasswordService implements DaffResetPasswordServiceInterface { - url = '/api/auth/'; - +export class DaffInMemoryResetPasswordService extends DaffInMemoryDriverBase implements DaffResetPasswordServiceInterface { constructor( private http: HttpClient, private loginService: DaffInMemoryLoginService, - ) {} + config: InMemoryBackendConfig, + ) { + super(config, DAFF_AUTH_IN_MEMORY_COLLECTION_NAME); + } resetPassword(info: DaffAuthResetPasswordInfo): Observable { return this.resetPasswordOnly(info).pipe( @@ -33,10 +37,10 @@ export class DaffInMemoryResetPasswordService implements DaffResetPasswordServic } resetPasswordOnly(info: DaffAuthResetPasswordInfo): Observable { - return this.http.post(`${this.url}resetPassword`, info); + return this.http.post(`${this.url}/resetPassword`, info); } sendResetEmail(email: string): Observable { - return this.http.post(`${this.url}sendResetEmail`, { email }); + return this.http.post(`${this.url}/sendResetEmail`, { email }); } }