-
Notifications
You must be signed in to change notification settings - Fork 109
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add
security
properties for iFrame
Closes #901
- Loading branch information
Showing
15 changed files
with
502 additions
and
20 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
58 changes: 58 additions & 0 deletions
58
packages/form-js-editor/src/features/properties-panel/groups/SecurityAttributesGroup.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
import { get, set } from 'min-dash'; | ||
|
||
import { simpleBoolEntryFactory } from '../entries/factories'; | ||
|
||
import { SECURITY_ATTRIBUTES_DEFINITIONS } from '@bpmn-io/form-js-viewer'; | ||
|
||
|
||
export function SecurityAttributesGroup(field, editField) { | ||
|
||
const entries = createEntries({ field, editField }); | ||
|
||
if (!entries.length) { | ||
return null; | ||
} | ||
|
||
return { | ||
id: 'securityAttributes', | ||
label: 'Security attributes', | ||
entries, | ||
tooltip: getTooltip() | ||
}; | ||
} | ||
|
||
function createEntries(props) { | ||
const { | ||
editField, | ||
field | ||
} = props; | ||
|
||
return SECURITY_ATTRIBUTES_DEFINITIONS.map((definition) => { | ||
const { | ||
label, | ||
property | ||
} = definition; | ||
|
||
return simpleBoolEntryFactory({ | ||
id: property, | ||
label: label, | ||
isDefaultVisible: (field) => field.type === 'iframe', | ||
path: [ 'security', property ], | ||
props, | ||
getValue: () => get(field, [ 'security', property ]), | ||
setValue: (value) => { | ||
const security = get(field, [ 'security' ], {}); | ||
editField(field, [ 'security' ], set(security, [ property ], value)); | ||
} | ||
}); | ||
}); | ||
} | ||
|
||
// helpers ////////// | ||
|
||
function getTooltip() { | ||
return <> | ||
<p>Allow the iframe to access more functionality of your browser, details regarding the various options can be found in the <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe">MDN iFrame documentation.</a></p> | ||
<p>Be cautious when embedding content from external sources. Ensure you trust the source and are aware of the potential security risks.</p> | ||
</>; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
128 changes: 128 additions & 0 deletions
128
...form-js-editor/test/spec/features/properties-panel/groups/SecurityAttributesGroup.spec.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
import { | ||
cleanup, | ||
fireEvent, | ||
render | ||
} from '@testing-library/preact/pure'; | ||
|
||
import { SECURITY_ATTRIBUTES_DEFINITIONS } from '@bpmn-io/form-js-viewer'; | ||
|
||
import { SecurityAttributesGroup } from '../../../../../src/features/properties-panel/groups'; | ||
|
||
import { TestPropertiesPanel, MockPropertiesPanelContext } from '../helper'; | ||
|
||
|
||
describe('SecurityAttributesGroup', function() { | ||
|
||
afterEach(() => cleanup()); | ||
|
||
|
||
it('should NOT render for checkbox', function() { | ||
|
||
// given | ||
const field = { type: 'checkbox' }; | ||
|
||
renderSecurityAttributesGroup({ field }); | ||
|
||
// then | ||
expect(findGroup('appearance', document.body)).to.not.exist; | ||
}); | ||
|
||
SECURITY_ATTRIBUTES_DEFINITIONS.forEach(({ property }) => { | ||
|
||
|
||
describe(property, function() { | ||
|
||
it('should render for iframe', function() { | ||
|
||
// given | ||
const field = { type: 'iframe' }; | ||
|
||
// when | ||
const { container } = renderSecurityAttributesGroup({ field }); | ||
|
||
// then | ||
const input = findInput(property, container); | ||
|
||
expect(input).to.exist; | ||
}); | ||
|
||
|
||
it('should read', function() { | ||
|
||
// given | ||
const field = { | ||
type: 'iframe', | ||
security: { | ||
[property]: true | ||
} | ||
}; | ||
|
||
// when | ||
const { container } = renderSecurityAttributesGroup({ field }); | ||
|
||
const input = findInput(property, container); | ||
|
||
// then | ||
expect(input).to.exist; | ||
expect(input.checked).to.equal(true); | ||
}); | ||
|
||
|
||
it('should write', async function() { | ||
|
||
// given | ||
const field = { | ||
type: 'iframe', | ||
security: { | ||
[property]: true | ||
} | ||
}; | ||
|
||
const editFieldSpy = sinon.spy(); | ||
|
||
const { container } = renderSecurityAttributesGroup({ field, editField: editFieldSpy }); | ||
|
||
const input = findInput(property, container); | ||
|
||
// when | ||
fireEvent.click(input); | ||
|
||
// then | ||
expect(editFieldSpy).to.have.been.calledOnce; | ||
expect(field.security[property]).to.equal(false); | ||
}); | ||
|
||
}); | ||
|
||
}); | ||
|
||
}); | ||
|
||
|
||
// helper /////////////// | ||
|
||
function renderSecurityAttributesGroup(options) { | ||
const { | ||
editField, | ||
field, | ||
services | ||
} = options; | ||
|
||
const groups = [ SecurityAttributesGroup(field, editField) ]; | ||
|
||
return render( | ||
<MockPropertiesPanelContext services={ services }> | ||
<TestPropertiesPanel | ||
field={ field } | ||
groups={ groups } /> | ||
</MockPropertiesPanelContext> | ||
); | ||
} | ||
|
||
function findInput(id, container) { | ||
return container.querySelector(`input[name="${id}"]`); | ||
} | ||
|
||
function findGroup(id, container) { | ||
return container.querySelector(`.bio-properties-panel-group [data-group-id="group-${id}"]`); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
33 changes: 33 additions & 0 deletions
33
packages/form-js-viewer/src/render/hooks/useSecurityAttributesMap.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
import { get } from 'min-dash'; | ||
import { SECURITY_ATTRIBUTES_DEFINITIONS, SANDBOX_ATTRIBUTE } from '../../util/constants'; | ||
import { useMemo } from 'preact/hooks'; | ||
import { useDeepCompareState } from './useDeepCompareState'; | ||
|
||
/** | ||
* A custom hook to build up security attributes from form configuration. | ||
* | ||
* @param {Object} security - The security configuration. | ||
* @returns {Array} - Returns a tuple with sandbox and allow attributes. | ||
*/ | ||
export function useSecurityAttributesMap(security) { | ||
|
||
const securityMemoized = useDeepCompareState(security); | ||
|
||
const sandbox = useMemo(() => | ||
SECURITY_ATTRIBUTES_DEFINITIONS | ||
.filter(({ attribute }) => attribute === SANDBOX_ATTRIBUTE) | ||
.filter(({ property }) => get(securityMemoized, [ property ], false)) | ||
.map(({ directive }) => directive) | ||
.join(' ') | ||
, [ securityMemoized ]); | ||
|
||
const allow = useMemo(() => | ||
SECURITY_ATTRIBUTES_DEFINITIONS | ||
.filter(({ attribute }) => attribute !== SANDBOX_ATTRIBUTE) | ||
.filter(({ property }) => get(securityMemoized, [ property ], false)) | ||
.map(({ directive }) => directive) | ||
.join('; ') | ||
, [ securityMemoized ]); | ||
|
||
return [ sandbox, allow ]; | ||
} |
Oops, something went wrong.