Skip to content

Commit

Permalink
fix: translate protected media
Browse files Browse the repository at this point in the history
  • Loading branch information
ChristiaanScheermeijer committed Dec 4, 2024
1 parent f026ed2 commit 2c37f81
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 14 deletions.
24 changes: 20 additions & 4 deletions packages/common/src/controllers/AccessController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ export default class AccessController {
* If no access tokens exist, it attempts to generate them, if the passport token is expired, it attempts to refresh them.
* If an access token retrieval fails or the user is not entitled to the content, an error is thrown.
*/
getMediaById = async (mediaId: string) => {
getMediaById = async (mediaId: string, language?: string) => {
const { entitledPlan } = useAccountStore.getState();

if (!this.siteId || !entitledPlan) {
Expand All @@ -67,13 +67,25 @@ export default class AccessController {
if (!accessTokens?.passport) {
throw new Error('Failed to get / generate access tokens and retrieve media.');
}
return await this.apiService.getMediaByIdWithPassport({ id: mediaId, siteId: this.siteId, planId: entitledPlan.id, passport: accessTokens.passport });
return await this.apiService.getMediaByIdWithPassport({
id: mediaId,
siteId: this.siteId,
planId: entitledPlan.id,
passport: accessTokens.passport,
language,
});
} catch (error: unknown) {
if (error instanceof ApiError && error.code === 403) {
// If the passport is invalid or expired, refresh the access tokens and try to get the media again.
const accessTokens = await this.refreshAccessTokens();
if (accessTokens?.passport) {
return await this.apiService.getMediaByIdWithPassport({ id: mediaId, siteId: this.siteId, planId: entitledPlan.id, passport: accessTokens.passport });
return await this.apiService.getMediaByIdWithPassport({
id: mediaId,
siteId: this.siteId,
planId: entitledPlan.id,
passport: accessTokens.passport,
language,
});
}

throw new Error('Failed to refresh access tokens and retrieve media.');
Expand Down Expand Up @@ -160,7 +172,11 @@ export default class AccessController {
* Retrieves the access tokens from local storage (if any) along with their expiration timestamp.
*/
getAccessTokens = async (): Promise<(AccessTokens & { expires: number }) | null> => {
const accessTokens = await this.storageService.getItem<AccessTokens & { expires: number }>(ACCESS_TOKENS, true, true);
const accessTokens = await this.storageService.getItem<
AccessTokens & {
expires: number;
}
>(ACCESS_TOKENS, true, true);
if (accessTokens) {
useAccessStore.setState({ passport: accessTokens.passport });
}
Expand Down
12 changes: 6 additions & 6 deletions packages/common/src/controllers/EntitlementController.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,10 +82,10 @@ describe('entitlementController', () => {
supportedLanguages: [],
});

const result = await entitlementController.getSignedMedia('uB8aRnu6');
const result = await entitlementController.getSignedMedia('uB8aRnu6', 'en');

expect(result?.mediaid).toEqual('uB8aRnu6');
expect(getMediaById).toBeCalledWith({ id: 'uB8aRnu6', token: undefined, drmPolicyId: undefined });
expect(getMediaById).toBeCalledWith({ id: 'uB8aRnu6', token: undefined, drmPolicyId: undefined, language: 'en' });

expect(getMediaByIdAccessController).not.toBeCalled();
expect(getMediaTokenGeneric).not.toBeCalled();
Expand All @@ -110,11 +110,11 @@ describe('entitlementController', () => {
supportedLanguages: [],
});

const result = await entitlementController.getSignedMedia('uB8aRnu6');
const result = await entitlementController.getSignedMedia('uB8aRnu6', 'nl');

expect(result?.mediaid).toEqual('uB8aRnu6');
expect(getMediaTokenJwp).toBeCalledWith(jwpSigningConfig, 'uB8aRnu6', 'jwttoken', undefined, undefined);
expect(getMediaById).toBeCalledWith({ id: 'uB8aRnu6', token: 'jwpmediatoken', drmPolicyId: undefined });
expect(getMediaById).toBeCalledWith({ id: 'uB8aRnu6', token: 'jwpmediatoken', drmPolicyId: undefined, language: 'nl' });

expect(getMediaByIdAccessController).not.toBeCalled();
expect(getMediaTokenGeneric).not.toBeCalled();
Expand Down Expand Up @@ -240,10 +240,10 @@ describe('entitlementController', () => {
supportedLanguages: [],
});

const result = await entitlementController.getSignedMedia('uB8aRnu6');
const result = await entitlementController.getSignedMedia('uB8aRnu6', 'de');

expect(result?.mediaid).toEqual('uB8aRnu6');
expect(getMediaByIdAccessController).toBeCalledWith('uB8aRnu6');
expect(getMediaByIdAccessController).toBeCalledWith('uB8aRnu6', 'de');
});
});
});
6 changes: 3 additions & 3 deletions packages/common/src/controllers/EntitlementController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ export default class EntitlementController {
}
};

getSignedMedia = async (id: string, params?: GetMediaParams) => {
getSignedMedia = async (id: string, language?: string, params?: GetMediaParams) => {
const { config, settings } = useConfigStore.getState();
const { custom, contentProtection } = config;

Expand All @@ -76,13 +76,13 @@ export default class EntitlementController {

// signing is handled by access bridge
if (isAccessBridgeEnabled) {
signedMediaItem = await this.accessController.getMediaById(id);
signedMediaItem = await this.accessController.getMediaById(id, language);
} else {
const authData = await this.accountController.getAuthData();
const entitlementService = this.getEntitlementService();
const token = await entitlementService?.getMediaToken(config, id, authData?.jwt, params, drmPolicyId);

signedMediaItem = await this.apiService.getMediaById({ id, token, drmPolicyId });
signedMediaItem = await this.apiService.getMediaById({ id, token, drmPolicyId, language });
}

await this.validateGeoRestriction(signedMediaItem);
Expand Down
5 changes: 4 additions & 1 deletion packages/hooks-react/src/useProtectedMedia.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
import { useQuery } from 'react-query';
import { useTranslation } from 'react-i18next';
import type { PlaylistItem } from '@jwp/ott-common/types/playlist';
import { getModule } from '@jwp/ott-common/src/modules/container';
import EntitlementController from '@jwp/ott-common/src/controllers/EntitlementController';

export default function useProtectedMedia(item: PlaylistItem) {
const entitlementController = getModule(EntitlementController);
const { i18n } = useTranslation();
const { language } = i18n;

return useQuery(['media-signed', item.mediaid, {}], async () => entitlementController.getSignedMedia(item.mediaid), {
return useQuery(['media-signed', item.mediaid, language], async () => entitlementController.getSignedMedia(item.mediaid, language), {
retry: 2,
retryDelay: 1000,
keepPreviousData: false,
Expand Down

0 comments on commit 2c37f81

Please sign in to comment.