Add ability to export data as otpauth URIs - Closes #386

This commit is contained in:
Bubka
2024-11-08 08:41:11 +01:00
parent 63a700da44
commit 3e2a80b816
14 changed files with 309 additions and 31 deletions

View File

@ -71,7 +71,7 @@
:disabled='areDisabled' class="button is-rounded"
:class="[{ 'is-outlined': mode == 'dark' || areDisabled }, areDisabled ? 'is-dark': 'is-link']"
@click="$emit('export-button-clicked')"
:title="$t('twofaccounts.export_selected_to_json')" >
:title="$t('twofaccounts.export_selected_accounts')" >
{{ $t('commons.export') }}
</button>
</p>

View File

@ -0,0 +1,39 @@
<script setup>
import { UseColorMode } from '@vueuse/components'
const router = useRouter()
const emit = defineEmits(['export-twofauth-format', 'export-otpauth-format'])
const $2fauth = inject('2fauth')
</script>
<template>
<div class="block">
<UseColorMode v-slot="{ mode }">
<p class="has-text-weight-bold has-text-grey">
{{ $t('twofaccounts.twofauth_export_format_sub') }}
</p>
</UseColorMode>
<p class="is-size-7-mobile">
{{ $t('twofaccounts.twofauth_export_format_desc') }}
{{ $t('twofaccounts.twofauth_export_format_url') }}
<a id="lnkExportSchemaUrl" class="is-link" tabindex="0" :href="$2fauth.urls.exportSchemaUrl" target="_blank">
{{ $t('twofaccounts.twofauth_export_schema') }}
</a>
</p>
<button id="btnExport2FAuth" class="button is-link is-rounded is-focus my-3" @click="$emit('export-twofauth-format')" :title="$t('twofaccounts.export_selected_to_json')">
{{ $t('twofaccounts.twofauth_export_format') }}
</button>
</div>
<div class="block">
<p class="has-text-weight-bold has-text-grey">
{{ $t('twofaccounts.otpauth_export_format_sub') }}
</p>
<p class="is-size-7-mobile">
{{ $t('twofaccounts.otpauth_export_format_desc') }}
</p>
<button id="btnExportOtpauth" class="button is-link is-rounded is-focus my-3" @click="$emit('export-otpauth-format')" :title="$t('twofaccounts.export_selected_to_otpauth_uri')">
{{ $t('twofaccounts.otpauth_export_format') }}
</button>
</div>
</template>

View File

@ -55,8 +55,8 @@ export default {
return apiClient.delete('/twofaccounts?ids=' + ids, { ...config })
},
export(ids, config = {}) {
return apiClient.get('/twofaccounts/export?ids=' + ids, { ...config })
export(ids, otpauthFormat, config = {}) {
return apiClient.get('/twofaccounts/export?ids=' + ids + (otpauthFormat ? '&otpauth=1' : ''), { ...config })
},
getQrcode(id, config = {}) {

View File

@ -163,12 +163,25 @@ export const useTwofaccounts = defineStore({
/**
* Exports selected accounts to a json file
*/
export() {
twofaccountService.export(this.selectedIds.join(), {responseType: 'blob'})
.then((response) => {
var blob = new Blob([response.data], {type: "application/json;charset=utf-8"});
saveAs.saveAs(blob, "2fauth_export.json");
})
export(format = '2fauth') {
if (format == 'otpauth') {
twofaccountService.export(this.selectedIds.join(), true)
.then((response) => {
let uris = []
response.data.data.forEach(account => {
uris.push(account.uri)
});
var blob = new Blob([uris.join('\n')], {type: "text/plain;charset=utf-8"});
saveAs.saveAs(blob, "2fauth_export_otpauth.txt");
})
}
else {
twofaccountService.export(this.selectedIds.join(), false, {responseType: 'blob'})
.then((response) => {
var blob = new Blob([response.data], {type: "application/json;charset=utf-8"});
saveAs.saveAs(blob, "2fauth_export.json");
})
}
},
/**

View File

@ -7,6 +7,7 @@
import Toolbar from '@/components/Toolbar.vue'
import OtpDisplay from '@/components/OtpDisplay.vue'
import ActionButtons from '@/components/ActionButtons.vue'
import ExportButtons from '@/components/ExportButtons.vue'
import Dots from '@/components/Dots.vue'
import { UseColorMode } from '@vueuse/components'
import { useUserStore } from '@/stores/user'
@ -29,6 +30,7 @@
const groups = useGroups()
const showOtpInModal = ref(false)
const showExportFormatSelector = ref(false)
const showGroupSwitch = ref(false)
const showDestinationGroupSelector = ref(false)
const isDragging = ref(false)
@ -357,7 +359,14 @@
</div>
</div>
</div>
<!-- modal -->
<!-- export modal -->
<Modal v-model="showExportFormatSelector" :isFullHeight="true">
<ExportButtons
@export-twofauth-format="twofaccounts.export()"
@export-otpauth-format="twofaccounts.export('otpauth')">
</ExportButtons>
</Modal>
<!-- otp modal -->
<Modal v-model="showOtpInModal">
<OtpDisplay
ref="otpDisplay"
@ -467,7 +476,7 @@
:areDisabled="twofaccounts.hasNoneSelected"
@move-button-clicked="showDestinationGroupSelector = true"
@delete-button-clicked="deleteAccounts"
@export-button-clicked="twofaccounts.export()">
@export-button-clicked="showExportFormatSelector = true">
</ActionButtons>
</VueFooter>
</div>