Skip to content

Commit

Permalink
Specify iframe sandbox and allow rules (#3650)
Browse files Browse the repository at this point in the history
  • Loading branch information
JohannesDoberer authored Feb 23, 2024
1 parent 0613d51 commit ad0b5de
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 2 deletions.
25 changes: 23 additions & 2 deletions container/src/LuigiContainer.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,16 @@
reflect: false,
attribute: 'client-permissions',
},
allowRules: {
type: 'Array',
reflect: false,
attribute: 'allow-rules',
},
sandboxRules: {
type: 'Array',
reflect: false,
attribute: 'sandbox-rules',
},
},
extend: (customElementConstructor) => {
let notInitFn = (name) => {
Expand Down Expand Up @@ -71,6 +81,7 @@
import { ContainerAPI } from './api/container-api';
import { Events } from './constants/communication';
import { GenericHelperFunctions } from './utilities/helpers';
import { getAllowRules } from './services/iframe-helpers';
export let viewurl: string;
export let context: string;
Expand All @@ -85,6 +96,8 @@
export let searchParams: any;
export let pathParams: any;
export let clientPermissions: any;
export let allowRules: string[];
export let sandboxRules: string[];
export let userSettings: any;
export let anchor: string;
Expand All @@ -111,7 +124,9 @@
pathParams &&
clientPermissions &&
userSettings &&
anchor
anchor &&
allowRules &&
sandboxRules
);
};
Expand Down Expand Up @@ -197,7 +212,13 @@
>
{#if containerInitialized}
{#if !webcomponent}
<iframe bind:this={iframeHandle.iframe} src={viewurl} title={label} />
<iframe
bind:this={iframeHandle.iframe}
src={viewurl}
title={label}
allow={getAllowRules(allowRules)}
sandbox={sandboxRules ? sandboxRules.join(' ') : undefined}
/>
{/if}
{/if}
</main>
Expand Down
14 changes: 14 additions & 0 deletions container/src/services/iframe-helpers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/**
* Retrieves the allow rules for iframes and modifies them according to w3c standard conditions.
* @param {string[]} allowRules - An array of allow rules.
* @returns {string|undefined} The modified allow rules joined as a single string, or undefined if allowRules is falsy.
*/
export const getAllowRules = (allowRules: string[]) => {
if (!allowRules) return undefined;
const rules = allowRules;
rules.forEach((rule, index) => {
rules[index] = rule + (rule.indexOf(';') != -1 ? '' : ';');
rules[index] = (allowRules[index] as any).replaceAll('"', "'");
});
return rules.join(' ');
};
2 changes: 2 additions & 0 deletions container/test-app/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,8 @@
<luigi-container
viewURL="https://fiddle.luigi-project.io/examples/microfrontends/fundamental/table-demo-page.html"
context='{"title": "Team", "content":""}'
allow-rules='["fullscreen", "microphone", "camera \"none\"", "geolocation \"self\" https://a.example.com https://b.example.com"]'
sandbox-rules='["allow-scripts", "allow-same-origin"]'
></luigi-container>
</div>
<div class="lui-wrapper" route="projects">
Expand Down
23 changes: 23 additions & 0 deletions container/test/services/iframe-helpers.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { getAllowRules } from '../../src/services/iframe-helpers';

describe('getAllowRules function', () => {
it('returns undefined if allowRules is undefined', () => {
expect(getAllowRules(undefined)).toBeUndefined();
});

it('returns an empty string if allowRules is an empty array', () => {
expect(getAllowRules([])).toBe('');
});

it('if semicolon already present, keep it.', () => {
const allowRules = ['rule1', 'rule2;', 'rule3;'];
const expectedRules = 'rule1; rule2; rule3;';
expect(getAllowRules(allowRules)).toBe(expectedRules);
});

it('replaces double quotes with single quotes in each rule', () => {
const allowRules = ["fullscreen", "microphone", "camera \"none\"", "geolocation \"self\" https://a.example.com https://b.example.com"];
const expectedRules = "fullscreen; microphone; camera 'none'; geolocation 'self' https://a.example.com https://b.example.com;";
expect(getAllowRules(allowRules)).toBe(expectedRules);
});
});
12 changes: 12 additions & 0 deletions container/typings/LuigiContainer.svelte.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,18 @@ export default class LuigiContainer extends HTMLElement {
*/
anchor: string;

/**
* The list of rules for the content in the iframe, managed by the HTML `allow` attribute.
* You can use one or more rules by adding them to the array, for example allowRules: ["microphone", "camera"].
*/
allowRules: string[];

/**
* The list of rules for the content in the iframe, managed by the HTML `sandbox` attribute.
* You can use one or more rules by adding them to the array, for example sandboxRules: ["allow-scripts", "allow-same-origin"].
*/
sandboxRules: string[];

/**
* Function that updates the context of the microfrontend
* @param {Object} contextObj The context data
Expand Down

0 comments on commit ad0b5de

Please sign in to comment.