diff options
Diffstat (limited to 'apps/files_sharing/src')
-rw-r--r-- | apps/files_sharing/src/public-file-request.ts | 57 | ||||
-rw-r--r-- | apps/files_sharing/src/public-nickname-handler.ts | 86 | ||||
-rw-r--r-- | apps/files_sharing/src/services/GuestNameValidity.ts | 2 | ||||
-rw-r--r-- | apps/files_sharing/src/views/PublicAuthPrompt.vue | 138 |
4 files changed, 87 insertions, 196 deletions
diff --git a/apps/files_sharing/src/public-file-request.ts b/apps/files_sharing/src/public-file-request.ts deleted file mode 100644 index 1d640c5ea5e..00000000000 --- a/apps/files_sharing/src/public-file-request.ts +++ /dev/null @@ -1,57 +0,0 @@ -/** - * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors - * SPDX-License-Identifier: AGPL-3.0-or-later - */ - -import { defineAsyncComponent } from 'vue' -import { getBuilder } from '@nextcloud/browser-storage' -import { getGuestNickname, setGuestNickname } from '@nextcloud/auth' -import { getUploader } from '@nextcloud/upload' -import { spawnDialog } from '@nextcloud/dialogs' - -import logger from './services/logger' - -const storage = getBuilder('files_sharing').build() - -/** - * Setup file-request nickname header for the uploader - * @param nickname The nickname - */ -function registerFileRequestHeader(nickname: string) { - const uploader = getUploader() - uploader.setCustomHeader('X-NC-Nickname', encodeURIComponent(nickname)) - logger.debug('Nickname header registered for uploader', { headers: uploader.customHeaders }) -} - -/** - * Callback when a nickname was chosen - * @param nickname The chosen nickname - */ -function onSetNickname(nickname: string): void { - // Set the nickname - setGuestNickname(nickname) - // Set the dialog as shown - storage.setItem('public-auth-prompt-shown', 'true') - // Register header for uploader - registerFileRequestHeader(nickname) -} - -window.addEventListener('DOMContentLoaded', () => { - const nickname = getGuestNickname() ?? '' - const dialogShown = storage.getItem('public-auth-prompt-shown') !== null - - // If we don't have a nickname or the public auth prompt hasn't been shown yet, show it - // We still show the prompt if the user has a nickname to double check - if (!nickname || !dialogShown) { - spawnDialog( - defineAsyncComponent(() => import('./views/PublicAuthPrompt.vue')), - { - nickname, - }, - onSetNickname as (...rest: unknown[]) => void, - ) - } else { - logger.debug('Public auth prompt already shown.', { nickname }) - registerFileRequestHeader(nickname) - } -}) diff --git a/apps/files_sharing/src/public-nickname-handler.ts b/apps/files_sharing/src/public-nickname-handler.ts new file mode 100644 index 00000000000..02bdc641aaf --- /dev/null +++ b/apps/files_sharing/src/public-nickname-handler.ts @@ -0,0 +1,86 @@ +/** + * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +import { getBuilder } from '@nextcloud/browser-storage' +import { getGuestNickname, type NextcloudUser } from '@nextcloud/auth' +import { getUploader } from '@nextcloud/upload' +import { loadState } from '@nextcloud/initial-state' +import { showGuestUserPrompt } from '@nextcloud/dialogs' +import { t } from '@nextcloud/l10n' + +import logger from './services/logger' +import { subscribe } from '@nextcloud/event-bus' + +const storage = getBuilder('files_sharing').build() + +// Setup file-request nickname header for the uploader +const registerFileRequestHeader = (nickname: string) => { + const uploader = getUploader() + uploader.setCustomHeader('X-NC-Nickname', encodeURIComponent(nickname)) + logger.debug('Nickname header registered for uploader', { headers: uploader.customHeaders }) +} + +// Callback when a nickname was chosen +const onUserInfoChanged = (guest: NextcloudUser) => { + logger.debug('User info changed', { guest }) + registerFileRequestHeader(guest.displayName ?? '') +} + +// Monitor nickname changes +subscribe('user:info:changed', onUserInfoChanged) + +window.addEventListener('DOMContentLoaded', () => { + const nickname = getGuestNickname() ?? '' + const dialogShown = storage.getItem('public-auth-prompt-shown') !== null + + // Check if a nickname is mandatory + const isFileRequest = loadState('files_sharing', 'isFileRequest', false) + + const owner = loadState('files_sharing', 'owner', '') + const ownerDisplayName = loadState('files_sharing', 'ownerDisplayName', '') + const label = loadState('files_sharing', 'label', '') + const filename = loadState('files_sharing', 'filename', '') + + // If the owner provided a custom label, use it instead of the filename + const folder = label || filename + + const options = { + nickname, + notice: t('files_sharing', 'To upload files to {folder}, you need to provide your name first.', { folder }), + subtitle: undefined as string | undefined, + title: t('files_sharing', 'Upload files to {folder}', { folder }), + } + + // If the guest already has a nickname, we just make them double check + if (nickname) { + options.notice = t('files_sharing', 'Please confirm your name to upload files to {folder}', { folder }) + } + + // If the account owner set their name as public, + // we show it in the subtitle + if (owner) { + options.subtitle = t('files_sharing', '{ownerDisplayName} shared a folder with you.', { ownerDisplayName }) + } + + // If this is a file request, then we need a nickname + if (isFileRequest) { + // If we don't have a nickname or the public auth prompt hasn't been shown yet, show it + // We still show the prompt if the user has a nickname to double check + if (!nickname || !dialogShown) { + logger.debug('Showing public auth prompt.', { nickname }) + showGuestUserPrompt(options) + } + return + } + + if (!dialogShown && !nickname) { + logger.debug('Public auth prompt not shown yet but nickname is not mandatory.', { nickname }) + return + } + + // Else, we just register the nickname header if any. + logger.debug('Public auth prompt already shown.', { nickname }) + registerFileRequestHeader(nickname) +}) diff --git a/apps/files_sharing/src/services/GuestNameValidity.ts b/apps/files_sharing/src/services/GuestNameValidity.ts index 249a1a6fbb4..0557c5253ca 100644 --- a/apps/files_sharing/src/services/GuestNameValidity.ts +++ b/apps/files_sharing/src/services/GuestNameValidity.ts @@ -13,7 +13,7 @@ import { t } from '@nextcloud/l10n' */ export function getGuestNameValidity(name: string, escape = false): string { if (name.trim() === '') { - return t('files', 'Filename must not be empty.') + return t('files', 'Names must not be empty.') } if (name.startsWith('.')) { diff --git a/apps/files_sharing/src/views/PublicAuthPrompt.vue b/apps/files_sharing/src/views/PublicAuthPrompt.vue deleted file mode 100644 index 28955a87154..00000000000 --- a/apps/files_sharing/src/views/PublicAuthPrompt.vue +++ /dev/null @@ -1,138 +0,0 @@ -<!-- - - SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors - - SPDX-License-Identifier: AGPL-3.0-or-later ---> - -<template> - <NcDialog :buttons="dialogButtons" - class="public-auth-prompt" - data-cy-public-auth-prompt-dialog - is-form - :can-close="false" - :name="dialogName" - @submit="$emit('close', name)"> - <p v-if="owner" class="public-auth-prompt__subtitle"> - {{ t('files_sharing', '{ownerDisplayName} shared a folder with you.', { ownerDisplayName }) }} - </p> - - <!-- Header --> - <NcNoteCard class="public-auth-prompt__header" - :text="t('files_sharing', 'To upload files, you need to provide your name first.')" - type="info" /> - - <!-- Form --> - <NcTextField ref="input" - class="public-auth-prompt__input" - data-cy-public-auth-prompt-dialog-name - :label="t('files_sharing', 'Name')" - :placeholder="t('files_sharing', 'Enter your name')" - minlength="2" - name="name" - required - :value.sync="name" /> - </NcDialog> -</template> - -<script lang="ts"> -import { defineComponent } from 'vue' -import { loadState } from '@nextcloud/initial-state' -import { t } from '@nextcloud/l10n' - -import NcDialog from '@nextcloud/vue/components/NcDialog' -import NcNoteCard from '@nextcloud/vue/components/NcNoteCard' -import NcTextField from '@nextcloud/vue/components/NcTextField' - -import { getGuestNameValidity } from '../services/GuestNameValidity' - -export default defineComponent({ - name: 'PublicAuthPrompt', - - components: { - NcDialog, - NcNoteCard, - NcTextField, - }, - - props: { - /** - * Preselected nickname - * @default '' No name preselected by default - */ - nickname: { - type: String, - default: '', - }, - }, - - setup() { - return { - t, - - owner: loadState('files_sharing', 'owner', ''), - ownerDisplayName: loadState('files_sharing', 'ownerDisplayName', ''), - label: loadState('files_sharing', 'label', ''), - note: loadState('files_sharing', 'note', ''), - filename: loadState('files_sharing', 'filename', ''), - } - }, - - data() { - return { - name: '', - } - }, - - computed: { - dialogName() { - return this.t('files_sharing', 'Upload files to {folder}', { folder: this.label || this.filename }) - }, - dialogButtons() { - return [{ - label: t('files_sharing', 'Submit name'), - type: 'primary', - nativeType: 'submit', - }] - }, - }, - - watch: { - /** Reset name to pre-selected nickname (e.g. Talk / Collabora ) */ - nickname: { - handler() { - this.name = this.nickname - }, - immediate: true, - }, - - name() { - // Check validity of the new name - const newName = this.name.trim?.() || '' - const input = (this.$refs.input as Vue|undefined)?.$el.querySelector('input') - if (!input) { - return - } - - const validity = getGuestNameValidity(newName) - input.setCustomValidity(validity) - input.reportValidity() - }, - }, -}) -</script> -<style scoped lang="scss"> -.public-auth-prompt { - &__subtitle { - // Smaller than dialog title - font-size: 1.25em; - margin-block: 0 calc(3 * var(--default-grid-baseline)); - } - - &__header { - margin-block: 0 calc(3 * var(--default-grid-baseline)); - } - - &__input { - margin-block: calc(4 * var(--default-grid-baseline)) calc(2 * var(--default-grid-baseline)); - } -} -</style> |