@@ -0,0 +1,95 @@ | |||
<!-- Copyright (c) 2020 Bubble, Inc. All rights reserved. For personal (non-commercial) use, see license: https://getbubblenow.com/bubble-license/ --> | |||
<template> | |||
<div class="bubble-form"> | |||
<h4 class="text-center form-title"> | |||
{{ messages.manage_account_delete_title }} | |||
</h4> | |||
<span v-if="me && currentUser.name != 'root'"> | |||
<div class="form-group"> | |||
{{ messages.field_label_policy_account_deletion }}: | |||
<img v-show="!policy" :src="loadingImgSrc" /> | |||
<b>{{ messages["account_deletion_name_" + policy.deletionPolicy] }}</b> | |||
<br /> | |||
<span> | |||
{{ | |||
messages["account_deletion_description_" + policy.deletionPolicy] | |||
}} | |||
</span> | |||
<br /> | |||
{{ messages.account_deletion_change_tip }} | |||
<br /> | |||
<Button | |||
class="btn btn-danger" | |||
name="deleteAccountBtn" | |||
:disabled="!policy || deleteRequestSent" | |||
v-on:click="clickRequestUserDeletion()" | |||
> | |||
{{ messages.button_label_delete_account }} | |||
</Button> | |||
<img v-show="loading()" :src="loadingImgSrc" /> | |||
<div | |||
v-if="errors.requestUserDeletion" | |||
class="invalid-feedback d-block alert alert-danger" | |||
> | |||
{{ errors.requestUserDeletion }} | |||
</div> | |||
<div v-else-if="deleteRequestSent" class="alert alert-info"> | |||
{{ messages.field_label_account_delete_requested_notice }} | |||
</div> | |||
</div> | |||
</span> | |||
</div> | |||
</template> | |||
<style lang="scss" scoped> | |||
@import "../../../_scss/components/form"; | |||
.bubble-form { | |||
width: 800px; | |||
} | |||
</style> | |||
<script> | |||
import { mapState, mapActions, mapGetters } from "vuex"; | |||
import { util } from "~/_helpers"; | |||
import { loadingImgSrc } from "~/_store"; | |||
import { Button } from "~/_components/shared"; | |||
export default { | |||
components: { Button }, | |||
data() { | |||
return { | |||
currentUser: util.currentUser(), | |||
submitted: false, | |||
loadingImgSrc: loadingImgSrc, | |||
}; | |||
}, | |||
computed: { | |||
...mapState("system", ["messages"]), | |||
...mapState("users", ["policy", "deleteRequestSent", "errors"]), | |||
}, | |||
methods: { | |||
...mapActions("users", ["getPolicyByUserId", "requestUserDeletion"]), | |||
...mapGetters("users", ["loading"]), | |||
clickRequestUserDeletion() { | |||
this.errors.clear(); | |||
this.requestUserDeletion({ | |||
userId: this.currentUser.uuid, | |||
messages: this.messages, | |||
errors: this.errors, | |||
}); | |||
return false; // do not follow the click | |||
}, | |||
}, | |||
created() { | |||
if (util.validateAccount(this)) { | |||
this.getPolicyByUserId({ | |||
userId: this.currentUser.uuid, | |||
messages: this.messages, | |||
errors: this.errors, | |||
}); | |||
} | |||
}, | |||
}; | |||
</script> |
@@ -221,6 +221,10 @@ export const router = new Router({ | |||
path: 'me/policy', | |||
component: () => import('~/_pages/main/account/Policy'), | |||
}, | |||
{ | |||
path: 'me/delete', | |||
component: () => import('~/_pages/main/account/Delete'), | |||
}, | |||
{ | |||
path: 'devices', | |||
@@ -29,6 +29,7 @@ export const userService = { | |||
createUser, | |||
updateUser, | |||
deleteUser, | |||
requestUserDeletion, | |||
changePassword, | |||
adminChangePassword, | |||
approveAction, | |||
@@ -223,6 +224,13 @@ function deleteUser(userId, messages, errors) { | |||
return fetch(`${config.apiUrl}/users/${userId}`, util.deleteWithAuth()).then(util.handleCrudResponse(messages, errors)); | |||
} | |||
function requestUserDeletion(userId, messages, errors) { | |||
return fetch( | |||
`${config.apiUrl}/users/${userId}/request`, | |||
util.deleteWithAuth()) | |||
.then(util.handleCrudResponse(messages, errors)); | |||
} | |||
function changePassword(request, messages, errors) { | |||
return fetch(`${config.apiUrl}/me/changePassword`, util.postWithAuth(request)).then(util.handleCrudResponse(messages, errors)); | |||
} | |||
@@ -10,7 +10,7 @@ const state = { | |||
loading: { | |||
users: false, user: false, creating: false, updating: false, deleting: false, changingPassword: false, | |||
policy: false, updatingPolicy: false, addPolicyContact: false, removePolicyContact: false, | |||
listSshKeys: false, addSshKey: false, removeSshKey: false | |||
listSshKeys: false, addSshKey: false, removeSshKey: false, sendingDeleteRequest: false | |||
}, | |||
errors: {}, | |||
users: null, | |||
@@ -20,7 +20,8 @@ const state = { | |||
authenticator: {}, | |||
sshKey: null, | |||
sshKeys: [], | |||
changePasswordResponse: null | |||
changePasswordResponse: null, | |||
deleteRequestSent: false | |||
}; | |||
export const CONTACT_TYPE_AUTHENTICATOR = 'authenticator'; | |||
@@ -175,6 +176,15 @@ const actions = { | |||
); | |||
}, | |||
requestUserDeletion({ commit }, { userId, messages, errors }) { | |||
commit("requestUserDeletionRequest", userId); | |||
userService.requestUserDeletion(userId, messages, errors) | |||
.then((id) => commit("requestUserDeletionSuccess", id), | |||
(error) => commit("requestUserDeletionFailure", | |||
{ userId, error: error.toString() }) | |||
); | |||
}, | |||
changePassword({ commit }, {request, messages, errors}) { | |||
commit('changePasswordRequest', request); | |||
userService.changePassword(request, messages, errors) | |||
@@ -364,6 +374,20 @@ const mutations = { | |||
state.errors.deleteUser = error; | |||
}, | |||
requestUserDeletionRequest(state, id) { | |||
state.loading.sendingDeleteRequest = true; | |||
state.deleteRequestSent = false; | |||
}, | |||
requestUserDeletionSuccess(state, id) { | |||
state.loading.sendingDeleteRequest = false; | |||
state.deleteRequestSent = true; | |||
}, | |||
requestUserDeletionFailure(state, { id, error }) { | |||
state.loading.sendingDeleteRequest = false; | |||
state.deleteRequestSent = false; | |||
state.errors.requestUserDeletion = error; | |||
}, | |||
changePasswordRequest(state, id) { | |||
state.loading.changingPassword = true; | |||
}, | |||