mirror of
https://github.com/trailofbits/algo.git
synced 2025-07-13 17:22:56 +02:00
223 lines
6.6 KiB
Vue
223 lines
6.6 KiB
Vue
<template>
|
|
<div>
|
|
<div v-if="ui_config_error && ui_config_error === 'missing_google'" class="form-text alert alert-danger" role="alert">
|
|
Python module "google-auth" is missing, please install it to proceed
|
|
</div>
|
|
<div v-if="ui_config_error && ui_config_error === 'missing_requests'" class="form-text alert alert-danger" role="alert">
|
|
Python module "requests" is missing, please install it to proceed
|
|
</div>
|
|
<div
|
|
class="form-group dropzone"
|
|
v-if="ui_needs_upload"
|
|
v-on:dragover.prevent="dragover_handler"
|
|
v-on:dragleave.prevent="dragleave_handler"
|
|
v-on:drop.prevent="drop_handler"
|
|
v-on:click="show_file_select"
|
|
v-bind:class="{
|
|
'dropzone--can-drop': ui_can_drop,
|
|
'dropzone--error': ui_drop_error,
|
|
'dropzone--success': ui_drop_success,
|
|
}"
|
|
>
|
|
<strong>Drag your GCE config file or click here</strong>
|
|
<p>
|
|
File <code>configs/gce.json</code> was not found. Please create it (<a
|
|
href="https://github.com/trailofbits/algo/blob/master/docs/cloud-gce.md"
|
|
target="_blank"
|
|
rel="noopener noreferrer"
|
|
>how?</a
|
|
>) or upload.
|
|
</p>
|
|
<p>After upload it <strong>will be saved</strong> in the configs folder.</p>
|
|
<div v-if="ui_drop_error" class="alert alert-warning" role="alert">
|
|
<strong>Error:</strong> {{ ui_drop_error }}.
|
|
</div>
|
|
|
|
<div v-if="ui_drop_success" class="alert alert-success" role="alert">
|
|
<strong>{{ ui_drop_filename }} loaded successfully</strong>
|
|
</div>
|
|
</div>
|
|
<div v-else class="form-text alert alert-success" role="alert">
|
|
Google Compute Engine credentials were found in the project
|
|
</div>
|
|
<input type="file" accept=".json,applciation/json" v-on:change="filechange_handler" />
|
|
<region-select v-model="region" v-bind:options="ui_region_options" v-bind:loading="ui_loading_check || ui_loading_regions">
|
|
<label v-if="ui_needs_upload">Please select region</label>
|
|
<label v-else>Please specify <code>gce.json</code> credentials file to select region</label>
|
|
</region-select>
|
|
<button
|
|
class="btn btn-primary"
|
|
type="button"
|
|
v-on:click="submit"
|
|
v-bind:disabled="!is_valid"
|
|
>
|
|
Next
|
|
</button>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
module.exports = {
|
|
data: function () {
|
|
return {
|
|
drop_error: null,
|
|
gce_credentials_file: null,
|
|
region: null,
|
|
// helper variables
|
|
ui_can_drop: false,
|
|
ui_drop_error: null,
|
|
ui_drop_success: null,
|
|
ui_drop_filename: null,
|
|
ui_config_error: null,
|
|
ui_needs_upload: null,
|
|
ui_loading_regions: false,
|
|
ui_loading_check: false,
|
|
ui_region_options: []
|
|
};
|
|
},
|
|
created: function() {
|
|
this.check_config();
|
|
},
|
|
computed: {
|
|
is_valid() {
|
|
return this.gce_credentials_file && this.region;
|
|
}
|
|
},
|
|
methods: {
|
|
show_file_select(e) {
|
|
if (e.target.tagName === 'A') {
|
|
return;
|
|
}
|
|
const input = this.$el.querySelector(['input[type=file]']);
|
|
const event = new MouseEvent('click', {
|
|
'view': window,
|
|
'bubbles': true,
|
|
'cancelable': true
|
|
});
|
|
input.dispatchEvent(event);
|
|
},
|
|
dragover_handler(e) {
|
|
this.ui_can_drop = true;
|
|
this.ui_drop_success = false;
|
|
this.ui_drop_error = false;
|
|
this.ui_drop_filename = null;
|
|
},
|
|
dragleave_handler() {
|
|
this.ui_can_drop = false;
|
|
},
|
|
drop_handler(e) {
|
|
try {
|
|
const droppedFiles = e.dataTransfer.files;
|
|
if (droppedFiles.length !== 1) {
|
|
this.ui_drop_error = 'Please upload GCE config as single file';
|
|
}
|
|
this.read_file(droppedFiles[0]);
|
|
} catch (e) {
|
|
this.ui_drop_error = 'Unhandled error while trying to read GCE config';
|
|
}
|
|
},
|
|
filechange_handler(e) {
|
|
if (e.target.files.length) {
|
|
this.read_file(e.target.files[0]);
|
|
}
|
|
},
|
|
read_file(file) {
|
|
if (file.type !== 'application/json') {
|
|
this.ui_drop_error = 'Incorrect file type';
|
|
}
|
|
const reader = new FileReader();
|
|
reader.onload = e => {
|
|
let gce_config_content = null;
|
|
try {
|
|
gce_config_content = JSON.parse(e.target.result);
|
|
this.ui_drop_success = true;
|
|
this.ui_drop_filename = file.name;
|
|
this.gce_credentials_file = 'configs/gce.json';
|
|
} catch (e) {
|
|
this.ui_drop_error = 'JSON format error';
|
|
}
|
|
gce_config_content && this.load_regions(gce_config_content);
|
|
}
|
|
reader.onerror = e => {
|
|
this.ui_drop_error = 'Error while reading file';
|
|
}
|
|
reader.readAsText(file);
|
|
|
|
},
|
|
check_config() {
|
|
this.ui_loading_check = true;
|
|
fetch("/gce_config")
|
|
.then(r => {
|
|
if (r.status === 200 || r.status === 400) {
|
|
return r.json();
|
|
}
|
|
throw new Error(r.status);
|
|
})
|
|
.then(response => {
|
|
if (response.status === 'ok') {
|
|
this.gce_credentials_file = 'configs/gce.json';
|
|
this.load_regions();
|
|
this.ui_needs_upload = false;
|
|
} else if (response.error) {
|
|
this.ui_config_error = response.error;
|
|
} else {
|
|
this.ui_needs_upload = true;
|
|
}
|
|
})
|
|
.finally(() => {
|
|
this.ui_loading_check = false;
|
|
});
|
|
},
|
|
load_regions(gce_config_content) {
|
|
if (this.gce_credentials_file && this.ui_region_options.length === 0) {
|
|
this.ui_loading_regions = true;
|
|
fetch("/gce_regions", {
|
|
method: "post",
|
|
headers: {
|
|
"Content-Type": "application/json",
|
|
},
|
|
body: gce_config_content ? JSON.stringify(gce_config_content) : '{}',
|
|
})
|
|
.then((r) => r.json())
|
|
.then((data) => {
|
|
this.ui_region_options = data.items.map(i => ({
|
|
value: i.name,
|
|
key: i.name
|
|
}));
|
|
})
|
|
.finally(() => {
|
|
this.ui_loading_regions = false;
|
|
});
|
|
}
|
|
},
|
|
submit() {
|
|
this.$emit("submit", {
|
|
gce_credentials_file: this.gce_credentials_file,
|
|
region: this.region,
|
|
});
|
|
},
|
|
},
|
|
components: {
|
|
"region-select": window.httpVueLoader("/static/region-select.vue"),
|
|
},
|
|
};
|
|
</script>
|
|
<style scoped>
|
|
.dropzone {
|
|
padding: 2em;
|
|
border: 5px dotted #ccc;
|
|
cursor: pointer;
|
|
}
|
|
input[type=file] {
|
|
visibility: hidden;
|
|
}
|
|
.dropzone--can-drop {
|
|
border-color: var(--blue);
|
|
}
|
|
.dropzone--error {
|
|
border-color: var(--red);
|
|
}
|
|
.dropzone--success {
|
|
border-color: var(--green);
|
|
}
|
|
</style>
|