Skip to content

Commit

Permalink
[WIP] (fix) security: OC.dialogs.confirm() change to NcDialog
Browse files Browse the repository at this point in the history
TODO:

* typing: check whether typing "tokenToBeWiped" is possible without as as
  IToken | null (otherwise it's not nullable). Object as PropType<IToken |
  null> did not work.

* styles: confirm/cancel positioning

From nextcloud-libraries/nextcloud-dialogs#1371 (comment)
  • Loading branch information
thlehmann-ionos committed Jul 8, 2024
1 parent ff55aa3 commit fc768b1
Show file tree
Hide file tree
Showing 6 changed files with 64 additions and 40 deletions.
2 changes: 1 addition & 1 deletion src/components/security/AuthToken.vue
Original file line number Diff line number Diff line change
Expand Up @@ -350,7 +350,7 @@ export default defineComponent({
},
wipe() {
this.actionOpen = false
this.authTokenStore.wipeToken(this.token)
this.$emit('wipe', this.token)
},
},
})
Expand Down
1 change: 1 addition & 0 deletions src/components/security/AuthTokenList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
<tbody class="token-list__body">
<AuthToken v-for="token in sortedTokens"
:key="token.id"
@wipe="$emit('wipe', ...arguments)"
:token="token" />
</tbody>
</table>
Expand Down
61 changes: 60 additions & 1 deletion src/components/security/AuthTokenSection.vue
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,38 @@
<p class="settings-hint hidden-when-empty">
{{ t('simplesettings', 'Web, desktop and mobile clients currently logged in to your account.') }}
</p>
<AuthTokenList />
<AuthTokenList @wipe="doWipe" />
<AuthTokenSetup v-if="canCreateToken" />
<NcDialog
:open.sync="confirmingWipe"
:name="t('simplesettings', 'Confirm wipe')"
content-classes="wipe-dialog">
{{ t('simplesettings', 'Do you really want to wipe your data from this device?') }}
<div class="button-row">
<NcButton
@click="cancelWipe">
{{ t('simplesettings', 'Cancel') }}
</NcButton>

<NcButton icon="icon-delete"
@click="confirmedWipe">
{{ t('simplesettings', 'Confirm wipe') }}
</NcButton>
</div>
</NcDialog>
</div>
</template>

<script lang="ts">
// @ts-expect-error: Cannot find module or its corresponding type declarations.
import NcButton from '@nextcloud/vue/dist/Components/NcButton.js'
// @ts-expect-error: Cannot find module or its corresponding type declarations.
import NcDialog from '@nextcloud/vue/dist/Components/NcDialog.js'

import { confirmPassword } from '@nextcloud/password-confirmation'
import { loadState } from '@nextcloud/initial-state'
import { translate as t } from '@nextcloud/l10n'
import { useAuthTokenStore, type IToken } from '../../store/authtoken'
import { defineComponent } from 'vue'

import AuthTokenList from './AuthTokenList.vue'
Expand All @@ -42,16 +66,51 @@ import AuthTokenSetup from './AuthTokenSetup.vue'
export default defineComponent({
name: 'AuthTokenSection',
components: {
NcButton,
NcDialog,
AuthTokenList,
AuthTokenSetup,
},
setup() {
const authTokenStore = useAuthTokenStore()
return { authTokenStore }
},
data() {
return {
canCreateToken: loadState('simplesettings', 'can_create_app_token'),
tokenToBeWiped: null as IToken | null,
confirmingWipe: false,
}
},
methods: {
t,
async doWipe(token: IToken) {
this.tokenToBeWiped = token
this.confirmingWipe = true

await confirmPassword()
},
async cancelWipe() {
this.tokenToBeWiped = null
this.confirmingWipe = false
},
async confirmedWipe() {
if (this.tokenToBeWiped === null) {
return
}
await this.authTokenStore.wipeToken(this.tokenToBeWiped as IToken)
this.tokenToBeWiped = null
this.confirmingWipe = false
},
},
})
</script>

<style scoped>
.button-row {
display: flex;
flex-direction: row;
margin: 10px 0;
gap: 4px;
}
</style>
2 changes: 2 additions & 0 deletions src/components/security/AuthTokenSetup.vue
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@

<script lang="ts">
import { showError } from '@nextcloud/dialogs'
import { confirmPassword } from '@nextcloud/password-confirmation'
import { translate as t } from '@nextcloud/l10n'
import { defineComponent } from 'vue'
import { useAuthTokenStore, type ITokenResponse } from '../../store/authtoken'
Expand Down Expand Up @@ -77,6 +78,7 @@ export default defineComponent({
async submit() {
try {
this.loading = true
await confirmPassword()
this.newToken = await this.authTokenStore.addToken(this.deviceName)
} catch (error) {
logger.error(error as Error)
Expand Down
17 changes: 0 additions & 17 deletions src/oc.d.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1 @@
/// <reference types="@nextcloud/typings" />

declare namespace Nextcloud29WithPolyfills {
interface DialogsPolyfill {
confirm(
title: string,
message: string,
callback: () => void,
modal: boolean): void;
}

interface OC extends Nextcloud.v29.OC {
dialogs: Nextcloud.Common.Dialogs & DialogsPolyfill;
}
}

// eslint-disable-next-line no-var
declare var OC: Nextcloud29WithPolyfills
21 changes: 0 additions & 21 deletions src/store/authtoken.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
import { showError } from '@nextcloud/dialogs'
import { loadState } from '@nextcloud/initial-state'
import { translate as t } from '@nextcloud/l10n'
import { confirmPassword } from '@nextcloud/password-confirmation'
import { generateUrl } from '@nextcloud/router'
import { defineStore } from 'pinia'

Expand All @@ -31,17 +30,6 @@ import logger from '../logger'

const BASE_URL = generateUrl('/apps/simplesettings/authtokens')

const confirm = () => {
return new Promise(resolve => {
window.OC.dialogs.confirm(
t('simplesettings', 'Do you really want to wipe your data from this device?'),
t('simplesettings', 'Confirm wipe'),
resolve,
true,
)
})
}

export enum TokenType {
TEMPORARY_TOKEN = 0,
PERMANENT_TOKEN = 1,
Expand Down Expand Up @@ -101,8 +89,6 @@ export const useAuthTokenStore = defineStore('auth-token', {
logger.debug('Creating a new app token')

try {
await confirmPassword()

const { data } = await axios.post<ITokenResponse>(BASE_URL, { name })
this.tokens.push(data.deviceToken)
logger.debug('App token created')
Expand Down Expand Up @@ -142,13 +128,6 @@ export const useAuthTokenStore = defineStore('auth-token', {
logger.debug('Wiping app token', { token })

try {
await confirmPassword()

if (!(await confirm())) {
logger.debug('Wipe aborted by user')
return
}

await axios.post(`${BASE_URL}/wipe/${token.id}`)
logger.debug('App token marked for wipe', { token })

Expand Down

0 comments on commit fc768b1

Please sign in to comment.