Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Confirmation to enable Package Files Server #3388

Merged
merged 7 commits into from
Mar 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 18 additions & 5 deletions catalog/app/components/Dialog/Confirm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,22 @@ import * as React from 'react'
import * as M from '@material-ui/core'

interface DialogProps {
cancelTitle?: string
children: React.ReactNode
onSubmit: (value: boolean) => void
open: boolean
submitTitle?: string
title: string
}

function Dialog({ children, onSubmit, open, title }: DialogProps) {
function Dialog({
children,
onSubmit,
open,
cancelTitle = 'Cancel',
submitTitle = 'Submit',
title,
}: DialogProps) {
const handleCancel = React.useCallback(() => onSubmit(false), [onSubmit])
const handleSubmit = React.useCallback(() => onSubmit(true), [onSubmit])
return (
Expand All @@ -18,22 +27,24 @@ function Dialog({ children, onSubmit, open, title }: DialogProps) {
<M.DialogContent>{children}</M.DialogContent>
<M.DialogActions>
<M.Button onClick={handleCancel} color="primary" variant="outlined">
Cancel
{cancelTitle}
</M.Button>
<M.Button color="primary" onClick={handleSubmit} variant="contained">
Submit
{submitTitle}
</M.Button>
</M.DialogActions>
</M.Dialog>
)
}

interface PromptProps {
cancelTitle?: string
onSubmit: (value: boolean) => void
submitTitle?: string
title: string
}

export function useConfirm({ title, onSubmit }: PromptProps) {
export function useConfirm({ cancelTitle, title, onSubmit, submitTitle }: PromptProps) {
const [key, setKey] = React.useState(0)
const [opened, setOpened] = React.useState(false)
const open = React.useCallback(() => {
Expand All @@ -52,15 +63,17 @@ export function useConfirm({ title, onSubmit }: PromptProps) {
(children: React.ReactNode) => (
<Dialog
{...{
cancelTitle,
children,
key,
onSubmit: handleSubmit,
open: opened,
submitTitle,
title,
}}
/>
),
[key, handleSubmit, opened, title],
[cancelTitle, key, handleSubmit, opened, title, submitTitle],
)
return React.useMemo(
() => ({
Expand Down
80 changes: 62 additions & 18 deletions catalog/app/containers/Admin/Buckets/Buckets.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import * as M from '@material-ui/core'
import * as Lab from '@material-ui/lab'

import BucketIcon from 'components/BucketIcon'
import * as Dialog from 'components/Dialog'
import * as Pagination from 'components/Pagination'
import Skeleton from 'components/Skeleton'
import * as Notifications from 'containers/Notifications'
Expand Down Expand Up @@ -81,6 +82,66 @@ const integerInRange = (min: number, max: number) => (v: string | null | undefin
return undefined
}

const usePFSCheckboxStyles = M.makeStyles({
root: {
marginBottom: -9,
marginTop: -9,
},
})
function PFSCheckbox({ input, meta }: Form.CheckboxProps & M.CheckboxProps) {
const classes = usePFSCheckboxStyles()
const confirm = React.useCallback((checked) => input?.onChange(checked), [input])
const dialog = Dialog.useConfirm({
submitTitle: 'I agree',
title:
'You are about to enable JavaScript execution and data access in iframe previews of HTML files',
onSubmit: confirm,
})
const handleCheckbox = React.useCallback(
(event, checked: boolean) => {
if (checked) {
dialog.open()
} else {
input?.onChange(checked)
}
},
[dialog, input],
)
return (
<>
{dialog.render(
<M.Typography>
Warning: you must only enable this feature for buckets with trusted contents.
Failure to heed this warning may result in breach of sensitive data.
</M.Typography>,
)}
<M.FormControlLabel
control={
<M.Checkbox
classes={classes}
disabled={meta.submitting || meta.submitSucceeded}
checked={!!input?.checked}
onChange={handleCheckbox}
/>
}
label={
<>
Enable permissive HTML rendering
<Hint>
This allows execution of any linked JavaScript code and fetching network
resources relative to the package. Be aware that the iframe with rendered
HTML (and package resources) can be shared publicly during the session
lifespan. The session is active while the page with rendered HTML is open.
<br />
Enable only on trusted AWS S3 buckets.
</Hint>
</>
}
/>
</>
)
}

const editFormSpec: FormSpec<Model.GQLTypes.BucketUpdateInput> = {
title: R.pipe(
R.prop('title'),
Expand Down Expand Up @@ -648,24 +709,7 @@ function BucketFields({ bucket, reindex }: BucketFieldsProps) {
<M.Typography variant="h6">File preview options</M.Typography>
</M.AccordionSummary>
<M.Box className={classes.group} pt={1}>
<RF.Field
component={Form.Checkbox}
type="checkbox"
name="browsable"
label={
<>
Enable permissive HTML rendering
<Hint>
This allows execution of any JavaScript code and fetching network
resources relative to package. But beware, the iframe with rendered HTML
(and package resources) can be shared publicly during session lifespan.
Session is active while the page with rendered HTML is opened.
<br />
Enable only on trusted buckets.
</Hint>
</>
}
/>
<RF.Field component={PFSCheckbox} name="browsable" type="checkbox" />
</M.Box>
</M.Accordion>
</M.Box>
Expand Down
4 changes: 2 additions & 2 deletions catalog/app/containers/Admin/Form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,11 @@ const useCheckboxStyles = M.makeStyles({
},
})

interface CheckboxProps {
export interface CheckboxProps {
errors?: Record<string, React.ReactNode>
input?: RF.FieldInputProps<boolean>
meta: RF.FieldMetaState<string | Symbol>
label?: string
label?: React.ReactNode
FormControlLabelProps?: M.FormControlLabelProps
}

Expand Down
1 change: 1 addition & 0 deletions docs/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ Entries inside each section should be ordered by type:
* [Added] Add basic support for tasklist in Markdown ([#3339](https://github.com/quiltdata/quilt/pull/3339))
* [Added] Object-level validation, frontend ([#3336](https://github.com/quiltdata/quilt/pull/3336))
* [Added] Frontend for permissive HTML rendering ([#3198](https://github.com/quiltdata/quilt/pull/3198))
* [Added] Confirmation to enable Package Files Server ([#3388](https://github.com/quiltdata/quilt/pull/3388))
* [Fixed] Fixed mobile layout for collaborators badges ([#3307](https://github.com/quiltdata/quilt/pull/3307))
* [Fixed] Fixed metadata handling for entries without hash or size in pkgpush lambda ([#3314](https://github.com/quiltdata/quilt/pull/3314))
* [Fixed] Fixed adding metadata for S3 entries ([#3367]https://github.com/quiltdata/quilt/pull/3367)
Expand Down