diff --git a/ansible/roles/media-licenses/templates/vidis-sync-cronjob-configmap.yml.j2 b/ansible/roles/media-licenses/templates/vidis-sync-cronjob-configmap.yml.j2 index a98d839e20..9d3d96134d 100644 --- a/ansible/roles/media-licenses/templates/vidis-sync-cronjob-configmap.yml.j2 +++ b/ansible/roles/media-licenses/templates/vidis-sync-cronjob-configmap.yml.j2 @@ -10,3 +10,4 @@ data: NEST_LOG_LEVEL: "error" EXIT_ON_ERROR: "true" VIDIS_API_CLIENT_BASE_URL: "{{ VIDIS_API_CLIENT_BASE_URL }}" + VIDIS_SYNC_REGION: "{{ VIDIS_SYNC_REGION }}" diff --git a/apps/server/src/infra/sync/media-licenses/service/vidis-fetch.service.spec.ts b/apps/server/src/infra/sync/media-licenses/service/vidis-fetch.service.spec.ts index 7fe799a00f..7a864d7273 100644 --- a/apps/server/src/infra/sync/media-licenses/service/vidis-fetch.service.spec.ts +++ b/apps/server/src/infra/sync/media-licenses/service/vidis-fetch.service.spec.ts @@ -6,9 +6,10 @@ import { MediaSourceBasicAuthConfigNotFoundLoggableException } from '@modules/me import { mediaSourceFactory } from '@modules/media-source/testing'; import { AxiosErrorLoggable } from '@src/core/error/loggable'; import { axiosErrorFactory, axiosResponseFactory } from '@shared/testing'; +import { ConfigService } from '@nestjs/config'; import { Test, TestingModule } from '@nestjs/testing'; import { createMock, DeepMocked } from '@golevelup/ts-jest'; -import { AxiosResponse } from 'axios'; +import { AxiosResponse, RawAxiosRequestConfig } from 'axios'; import { vidisPageOfferFactory } from '../testing'; import { VidisFetchService } from './vidis-fetch.service'; @@ -30,6 +31,19 @@ describe(VidisFetchService.name, () => { provide: DefaultEncryptionService, useValue: createMock(), }, + { + provide: ConfigService, + useValue: createMock({ + getOrThrow: (key: string) => { + switch (key) { + case 'VIDIS_SYNC_REGION': + return 'test-region'; + default: + throw new Error(`Unknown key: ${key}`); + } + }, + }), + }, ], }).compile(); @@ -93,22 +107,29 @@ describe(VidisFetchService.name, () => { }); it('should create a vidis api client', async () => { - const { mediaSource, decryptedUsername, decryptedPassword } = setup(); + const { mediaSource } = setup(); await service.getOfferItemsFromVidis(mediaSource); - expect(vidisClientFactory.createVidisClient).toBeCalledWith({ - username: decryptedUsername, - password: decryptedPassword, - }); + expect(vidisClientFactory.createVidisClient).toBeCalledWith(); }); - it('should call the vidis endpoint for activated offer items', async () => { - const { mediaSource, vidisApiClientMock } = setup(); + it('should call the vidis endpoint for activated offer items with basic auth', async () => { + const { mediaSource, vidisApiClientMock, decryptedUsername, decryptedPassword } = setup(); await service.getOfferItemsFromVidis(mediaSource); - expect(vidisApiClientMock.getActivatedOffersByRegion).toBeCalledWith('test-region'); + const encodedBasicAuth = btoa(`${decryptedUsername}:${decryptedPassword}`); + const expectedAxiosOptions: RawAxiosRequestConfig = { + headers: { Authorization: expect.stringMatching(`Basic ${encodedBasicAuth}`) }, + }; + + expect(vidisApiClientMock.getActivatedOffersByRegion).toBeCalledWith( + 'test-region', + undefined, + undefined, + expectedAxiosOptions + ); }); }); diff --git a/apps/server/src/infra/sync/media-licenses/service/vidis-fetch.service.ts b/apps/server/src/infra/sync/media-licenses/service/vidis-fetch.service.ts index 0b59c86e96..b0cb45dd15 100644 --- a/apps/server/src/infra/sync/media-licenses/service/vidis-fetch.service.ts +++ b/apps/server/src/infra/sync/media-licenses/service/vidis-fetch.service.ts @@ -5,11 +5,14 @@ import { MediaSource, MediaSourceDataFormat } from '@modules/media-source'; import { MediaSourceBasicAuthConfigNotFoundLoggableException } from '@modules/media-source/loggable'; import { AxiosResponse, isAxiosError } from 'axios'; import { AxiosErrorLoggable } from '@src/core/error/loggable'; +import { ConfigService } from '@nestjs/config'; +import { VidisSyncConfig } from '../vidis-sync-config'; @Injectable() export class VidisFetchService { constructor( private readonly vidisClientFactory: VidisClientFactory, + private readonly configService: ConfigService, @Inject(DefaultEncryptionService) private readonly encryptionService: EncryptionService ) {} @@ -20,12 +23,12 @@ export class VidisFetchService { const vidisClient: IDMBetreiberApiInterface = this.vidisClientFactory.createVidisClient(); - // TODO: env var - const region = 'test-region'; const decryptedUsername = this.encryptionService.decrypt(mediaSource.basicAuthConfig.username); const decryptedPassword = this.encryptionService.decrypt(mediaSource.basicAuthConfig.password); const basicAuthEncoded = btoa(`${decryptedUsername}:${decryptedPassword}`); + const region = this.configService.getOrThrow('VIDIS_SYNC_REGION'); + try { const axiosResponse: AxiosResponse = await vidisClient.getActivatedOffersByRegion( region, diff --git a/apps/server/src/infra/sync/media-licenses/vidis-sync-config.ts b/apps/server/src/infra/sync/media-licenses/vidis-sync-config.ts new file mode 100644 index 0000000000..d49bf142ab --- /dev/null +++ b/apps/server/src/infra/sync/media-licenses/vidis-sync-config.ts @@ -0,0 +1,3 @@ +export interface VidisSyncConfig { + VIDIS_SYNC_REGION: string; +} diff --git a/apps/server/src/infra/vidis-client/vidis-client-factory.spec.ts b/apps/server/src/infra/vidis-client/vidis-client-factory.spec.ts index 3b02bfc36b..9c5de1e1c4 100644 --- a/apps/server/src/infra/vidis-client/vidis-client-factory.spec.ts +++ b/apps/server/src/infra/vidis-client/vidis-client-factory.spec.ts @@ -1,6 +1,5 @@ import { faker } from '@faker-js/faker'; -import { DeepMocked, createMock } from '@golevelup/ts-jest'; -import { ServerConfig } from '@modules/server'; +import { createMock } from '@golevelup/ts-jest'; import { ConfigService } from '@nestjs/config'; import { Test, TestingModule } from '@nestjs/testing'; import { VidisClientConfig } from './vidis-client-config'; @@ -9,7 +8,6 @@ import { VidisClientFactory } from './vidis-client-factory'; describe(VidisClientFactory.name, () => { let module: TestingModule; let factory: VidisClientFactory; - let configService: DeepMocked>; beforeAll(async () => { module = await Test.createTestingModule({ @@ -17,15 +15,21 @@ describe(VidisClientFactory.name, () => { VidisClientFactory, { provide: ConfigService, - useValue: createMock>(), + useValue: createMock>({ + getOrThrow: (key: string) => { + switch (key) { + case 'VIDIS_API_CLIENT_BASE_URL': + return faker.internet.url(); + default: + throw new Error(`Unknown key: ${key}`); + } + }, + }), }, ], }).compile(); factory = module.get(VidisClientFactory); - configService = module.get(ConfigService); - - configService.getOrThrow.mockReturnValueOnce(faker.internet.url()); }); afterAll(async () => { @@ -42,23 +46,8 @@ describe(VidisClientFactory.name, () => { describe('createVidisClient', () => { describe('when the function is called', () => { - const setup = () => { - const username = faker.string.alpha(); - const password = faker.string.alpha(); - - return { - username, - password, - }; - }; - it('should return a vidis api client as an IDMBetreiberApiInterface', () => { - const { username, password } = setup(); - - const result = factory.createVidisClient({ - username, - password, - }); + const result = factory.createVidisClient(); expect(result).toBeDefined(); }); diff --git a/apps/server/src/modules/server/server.config.ts b/apps/server/src/modules/server/server.config.ts index 8e1763263d..ec2b2b6284 100644 --- a/apps/server/src/modules/server/server.config.ts +++ b/apps/server/src/modules/server/server.config.ts @@ -33,6 +33,7 @@ import type { CoreModuleConfig } from '@src/core'; import { Algorithm } from 'jsonwebtoken'; import type { Timezone } from './types/timezone.enum'; import { VidisClientConfig } from '@infra/vidis-client'; +import { VidisSyncConfig } from '@infra/sync/media-licenses/vidis-sync-config'; export enum NodeEnvType { TEST = 'test', @@ -75,7 +76,8 @@ export interface ServerConfig ShdConfig, OauthConfig, EncryptionConfig, - VidisClientConfig { + VidisClientConfig, + VidisSyncConfig { NODE_ENV: NodeEnvType; SC_DOMAIN: string; HOST: string; @@ -324,6 +326,7 @@ const config: ServerConfig = { FEATURE_EXTERNAL_SYSTEM_LOGOUT_ENABLED: Configuration.get('FEATURE_EXTERNAL_SYSTEM_LOGOUT_ENABLED') as boolean, PUBLIC_BACKEND_URL: Configuration.get('PUBLIC_BACKEND_URL') as string, VIDIS_API_CLIENT_BASE_URL: Configuration.get('VIDIS_API_CLIENT_BASE_URL') as string, + VIDIS_SYNC_REGION: Configuration.get('VIDIS_SYNC_REGION') as string, }; export const serverConfig = () => config; diff --git a/config/default.schema.json b/config/default.schema.json index a1b31d058e..1d169aa6e0 100644 --- a/config/default.schema.json +++ b/config/default.schema.json @@ -1680,6 +1680,11 @@ "type": "string", "default": "https://service-stage.vidis.schule/o/vidis-rest", "description": "The VIDIS API base URL" + }, + "VIDIS_SYNC_REGION": { + "type": "string", + "default": "test-region", + "description": "The region for fetching activated offers from VIDIS" } }, "required": []