jcloud/dashboard/src2/views/site/DatabaseAccessDialog.vue

323 lines
7.9 KiB
Vue

<template>
<Dialog
:options="{ title: 'Access Database' }"
v-if="site"
v-model="showDialog"
@close="dialogClosed"
>
<template v-slot:body-content>
<LoadingText v-if="$resources.fetchDatabaseAccessInfo.loading" />
<!-- Not available on current plan, upsell higher plans -->
<div v-else-if="!databaseAccessInfo?.is_available_on_current_plan">
<div>
<p class="text-base">
Database access is not available on your current plan. Please
upgrade your plan to access your site database.
</p>
<Button
class="mt-4 w-full"
variant="solid"
@click="showChangePlanDialog = true"
>Upgrade Site Plan</Button
>
</div>
<Dialog
:options="{
title: 'Upgrade Plan',
actions: [
{
label: 'Submit',
variant: 'solid',
loading: $resources.changePlan.loading,
onClick: () => $resources.changePlan.submit()
}
]
}"
v-model="showChangePlanDialog"
>
<template v-slot:body-content>
<SitePlansTable
class="mt-3"
:plans="plans"
v-model:selectedPlan="selectedPlan"
/>
<ErrorMessage class="mt-4" :message="$resources.changePlan.error" />
</template>
</Dialog>
</div>
<!-- Available on the current plan -->
<div v-else>
<div v-if="databaseAccessInfo">
<div v-if="databaseAccessInfo.is_database_access_enabled">
<div>
<p class="mb-2 text-base font-semibold text-gray-700">
Using an Analytics or Business Intelligence Tool
</p>
<p class="mb-2 text-base">
Use following credentials with your analytics or business
intelligence tool
</p>
<p class="ml-1 font-mono text-sm">
Host: {{ databaseAccessInfo.credentials.host }}
</p>
<p class="ml-1 font-mono text-sm">
Port: {{ databaseAccessInfo.credentials.port }}
</p>
<p class="ml-1 font-mono text-sm">
Database Name: {{ databaseAccessInfo.credentials.database }}
</p>
<p class="ml-1 font-mono text-sm">
Username: {{ databaseAccessInfo.credentials.username }}
</p>
<p class="ml-1 font-mono text-sm">
Password: {{ databaseAccessInfo.credentials.password }}
</p>
</div>
<div class="pb-2 pt-5">
<p class="mb-2 text-base font-semibold text-gray-700">
Using MariaDB Client
</p>
<p class="mb-2 text-base">
<span
>Run this command in your terminal to access MariaDB
console</span
>
</p>
<ClickToCopyField class="ml-1" :textContent="dbAccessCommand" />
<p class="mt-3 text-sm">
Note: You should have a
<span class="font-mono">mariadb</span> client installed on your
computer.
</p>
</div>
</div>
<div v-else>
<p class="mb-2 text-sm">
Database console access is disabled for this site.
</p>
</div>
</div>
<div class="mt-4">
<div
v-if="
databaseAccessInfo &&
!databaseAccessInfo.is_database_access_enabled
"
class="mb-2"
>
<!-- Enable Read-Write Access -->
<FormControl
type="checkbox"
label="Enable Read-Write Access"
v-model="enableReadWriteAccess"
/>
<ErrorMessage
class="mt-2"
:message="
error ||
(enableReadWriteAccess &&
'Your credentials can be used to modify or wipe your database')
"
/>
</div>
<Button
v-if="
databaseAccessInfo &&
!databaseAccessInfo.is_database_access_enabled
"
@click="$resources.enableDatabaseAccess.submit()"
:loading="
$resources.enableDatabaseAccess.loading || pollingAgentJob
"
variant="solid"
class="mt-2 w-full"
>Enable
{{ enableReadWriteAccess ? 'Read-Write' : 'Read-Only' }}
Access</Button
>
<Button
v-if="
databaseAccessInfo &&
databaseAccessInfo.is_database_access_enabled
"
@click="$resources.disableDatabaseAccess.submit()"
:loading="
$resources.disableDatabaseAccess.loading || pollingAgentJob
"
class="w-full"
>Disable Access</Button
>
</div>
</div>
</template>
</Dialog>
</template>
<script>
import ClickToCopyField from '@/components/ClickToCopyField.vue';
import SitePlansTable from '@/components/SitePlansTable.vue';
import { notify } from '@/utils/toast';
import { jingrowRequest } from 'jingrow-ui';
export default {
props: ['site', 'modelValue'],
emits: ['update:modelValue'],
data() {
return {
pollingAgentJob: false,
showChangePlanDialog: false,
selectedPlan: null,
enableReadWriteAccess: false,
error: null
};
},
components: {
ClickToCopyField,
SitePlansTable
},
resources: {
fetchDatabaseAccessInfo() {
return {
url: 'jcloud.api.site.get_database_access_info',
params: {
name: this.site
},
auto: true
};
},
enableDatabaseAccess() {
return {
url: 'jcloud.api.site.enable_database_access',
params: {
name: this.site,
mode: this.enableReadWriteAccess ? 'read_write' : 'read_only'
},
onSuccess(d) {
this.pollDatabaseAccessJob(d);
}
};
},
disableDatabaseAccess() {
return {
url: 'jcloud.api.site.disable_database_access',
params: {
name: this.site
},
onSuccess(d) {
this.pollDatabaseAccessJob(d);
}
};
},
plans() {
return {
url: 'jcloud.api.site.get_plans',
params: {
name: this.site
},
initialData: [],
auto: true
};
},
changePlan() {
return {
url: 'jcloud.api.site.change_plan',
params: {
name: this.site,
plan: this.selectedPlan?.name
},
onSuccess() {
notify({
title: `Plan changed to ${this.selectedPlan.plan_title}`,
icon: 'check',
color: 'green'
});
this.showChangePlanDialog = false;
this.selectedPlan = null;
this.$resources.plans.reset();
this.$resources.fetchDatabaseAccessInfo.fetch();
},
onError(error) {
this.showChangePlanDialog = false;
notify({
title: error,
icon: 'x',
color: 'red'
});
}
};
}
},
computed: {
databaseAccessInfo() {
if (
!this.$resources.fetchDatabaseAccessInfo.loading &&
this.$resources.fetchDatabaseAccessInfo.data
) {
return this.$resources.fetchDatabaseAccessInfo.data;
}
return null;
},
dbAccessCommand() {
if (this.databaseAccessInfo) {
const { credentials } = this.databaseAccessInfo;
return `mysql -u ${credentials.username} -p -h ${credentials.host} -P ${credentials.port} --ssl --ssl-verify-server-cert`;
}
return null;
},
plans() {
let processedPlans = this.$resources.plans.data.map(plan => {
if (!plan.database_access) {
plan.disabled = true;
}
return plan;
});
return processedPlans;
},
showDialog: {
get() {
return this.modelValue;
},
set(value) {
this.$emit('update:modelValue', value);
}
}
},
methods: {
dialogClosed() {
this.$emit('update:show', null);
},
pollDatabaseAccessJob(jobName) {
this.pollingAgentJob = true;
jingrowRequest({
url: 'jcloud.api.site.get_job_status',
params: {
job_name: jobName
}
}).then(message => {
console.log(message);
if (message.status === 'Success') {
this.pollingAgentJob = false;
this.$resources.fetchDatabaseAccessInfo.fetch();
} else if (message.status === 'Failure') {
this.pollingAgentJob = false;
this.error = 'Something went wrong. Please try again.';
} else {
setTimeout(() => {
this.pollDatabaseAccessJob(jobName);
}, 1000);
}
});
}
}
};
</script>