fix(files_sharing): Set file-request header for nextcloud/upload

Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>
pull/45652/head
Ferdinand Thiessen 2024-09-04 18:33:06 +07:00
parent 3134053497
commit 1dafdce3e7
No known key found for this signature in database
GPG Key ID: 45FAE7268762B400
4 changed files with 105 additions and 89 deletions

@ -3,21 +3,54 @@
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
import { getGuestNickname, setGuestNickname } from '@nextcloud/auth'
import { spawnDialog } from '@nextcloud/dialogs'
import { getUploader } from '@nextcloud/upload'
import { defineAsyncComponent } from 'vue'
import logger from './services/logger'
import { getBuilder } from '@nextcloud/browser-storage'
const nick = localStorage.getItem('nick')
const publicAuthPromptShown = localStorage.getItem('publicAuthPromptShown')
const storage = getBuilder('files_sharing').build()
// 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 (!nick || !publicAuthPromptShown) {
spawnDialog(
defineAsyncComponent(() => import('./views/PublicAuthPrompt.vue')),
{},
() => localStorage.setItem('publicAuthPromptShown', 'true'),
)
} else {
logger.debug(`Public auth prompt already shown. Current nickname is '${nick}'`)
/**
* Setup file-request nickname header for the uploader
* @param nickname The nickname
*/
function registerFileRequestHeader(nickname: string) {
const uploader = getUploader()
uploader.setCustomHeader('X-NC-Nickname', 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)
}
})

