123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320 |
- <script setup lang="ts">
- import { useStore } from "vuex";
- import { ref, onMounted } from "vue";
- import { useRoute } from "vue-router";
- import Toast from "toasters";
- defineProps({
- modalUuid: { type: String, default: "" }
- });
- const route = useRoute();
- const store = useStore();
- const { socket } = store.state.websockets;
- const isPasswordLinked = () => store.dispatch("settings/isPasswordLinked");
- const isGithubLinked = () => store.dispatch("settings/isGithubLinked");
- const closeCurrentModal = () =>
- store.dispatch("modalVisibility/closeCurrentModal");
- const step = ref("confirm-identity");
- const apiDomain = ref("");
- const accountRemovalMessage = ref("");
- const password = ref({
- value: "",
- visible: false
- });
- const passwordElement = ref();
- const checkForAutofill = (cb, event) => {
- if (
- event.target.value !== "" &&
- event.inputType === undefined &&
- event.data === undefined &&
- event.dataTransfer === undefined &&
- event.isComposing === undefined
- )
- cb();
- };
- const submitOnEnter = (cb, event) => {
- if (event.which === 13) cb();
- };
- const togglePasswordVisibility = () => {
- if (passwordElement.value.type === "password") {
- passwordElement.value.type = "text";
- password.value.visible = true;
- } else {
- passwordElement.value.type = "password";
- password.value.visible = false;
- }
- };
- const confirmPasswordMatch = () =>
- socket.dispatch("users.confirmPasswordMatch", password.value.value, res => {
- if (res.status === "success") step.value = "remove-account";
- else new Toast(res.message);
- });
- const confirmGithubLink = () =>
- socket.dispatch("users.confirmGithubLink", res => {
- if (res.status === "success") {
- if (res.data.linked) step.value = "remove-account";
- else {
- new Toast(
- `Your GitHub account isn't linked. Please re-link your account and try again.`
- );
- step.value = "relink-github";
- }
- } else new Toast(res.message);
- });
- const relinkGithub = () => {
- localStorage.setItem(
- "github_redirect",
- `${window.location.pathname + window.location.search}${
- !route.query.removeAccount ? "&removeAccount=relinked-github" : ""
- }`
- );
- };
- const remove = () =>
- socket.dispatch("users.remove", res => {
- if (res.status === "success") {
- return socket.dispatch("users.logout", () =>
- lofig.get("cookie").then(cookie => {
- document.cookie = `${cookie.SIDname}=;expires=Thu, 01 Jan 1970 00:00:01 GMT;`;
- closeCurrentModal();
- window.location.href = "/";
- })
- );
- }
- return new Toast(res.message);
- });
- onMounted(async () => {
- apiDomain.value = await lofig.get("backend.apiDomain");
- accountRemovalMessage.value = await lofig.get("messages.accountRemoval");
- });
- </script>
- <template>
- <modal
- title="Confirm Account Removal"
- class="confirm-account-removal-modal"
- >
- <template #body>
- <div id="steps">
- <p
- class="step"
- :class="{ selected: step === 'confirm-identity' }"
- >
- 1
- </p>
- <span class="divider"></span>
- <p
- class="step"
- :class="{
- selected:
- (isPasswordLinked && step === 'export-data') ||
- step === 'relink-github'
- }"
- >
- 2
- </p>
- <span class="divider"></span>
- <p
- class="step"
- :class="{
- selected:
- (isPasswordLinked && step === 'remove-account') ||
- step === 'export-data'
- }"
- >
- 3
- </p>
- <span class="divider" v-if="!isPasswordLinked"></span>
- <p
- class="step"
- :class="{ selected: step === 'remove-account' }"
- v-if="!isPasswordLinked"
- >
- 4
- </p>
- </div>
- <div
- class="content-box"
- id="password-linked"
- v-if="step === 'confirm-identity' && isPasswordLinked"
- >
- <h2 class="content-box-title">Enter your password</h2>
- <p class="content-box-description">
- Confirming your password will let us verify your identity.
- </p>
- <p class="content-box-optional-helper">
- <router-link id="forgot-password" to="/reset_password">
- Forgot password?
- </router-link>
- </p>
- <div class="content-box-inputs">
- <div class="control is-grouped input-with-button">
- <div id="password-visibility-container">
- <input
- class="input"
- type="password"
- placeholder="Enter password here..."
- autofocus
- ref="passwordElement"
- v-model="password.value"
- @input="
- checkForAutofill(
- confirmPasswordMatch,
- $event
- )
- "
- @keypress="
- submitOnEnter(confirmPasswordMatch, $event)
- "
- />
- <a @click="togglePasswordVisibility()">
- <i class="material-icons">
- {{
- !password.visible
- ? "visibility"
- : "visibility_off"
- }}
- </i>
- </a>
- </div>
- <p class="control">
- <button
- class="button is-info"
- @click="confirmPasswordMatch()"
- >
- Check
- </button>
- </p>
- </div>
- </div>
- </div>
- <div
- class="content-box"
- v-else-if="isGithubLinked && step === 'confirm-identity'"
- >
- <h2 class="content-box-title">Verify your GitHub</h2>
- <p class="content-box-description">
- Check your account is still linked to remove your account.
- </p>
- <div class="content-box-inputs">
- <a class="button is-github" @click="confirmGithubLink()">
- <div class="icon">
- <img
- class="invert"
- src="/assets/social/github.svg"
- />
- </div>
- Check GitHub is linked
- </a>
- </div>
- </div>
- <div class="content-box" v-if="step === 'relink-github'">
- <h2 class="content-box-title">Re-link GitHub</h2>
- <p class="content-box-description">
- Re-link your GitHub account in order to verify your
- identity.
- </p>
- <div class="content-box-inputs">
- <a
- class="button is-github"
- @click="relinkGithub()"
- :href="`${apiDomain}/auth/github/link`"
- >
- <div class="icon">
- <img
- class="invert"
- src="/assets/social/github.svg"
- />
- </div>
- Re-link GitHub to account
- </a>
- </div>
- </div>
- <div v-if="step === 'export-data'">
- DOWNLOAD A BACKUP OF YOUR DATA BEFORE ITS PERMENATNELY DELETED
- </div>
- <div
- class="content-box"
- id="remove-account-container"
- v-if="step === 'remove-account'"
- >
- <h2 class="content-box-title">Remove your account</h2>
- <p class="content-box-description">
- {{ accountRemovalMessage }}
- </p>
- <div class="content-box-inputs">
- <quick-confirm placement="right" @confirm="remove()">
- <button class="button">
- <i class="material-icons">delete</i>
- Remove Account
- </button>
- </quick-confirm>
- </div>
- </div>
- </template>
- </modal>
- </template>
- <style lang="less">
- .confirm-account-removal-modal {
- .modal-card {
- width: 650px;
- }
- }
- </style>
- <style lang="less" scoped>
- h2 {
- margin: 0;
- }
- .content-box {
- margin-top: 20px;
- max-width: unset;
- }
- #steps {
- margin-top: 0;
- }
- #password-linked {
- #password-visibility-container {
- width: 100%;
- }
- > a {
- color: var(--primary-color);
- }
- }
- .control {
- margin-bottom: 0 !important;
- }
- #remove-account-container .content-box-inputs {
- width: fit-content;
- }
- </style>
|