Unverified Commit 9233d19c authored by mvdbeek's avatar mvdbeek
Browse files

Display warning if ouput sanitized

parent 733a9cf8
Loading
Loading
Loading
Loading
+91 −40
Original line number Diff line number Diff line
<script setup lang="ts">
import { computed, ref, watch } from "vue";

import { useUserStore } from "@/stores/userStore";
import { withPrefix } from "@/utils/redirect";

import Alert from "@/components/Alert.vue";
import LoadingSpan from "@/components/LoadingSpan.vue";

const emit = defineEmits(["load"]);
const props = withDefaults(
    defineProps<{
        id?: string;
        src?: string;
        isPreview?: boolean;
    }>(),
    {
        id: "frame",
        src: "",
        isPreview: false,
    }
);

const { isAdmin } = useUserStore();
const srcWithRoot = computed(() => withPrefix(props.src));
const sanitizedImport = ref(false);
const sanitizedToolId = ref<String | false>(false);
const isLoading = ref(true);
watch(
    () => srcWithRoot.value,
    async () => {
        sanitizedImport.value = false;
        sanitizedToolId.value = false;
        if (props.isPreview) {
            try {
                const response = await fetch(srcWithRoot.value, { method: "HEAD" });
                const isImported = response.headers.get("x-sanitized-job-imported");
                const toolId = response.headers.get("x-sanitized-tool-id");
                if (isImported !== null) {
                    sanitizedImport.value = true;
                } else if (toolId !== null) {
                    sanitizedToolId.value = toolId;
                }
            } catch (e) {
                // I guess that's fine and the center panel will show something
                console.error(e);
            }
        }
    },
    { immediate: true }
);

const plainText = "Contents are shown as plain text.";
const sanitizedMessage = computed(() => {
    if (sanitizedImport.value) {
        return `Dataset has been imported. ${plainText}`;
    } else if (sanitizedToolId.value) {
        return `Dataset created by a tool that is not known to create safe HTML. ${plainText}`;
    }
    return undefined;
});

function onLoad(ev: Event) {
    isLoading.value = false;
    const iframe = ev.currentTarget as HTMLIFrameElement;
    const location = iframe?.contentWindow && iframe.contentWindow.location;
    try {
        if (location && location.host && location.pathname != "/") {
            emit("load");
        }
    } catch (err) {
        console.warn("CenterFrame - onLoad location access forbidden.", ev, location);
    }
}
</script>
<template>
    <div>
        <Alert v-if="sanitizedMessage" :dismissible="true" variant="warning">
            {{ sanitizedMessage }}
            <p v-if="isAdmin && sanitizedToolId">
                <router-link to="/admin/sanitize_allow">Review Allowlist</router-link> if outputs of
                {{ sanitizedToolId }} are trusted and should be shown as HTML.
            </p>
        </Alert>
        <LoadingSpan v-if="isLoading">Loading ...</LoadingSpan>
        <iframe
            :id="id"
            :name="id"
@@ -9,38 +93,5 @@
            width="100%"
            height="100%"
            @load="onLoad" />
    </div>
</template>
<script>
import { withPrefix } from "utils/redirect";

export default {
    props: {
        id: {
            type: String,
            default: "frame",
        },
        src: {
            type: String,
            default: "",
        },
    },
    computed: {
        srcWithRoot() {
            return withPrefix(this.src);
        },
    },
    methods: {
        onLoad(ev) {
            const iframe = ev.currentTarget;
            const location = iframe.contentWindow && iframe.contentWindow.location;
            try {
                if (location && location.host && location.pathname != "/") {
                    this.$emit("load");
                }
            } catch (err) {
                console.warn("CenterFrame - onLoad location access forbidden.", ev, location);
            }
        },
    },
};
</script>
+1 −0
Original line number Diff line number Diff line
@@ -238,6 +238,7 @@ export function getRouter(Galaxy) {
                        component: CenterFrame,
                        props: (route) => ({
                            src: `/datasets/${route.params.datasetId}/display/?preview=True`,
                            isPreview: true,
                        }),
                    },
                    {
+2 −0
Original line number Diff line number Diff line
@@ -641,8 +641,10 @@ class Data(metaclass=DataMeta):
            content_type = "text/html"
            if from_dataset.creating_job.imported:
                content_type = "text/plain"
                headers["x-sanitized-job-imported"] = True
            if not from_dataset.creating_job.tool_id.startswith(tuple(trans.app.config.sanitize_allowlist)):
                content_type = "text/plain"
                headers["x-sanitized-tool-id"] = from_dataset.creating_job.tool_id
            headers["content-type"] = content_type

        return open(filename, mode="rb")