@ -4,46 +4,32 @@
-->
<template>
<NcDialog class="public-auth-prompt"
<NcDialog :buttons="dialogButtons"
class="public-auth-prompt"
data-cy-public-auth-prompt-dialog
dialog-classes="public-auth-prompt__dialog"
is-form
:can-close="false"
:name="dialogName">
<h3 v-if="owner" class="public-auth-prompt__subtitle">
: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 }) }}
</h3>
</p>
<!-- Header -->
<NcNoteCard type="info" class="public-auth-prompt__header">
<p id="public-auth-prompt-dialog-description" class="public-auth-prompt__description">
{{ t('files_sharing', 'To upload files, you need to provide your name first.') }}
</p>
</NcNoteCard>
<NcNoteCard class="public-auth-prompt__header"
:text="t('files_sharing', 'To upload files, you need to provide your name first.')"
type="info" />
<!-- Form -->
<form ref="form"
aria-describedby="public-auth-prompt-dialog-description"
class="public-auth-prompt__form"
@submit.prevent.stop="">
<NcTextField ref="input"
class="public-auth-prompt__input"
data-cy-public-auth-prompt-dialog-name
:label="t('files_sharing', 'Enter your name')"
:minlength="2"
:required="true"
:value.sync="name"
name="name" />
</form>
<!-- Submit -->
<template #actions>
<NcButton ref="submit"
data-cy-public-auth-prompt-dialog-submit
:disabled="name.trim() === ''"
@click="onSubmit">
{{ t('files_sharing', 'Submit name') }}
</NcButton>
</template>
<NcTextField ref="input"
class="public-auth-prompt__input"
data-cy-public-auth-prompt-dialog-name
:label="t('files_sharing', 'Nickname')"
:placeholder="t('files_sharing', 'Enter your nickname')"
minlength="2"
name="name"
required
:value.sync="name" />
</NcDialog>
</template>
@ -51,7 +37,6 @@
import { defineComponent } from 'vue'
import { t } from '@nextcloud/l10n'
import NcButton from '@nextcloud/vue/dist/Components/NcButton.js'
import NcDialog from '@nextcloud/vue/dist/Components/NcDialog.js'
import NcNoteCard from '@nextcloud/vue/dist/Components/NcNoteCard.js'
import NcTextField from '@nextcloud/vue/dist/Components/NcTextField.js'
@ -61,12 +46,22 @@ export default defineComponent({
name: 'PublicAuthPrompt',
components: {
NcButton,
NcDialog,
NcNoteCard,
NcTextField,
},
props: {
/**
* Preselected nickname
* @default '' No name preselected by default
*/
nickname: {
type: String,
default: '',
},
},
setup() {
return {
t,
@ -89,51 +84,40 @@ export default defineComponent({
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',
}]
},
},
beforeMount() {
// Pre-load the name from local storage if already set by another app
// like Talk, Colabora or Text...
const talkNick = localStorage.getItem('nick')
if (talkNick) {
this.name = talkNick
}
},
methods: {
onSubmit() {
const form = this.$refs.form as HTMLFormElement
if (!form.checkValidity()) {
form.reportValidity()
return
}
if (this.name.trim() === '') {
return
}
localStorage.setItem('nick', this.name)
this.$emit('close')
watch: {
/** Reset name to pre-selected nickname (e.g. Talk / Collabora ) */
nickname: {
handler() {
this.name = this.nickname
},
immediate: true,
},
},
})
</script>
<style lang="scss">
<style scoped lang="scss">
.public-auth-prompt {
&__subtitle {
// Smaller than dialog title
font-size: 16px;
margin-block: 12px;
font-size: 1.25em;
margin-block: 0 calc(3 * var(--default-grid-baseline));
}
&__header {
// Fix extra margin generating an unwanted gap
margin-block: 12px;
margin-block: 0 calc(3 * var(--default-grid-baseline));
}
&__form {
// Double the margin of the header
margin-block: 24px;
&__input {
margin-block: calc(4 * var(--default-grid-baseline)) calc(2 * var(--default-grid-baseline));
}
}
</style>

19
package-lock.json generated

@ -29,7 +29,7 @@
"@nextcloud/paths": "^2.2.1",
"@nextcloud/router": "^3.0.0",
"@nextcloud/sharing": "^0.2.3",
"@nextcloud/upload": "^1.5.0",
"@nextcloud/upload": "^1.6.0",
"@nextcloud/vue": "^8.17.1",
"@simplewebauthn/browser": "^10.0.0",
"@skjnldsv/sanitize-svg": "^1.0.2",
@ -4123,20 +4123,20 @@
}
},
"node_modules/@nextcloud/upload": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/@nextcloud/upload/-/upload-1.5.0.tgz",
"integrity": "sha512-xVnmN1DwoGNIGIKrqxqPaqloOZ7pmVpUhFzCPkJ+hhmulptHQ2AiiIR8qYOMjc/O4BYq+p8nPspy9OgLGJ4KsA==",
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/@nextcloud/upload/-/upload-1.6.0.tgz",
"integrity": "sha512-8u3shCNGChzJpE3VwfoA0q0B5KoLgB9QEWnFU0ZkWYPy4KrxMKHLcdncQBt3VpBJwMg8Q1YqxUHKHZ3HX6e6Hw==",
"dependencies": {
"@nextcloud/auth": "^2.4.0",
"@nextcloud/axios": "^2.5.0",
"@nextcloud/dialogs": "^5.2.0",
"@nextcloud/dialogs": "^5.3.7",
"@nextcloud/files": "^3.8.0",
"@nextcloud/l10n": "^3.1.0",
"@nextcloud/logger": "^3.0.2",
"@nextcloud/paths": "^2.2.1",
"@nextcloud/router": "^3.0.0",
"@nextcloud/sharing": "^0.2.3",
"axios": "^1.7.4",
"axios": "^1.7.7",
"axios-retry": "^4.5.0",
"crypto-browserify": "^3.12.0",
"p-cancelable": "^4.0.1",
@ -7777,10 +7777,9 @@
}
},
"node_modules/axios": {
"version": "1.7.4",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.7.4.tgz",
"integrity": "sha512-DukmaFRnY6AzAALSH4J2M3k6PkaC+MfaAGdEERRWcC9q3/TWQwLpHR8ZRLKTdQ3aBDL64EdluRDjJqKw+BPZEw==",
"license": "MIT",
"version": "1.7.7",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz",
"integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==",
"dependencies": {
"follow-redirects": "^1.15.6",
"form-data": "^4.0.0",

@ -60,7 +60,7 @@
"@nextcloud/paths": "^2.2.1",
"@nextcloud/router": "^3.0.0",
"@nextcloud/sharing": "^0.2.3",
"@nextcloud/upload": "^1.5.0",
"@nextcloud/upload": "^1.6.0",
"@nextcloud/vue": "^8.17.1",
"@simplewebauthn/browser": "^10.0.0",
"@skjnldsv/sanitize-svg": "^1.0.2",