diff options
Diffstat (limited to 'apps/settings/src/components/AuthTokenSection.vue')
-rw-r--r-- | apps/settings/src/components/AuthTokenSection.vue | 178 |
1 files changed, 178 insertions, 0 deletions
diff --git a/apps/settings/src/components/AuthTokenSection.vue b/apps/settings/src/components/AuthTokenSection.vue new file mode 100644 index 00000000000..c53256102d3 --- /dev/null +++ b/apps/settings/src/components/AuthTokenSection.vue @@ -0,0 +1,178 @@ +<!-- + - @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at> + - + - @author 2019 Christoph Wurst <christoph@winzerhof-wurst.at> + - + - @license GNU AGPL version 3 or any later version + - + - This program is free software: you can redistribute it and/or modify + - it under the terms of the GNU Affero General Public License as + - published by the Free Software Foundation, either version 3 of the + - License, or (at your option) any later version. + - + - This program is distributed in the hope that it will be useful, + - but WITHOUT ANY WARRANTY; without even the implied warranty of + - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + - GNU Affero General Public License for more details. + - + - You should have received a copy of the GNU Affero General Public License + - along with this program. If not, see <http://www.gnu.org/licenses/>. + --> + +<template> + <div id="security" class="section"> + <h2>{{ t('settings', 'Devices & sessions') }}</h2> + <p class="settings-hint hidden-when-empty">{{ t('settings', 'Web, desktop and mobile clients currently logged in to your account.') }}</p> + <AuthTokenList :tokens="tokens" + @toggleScope="toggleTokenScope" + @rename="rename" + @delete="deleteToken" + @wipe="wipeToken" /> + <AuthTokenSetupDialogue v-if="canCreateToken" :add="addNewToken" /> + </div> +</template> + +<script> + import Axios from 'nextcloud-axios'; + import confirmPassword from 'nextcloud-password-confirmation'; + + import AuthTokenList from './AuthTokenList'; + import AuthTokenSetupDialogue from './AuthTokenSetupDialogue'; + + const confirm = () => { + return new Promise(res => { + OC.dialogs.confirm( + t('core', 'Do you really want to wipe your data from this device?'), + t('core', 'Confirm wipe'), + res, + true + ) + }) + } + + /** + * Tap into a promise without losing the value + */ + const tap = cb => val => { + cb(val); + return val; + }; + + export default { + name: "AuthTokenSection", + props: { + tokens: { + type: Array, + required: true, + }, + canCreateToken: { + type: Boolean, + required: true + } + }, + components: { + AuthTokenSetupDialogue, + AuthTokenList + }, + data() { + return { + baseUrl: OC.generateUrl('/settings/personal/authtokens'), + } + }, + methods: { + addNewToken (name) { + console.debug('creating a new app token', name); + + const data = { + name, + }; + return Axios.post(this.baseUrl, data) + .then(resp => resp.data) + .then(tap(() => console.debug('app token created'))) + .then(tap(data => this.tokens.push(data.deviceToken))) + .catch(err => { + console.error.bind('could not create app password', err); + OC.Notification.showTemporary(t('core', 'Error while creating device token')); + throw err; + }); + }, + toggleTokenScope (token, scope, value) { + console.debug('updating app token scope', token.id, scope, value); + + const oldVal = token.scope[scope]; + token.scope[scope] = value; + + return this.updateToken(token) + .then(tap(() => console.debug('app token scope updated'))) + .catch(err => { + console.error.bind('could not update app token scope', err); + OC.Notification.showTemporary(t('core', 'Error while updating device token scope')); + + // Restore + token.scope[scope] = oldVal; + + throw err; + }) + }, + rename (token, newName) { + console.debug('renaming app token', token.id, token.name, newName); + + const oldName = token.name; + token.name = newName; + + return this.updateToken(token) + .then(tap(() => console.debug('app token name updated'))) + .catch(err => { + console.error.bind('could not update app token name', err); + OC.Notification.showTemporary(t('core', 'Error while updating device token name')); + + // Restore + token.name = oldName; + }) + }, + updateToken (token) { + return Axios.put(this.baseUrl + '/' + token.id, token) + .then(resp => resp.data) + }, + deleteToken (token) { + console.debug('deleting app token', token); + + this.tokens = this.tokens.filter(t => t !== token); + + return Axios.delete(this.baseUrl + '/' + token.id) + .then(resp => resp.data) + .then(tap(() => console.debug('app token deleted'))) + .catch(err => { + console.error.bind('could not delete app token', err); + OC.Notification.showTemporary(t('core', 'Error while deleting the token')); + + // Restore + this.tokens.push(token); + }) + }, + async wipeToken(token) { + console.debug('wiping app token', token); + + try { + await confirmPassword() + + if (!(await confirm())) { + console.debug('wipe aborted by user') + return; + } + await Axios.post(this.baseUrl + '/wipe/' + token.id) + console.debug('app token marked for wipe') + + token.type = 2; + } catch (err) { + console.error('could not wipe app token', err); + OC.Notification.showTemporary(t('core', 'Error while wiping the device with the token')); + } + } + } + } +</script> + +<style scoped> + +</style> |