Skip to content

Commit

Permalink
fix: show warn msg when manual workaround needed
Browse files Browse the repository at this point in the history
Signed-off-by: Andres Correa Casablanca <[email protected]>
  • Loading branch information
castarco committed Mar 15, 2024
1 parent c907ca3 commit 62b304a
Show file tree
Hide file tree
Showing 6 changed files with 62 additions and 25 deletions.
16 changes: 13 additions & 3 deletions e2e/e2e.test.mts
Original file line number Diff line number Diff line change
Expand Up @@ -277,9 +277,17 @@ describe('middleware (hybrid)', () => {
beforeAll(async () => {
await execFile('pnpm', ['install'], execOpts)
await execFile('pnpm', ['run', 'clean'], execOpts)
const { stdout: buildStdout } = await execFile('pnpm', ['run', 'build'], execOpts)
const { stdout: buildStdout } = await execFile(
'pnpm',
['run', 'build'],
execOpts,
)
expect(buildStdout).toMatch(/run the build step again/)
const { stdout: buildStdout2 } = await execFile('pnpm', ['run', 'build'], execOpts)
const { stdout: buildStdout2 } = await execFile(
'pnpm',
['run', 'build'],
execOpts,
)
expect(buildStdout2).not.toMatch(/run the build step again/)
})

Expand Down Expand Up @@ -317,6 +325,8 @@ describe('middleware (hybrid)', () => {
}

it('patches inline resources for dynamically generated pages referring static resources', async () => {
await checkHtmlIsPatched('/', { '/code.js': 'sha256-X7QGGDHgf6XMoabXvV9pW7gl3ALyZhZlgKq1s3pwmME=' })
await checkHtmlIsPatched('/', {
'/code.js': 'sha256-X7QGGDHgf6XMoabXvV9pW7gl3ALyZhZlgKq1s3pwmME=',
})
})
})
4 changes: 1 addition & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,7 @@
"default": "./src/state.mjs"
}
},
"files": [
"src/*"
],
"files": ["src/*"],
"scripts": {
"format": "biome format --write .",
"install-githooks": "if [ -d .git ]; then git config core.hooksPath .hooks; fi",
Expand Down
36 changes: 27 additions & 9 deletions src/core.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -485,10 +485,17 @@ export const scanForNestedResources = async (logger, dirPath, h) => {
}

/**
* @param {Logger} logger
* @param {HashesCollection} h
* @param {string} sriHashesModule
* @param {boolean} enableMiddleware_SRI
*/
export async function generateSRIHashesModule(h, sriHashesModule) {
export async function generateSRIHashesModule(
logger,
h,
sriHashesModule,
enableMiddleware_SRI,
) {
let persistHashes = false

const inlineScriptHashes = Array.from(h.inlineScriptHashes).sort()
Expand Down Expand Up @@ -539,6 +546,12 @@ export async function generateSRIHashesModule(h, sriHashesModule) {
}

if (persistHashes) {
if (enableMiddleware_SRI) {
logger.warn(
'SRI hashes have changed for static resources that may be used in dynamic pages. You should run the build step again',
)
}

let hashesFileContent = '// Do not edit this file manually\n\n'
hashesFileContent += `export const inlineScriptHashes = /** @type {string[]} */ ([${inlineScriptHashes
.map(h => `\n\t'${h}',`)
Expand Down Expand Up @@ -589,7 +602,7 @@ export async function generateSRIHashesModule(h, sriHashesModule) {
*/
export const processStaticFiles = async (
logger,
{ distDir, sriHashesModule },
{ distDir, sriHashesModule, enableMiddleware_SRI },
) => {
const h = /** @satisfies {HashesCollection} */ {
inlineScriptHashes: new Set(),
Expand Down Expand Up @@ -618,7 +631,12 @@ export const processStaticFiles = async (
return
}

await generateSRIHashesModule(h, sriHashesModule)
await generateSRIHashesModule(
logger,
h,
sriHashesModule,
enableMiddleware_SRI,
)
}

/**
Expand Down Expand Up @@ -673,23 +691,23 @@ const loadVirtualMiddlewareModule = async (
sriHashesModule &&
(await doesFileExist(sriHashesModule))
) {
extraImports = `import * as hashesModule from '${sriHashesModule}'`
extraImports = `import { perResourceSriHashes } from '${sriHashesModule}'`
staticHashesModuleLoader = `
try {
if (hashesModule.perResourceSriHashes) {
if (perResourceSriHashes) {
for (const [key, value] of Object.entries(
hashesModule.perResourceSriHashes?.scripts ?? {},
perResourceSriHashes.scripts ?? {},
)) {
globalHashes.scripts.set(key, value)
}
for (const [key, value] of Object.entries(
hashesModule.perResourceSriHashes?.styles ?? {},
perResourceSriHashes.styles ?? {},
)) {
globalHashes.styles.set(key, value)
}
}
} catch (err) {
console.warn('Failed to load static hashes module:', err)
console.error('Failed to load static hashes module:', err)
}
`
} else if (enableStatic_SRI && sriHashesModule) {
Expand Down Expand Up @@ -725,7 +743,7 @@ const loadVirtualHashesModule = async (enableStatic_SRI, sriHashesModule) => {
sriHashesModule &&
(await doesFileExist(sriHashesModule))
) {
return `export * from '${sriHashesModule}'`
return await readFile(sriHashesModule, 'utf8')
}
return `
export const inlineScriptHashes = []
Expand Down
5 changes: 4 additions & 1 deletion src/main.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,10 @@ export type ShieldOptions = {
*/
sriHashesModule?: string | undefined
}
export type StrictShieldOptions = ShieldOptions & { distDir: string }
export type StrictShieldOptions = ShieldOptions & {
distDir: string
enableMiddleware_SRI: boolean
}

// Main Integration
// -----------------------------------------------------------------------------
Expand Down
20 changes: 14 additions & 6 deletions src/main.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -24,21 +24,29 @@ export const shield = ({
enableStatic_SRI,
sriHashesModule,
}) => {
const astroBuildDone =
/** @satisfies {AstroHooks['astro:build:done']} */ async ({
dir,
logger,
}) =>
/**
* @param {boolean} enableMiddleware_SRI
* @returns {NonNullable<AstroHooks['astro:build:done']>}
*/
const getAstroBuildDone =
enableMiddleware_SRI =>
/** @satisfies {NonNullable<AstroHooks['astro:build:done']>} */
async ({ dir, logger }) =>
await processStaticFiles(logger, {
distDir: fileURLToPath(dir),
sriHashesModule,
enableMiddleware_SRI,
})

return /** @satisfies {AstroIntegration} */ {
name: '@kindspells/astro-shield',
hooks: {
...((enableStatic_SRI ?? true) === true
? { 'astro:build:done': astroBuildDone }
? {
'astro:build:done': getAstroBuildDone(
enableMiddleware_SRI ?? false,
),
}
: undefined),
...(enableMiddleware_SRI === true
? {
Expand Down
6 changes: 3 additions & 3 deletions tests/core.test.mts
Original file line number Diff line number Diff line change
Expand Up @@ -362,7 +362,7 @@ describe('updateStaticPageSriHashes', () => {
<title>My Test Page</title>
</head>
<body>
<script type="module" src="/core.mjs" integrity="sha256-etOR/kKV9aCSESe7t5JeBixVQA1DjUU2Zxk13wsPU8M="></script>
<script type="module" src="/core.mjs" integrity="sha256-KnjtswtmvdHQSShp8mURE9kt/62bvYGd5jCdjmbFDiI="></script>
</body>
</html>`

Expand All @@ -379,7 +379,7 @@ describe('updateStaticPageSriHashes', () => {
expect(h.extScriptHashes.size).toBe(1)
expect(
h.extScriptHashes.has(
'sha256-etOR/kKV9aCSESe7t5JeBixVQA1DjUU2Zxk13wsPU8M=',
'sha256-KnjtswtmvdHQSShp8mURE9kt/62bvYGd5jCdjmbFDiI=',
),
).toBe(true)
expect(h.inlineScriptHashes.size).toBe(0)
Expand Down Expand Up @@ -892,7 +892,7 @@ describe('generateSRIHashesModule', () => {
expect(await doesFileExist(modulePath)).toBe(false)

const h = getEmptyHashes()
await generateSRIHashesModule(h, modulePath)
await generateSRIHashesModule(console, h, modulePath, false)

expect(await doesFileExist(modulePath)).toBe(true)

Expand Down

0 comments on commit 62b304a

Please sign in to comment.