Skip to content

Commit

Permalink
refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
nd0ut committed May 17, 2024
1 parent e6a7ac4 commit c56402f
Show file tree
Hide file tree
Showing 7 changed files with 102 additions and 19 deletions.
10 changes: 6 additions & 4 deletions abstract/Block.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
// @ts-check
import { BaseComponent, Data } from '@symbiotejs/symbiote';
import { initialConfig } from '../blocks/Config/initialConfig.js';
import { EventEmitter } from '../blocks/UploadCtxProvider/EventEmitter.js';
import { WindowHeightTracker } from '../utils/WindowHeightTracker.js';
import { extractFilename, extractCdnUrlModifiers, extractUuid } from '../utils/cdn-utils.js';
import { getLocaleDirection } from '../utils/getLocaleDirection.js';
import { getPluralForm } from '../utils/getPluralForm.js';
import { applyTemplateData, getPluralObjects } from '../utils/template-utils.js';
Expand All @@ -10,8 +12,6 @@ import { blockCtx } from './CTX.js';
import { LocaleManager, localeStateKey } from './LocaleManager.js';
import { l10nProcessor } from './l10nProcessor.js';
import { sharedConfigKey } from './sharedConfigKey.js';
import { initialConfig } from '../blocks/Config/initialConfig.js';
import { extractFilename, extractOperations, extractUuid } from '../utils/cdn-utils.js';

const TAG_PREFIX = 'lr-';

Expand Down Expand Up @@ -244,12 +244,14 @@ export class Block extends BaseComponent {
*/
proxyUrl(url) {
if (this.cfg.secureDeliveryProxy && this.cfg.secureDeliveryProxyUrlResolver) {
console.warn('Both secureDeliveryProxy and secureDeliveryProxyUrlResolver are set. The secureDeliveryProxyUrlResolver will be used.');
console.warn(
'Both secureDeliveryProxy and secureDeliveryProxyUrlResolver are set. The secureDeliveryProxyUrlResolver will be used.',
);
}
if (this.cfg.secureDeliveryProxyUrlResolver) {
return this.cfg.secureDeliveryProxyUrlResolver(url, {
uuid: extractUuid(url),
cdnUrlModifiers: extractOperations(url),
cdnUrlModifiers: extractCdnUrlModifiers(url),
fileName: extractFilename(url),
});
}
Expand Down
24 changes: 15 additions & 9 deletions abstract/SecureUploadsManager.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
// @ts-check

/** @param {import('../types').SecureUploadsSignatureAndExpire} secureToken */
const isSecureTokenExpired = (secureToken) => {
const { secureExpire } = secureToken;
return Date.now() > Number(secureExpire);
};
import { isSecureTokenExpired } from '../utils/isSecureTokenExpired.js';

export class SecureUploadsManager {
/**
Expand Down Expand Up @@ -37,10 +33,20 @@ export class SecureUploadsManager {
this._block.debugPrint('Secure signature resolver is set. Fetching secure token...');

if (!this._secureToken || isSecureTokenExpired(this._secureToken)) {
const result = await secureUploadsSignatureResolver();
this._block.debugPrint('Secure token fetched:', result);

this._secureToken = result ?? null;
try {
const result = await secureUploadsSignatureResolver();
if (!result) {
this._block.debugPrint('Secure signature resolver returned nothing.');
this._secureToken = null;
} else if (!result.secureSignature || !result.secureExpire) {
throw new Error('Secure signature resolver returned invalid data.');
} else {
this._block.debugPrint('Secure signature resolved:', result);
this._secureToken = result;
}
} catch (err) {
console.error('Secure signature resolving failed. Falling back to the previous one.', err);
}
}

return this._secureToken;
Expand Down
2 changes: 1 addition & 1 deletion types/exported.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export type MetadataCallback = (fileEntry: OutputFileEntry) => Promise<Metadata>
export type LocaleDefinitionOverride = Record<string, LocaleDefinition>;
export type SecureDeliveryProxyUrlResolver = (
previewUrl: string,
{ uuid: string, cdnUrlModifiers: string, fileName: string },
urlParts: { uuid: string; cdnUrlModifiers: string; fileName: string },
) => string;
export type SecureUploadsSignatureAndExpire = { secureSignature: string; secureExpire: string };
export type SecureUploadsSignatureResolver = () => Promise<SecureUploadsSignatureAndExpire | null>;
Expand Down
22 changes: 17 additions & 5 deletions utils/cdn-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,19 +85,31 @@ export function extractUuid(cdnUrl) {
}

/**
* Extract UUID from CDN URL
* Extract operations string from CDN URL
*
* @param {string} cdnUrl
* @returns {string[]}
* @returns {string}
*/
export function extractOperations(cdnUrl) {
export function extractCdnUrlModifiers(cdnUrl) {
let withoutFilename = trimFilename(cdnUrl);
let url = new URL(withoutFilename);
let operationsMarker = url.pathname.indexOf('/-/');
if (operationsMarker === -1) {
return [];
return '';
}
let operationsStr = url.pathname.substring(operationsMarker);
let operationsStr = url.pathname.substring(operationsMarker).slice(1);

return operationsStr;
}

/**
* Extract UUID from CDN URL
*
* @param {string} cdnUrl
* @returns {string[]}
*/
export function extractOperations(cdnUrl) {
let operationsStr = extractCdnUrlModifiers(cdnUrl);

return operationsStr
.split('/-/')
Expand Down
14 changes: 14 additions & 0 deletions utils/cdn-utils.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
trimFilename,
extractUuid,
extractOperations,
extractCdnUrlModifiers,
} from './cdn-utils.js';

const falsyValues = ['', undefined, null, false, true, 0, 10];
Expand Down Expand Up @@ -211,3 +212,16 @@ describe('cdn-utils/extractOperations', () => {
]);
});
});

describe('cdn-utils/extractCdnUrlModifiers', () => {
it('should extract operations string from cdn url', () => {
expect(extractCdnUrlModifiers('https://ucarecdn.com/:uuid/')).to.eql('');
expect(extractCdnUrlModifiers('https://ucarecdn.com/:uuid/image.jpeg')).to.eql('');
expect(
extractCdnUrlModifiers('https://ucarecdn.com/c2499162-eb07-4b93-b31e-94a89a47e858/-/resize/100x/image.jpeg'),
).to.eql('-/resize/100x/');
expect(
extractCdnUrlModifiers('https://domain.ucr.io:8080/-/resize/100x/https://domain.com/image.jpg?q=1#hash'),
).to.eql('-/resize/100x/');
});
});
17 changes: 17 additions & 0 deletions utils/isSecureTokenExpired.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/** @param {number} ms */
const msToUnixTimestamp = (ms) => Math.floor(ms / 1000);

/**
* Check if secure token is expired. It uses a threshold of 10 seconds by default. i.e. if the token is not expired yet
* but will expire in the next 10 seconds, it will return false.
*
* @param {import('../types').SecureUploadsSignatureAndExpire} secureToken
* @param {{ threshold?: number }} [options]
*/
export const isSecureTokenExpired = (secureToken, { threshold } = { threshold: 10 * 1000 }) => {
const { secureExpire } = secureToken;
const nowUnix = msToUnixTimestamp(Date.now());
const expireUnix = Number(secureExpire);
const thresholdUnix = msToUnixTimestamp(threshold);
return nowUnix + thresholdUnix >= expireUnix;
};
32 changes: 32 additions & 0 deletions utils/isSecureTokenExpired.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { isSecureTokenExpired } from './isSecureTokenExpired';
import { expect } from '@esm-bundle/chai';
import * as sinon from 'sinon';

const DATE_NOW = 60 * 1000;

describe('isSecureTokenExpired', () => {
let clock;
beforeEach(() => {
clock = sinon.useFakeTimers(DATE_NOW);
});

afterEach(() => {
clock.restore();
});

it('should return true if the token is expired', () => {
expect(isSecureTokenExpired({ secureExpire: '0', secureSignature: '' })).to.equal(true);
expect(isSecureTokenExpired({ secureExpire: '59', secureSignature: '' })).to.equal(true);
});

it('should return true if the token will expire in the next 10 seconds', () => {
expect(isSecureTokenExpired({ secureExpire: '60', secureSignature: '' })).to.equal(true);
expect(isSecureTokenExpired({ secureExpire: '61', secureSignature: '' })).to.equal(true);
expect(isSecureTokenExpired({ secureExpire: '70', secureSignature: '' })).to.equal(true);
});

it("should return false if the token is not expired and won't expire in next 10 seconds", () => {
expect(isSecureTokenExpired({ secureExpire: '71', secureSignature: '' })).to.equal(false);
expect(isSecureTokenExpired({ secureExpire: '80', secureSignature: '' })).to.equal(false);
});
});

0 comments on commit c56402f

Please sign in to comment.