aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorskjnldsv <skjnldsv@protonmail.com>2024-07-09 11:00:08 +0200
committerJohn Molakvoæ <skjnldsv@users.noreply.github.com>2024-07-12 20:14:30 +0200
commit208ff8013dc750326cab7fcf11d09ceef2a60f51 (patch)
treebf260ae0d1c26291e5b89c8a47f5cb57d3c5be29
parent06462804f7f8b2c046aa3875d8780fb4e4f4d9fc (diff)
downloadnextcloud-server-208ff8013dc750326cab7fcf11d09ceef2a60f51.tar.gz
nextcloud-server-208ff8013dc750326cab7fcf11d09ceef2a60f51.zip
chore(files_sharing): refactor sharing config
Signed-off-by: skjnldsv <skjnldsv@protonmail.com>
-rw-r--r--apps/files_sharing/src/components/NewFileRequestDialog.vue134
-rw-r--r--apps/files_sharing/src/components/NewFileRequestDialog/FileRequestDatePassword.vue31
-rw-r--r--apps/files_sharing/src/components/NewFileRequestDialog/FileRequestFinish.vue8
-rw-r--r--apps/files_sharing/src/components/SharingEntryLink.vue16
-rw-r--r--apps/files_sharing/src/components/SharingEntryQuickShareSelect.vue2
-rw-r--r--apps/files_sharing/src/components/SharingInput.vue2
-rw-r--r--apps/files_sharing/src/mixins/ShareDetails.js2
-rw-r--r--apps/files_sharing/src/mixins/SharesMixin.js2
-rw-r--r--apps/files_sharing/src/models/Share.js23
-rw-r--r--apps/files_sharing/src/services/ConfigService.js322
-rw-r--r--apps/files_sharing/src/services/ConfigService.ts293
-rw-r--r--apps/files_sharing/src/utils/GeneratePassword.ts2
-rw-r--r--apps/files_sharing/src/views/SharingDetailsTab.vue2
-rw-r--r--apps/files_sharing/src/views/SharingTab.vue2
14 files changed, 463 insertions, 378 deletions
diff --git a/apps/files_sharing/src/components/NewFileRequestDialog.vue b/apps/files_sharing/src/components/NewFileRequestDialog.vue
index 50e3ff485c9..d6fec8f20e2 100644
--- a/apps/files_sharing/src/components/NewFileRequestDialog.vue
+++ b/apps/files_sharing/src/components/NewFileRequestDialog.vue
@@ -24,21 +24,23 @@
class="file-request-dialog__form"
aria-labelledby="file-request-dialog-description"
data-cy-file-request-dialog-form
- @submit.prevent.stop="onSubmit">
- <FileRequestIntro v-if="currentStep === STEP.FIRST"
+ @submit.prevent.stop="">
+ <FileRequestIntro v-show="currentStep === STEP.FIRST"
:context="context"
:destination.sync="destination"
:disabled="loading"
:label.sync="label"
:note.sync="note" />
- <FileRequestDatePassword v-else-if="currentStep === STEP.SECOND"
+ <FileRequestDatePassword v-show="currentStep === STEP.SECOND"
:deadline.sync="deadline"
:disabled="loading"
:password.sync="password" />
- <FileRequestFinish v-else-if="share"
+ <FileRequestFinish v-if="share"
+ v-show="currentStep === STEP.LAST"
:emails="emails"
+ :isShareByMailEnabled="isShareByMailEnabled"
:share="share"
@add-email="email => emails.push(email)"
@remove-email="onRemoveEmail" />
@@ -79,17 +81,19 @@
<NcLoadingIcon v-if="loading" />
<IconNext v-else :size="20" />
</template>
- {{ continueButtonLabel }}
+ {{ t('files_sharing', 'Continue') }}
</NcButton>
<!-- Finish -->
<NcButton v-else
- :aria-label="t('files_sharing', 'Close the creation dialog')"
+ :aria-label="finishButtonLabel"
+ :disabled="loading"
data-cy-file-request-dialog-controls="finish"
type="primary"
- @click="$emit('close')">
+ @click="onFinish">
<template #icon>
- <IconCheck :size="20" />
+ <NcLoadingIcon v-if="loading" />
+ <IconCheck v-else :size="20" />
</template>
{{ finishButtonLabel }}
</NcButton>
@@ -99,14 +103,15 @@
<script lang="ts">
import type { AxiosError } from 'axios'
-import type { Folder, Node } from '@nextcloud/files'
+import { Permission, type Folder, type Node } from '@nextcloud/files'
import type { OCSResponse } from '@nextcloud/typings/ocs'
import type { PropType } from 'vue'
import { defineComponent } from 'vue'
import { emit } from '@nextcloud/event-bus'
import { generateOcsUrl } from '@nextcloud/router'
-import { showError } from '@nextcloud/dialogs'
+import { getCapabilities } from '@nextcloud/capabilities'
+import { showError, showSuccess } from '@nextcloud/dialogs'
import { translate, translatePlural } from '@nextcloud/l10n'
import { Type } from '@nextcloud/sharing'
import axios from '@nextcloud/axios'
@@ -159,9 +164,12 @@ export default defineComponent({
setup() {
return {
+ STEP,
+
n: translatePlural,
t: translate,
- STEP,
+
+ isShareByMailEnabled: getCapabilities()?.files_sharing?.sharebymail?.enabled === true
}
},
@@ -183,13 +191,6 @@ export default defineComponent({
},
computed: {
- continueButtonLabel() {
- if (this.currentStep === STEP.LAST) {
- return this.t('files_sharing', 'Close')
- }
- return this.t('files_sharing', 'Continue')
- },
-
finishButtonLabel() {
if (this.emails.length === 0) {
return this.t('files_sharing', 'Close')
@@ -231,8 +232,17 @@ export default defineComponent({
this.$emit('close')
},
- onSubmit() {
- this.$emit('submit')
+ async onFinish() {
+ if (this.emails.length === 0 || this.isShareByMailEnabled === false) {
+ showSuccess(this.t('files_sharing', 'File request created'))
+ this.$emit('close')
+ return
+ }
+
+ await this.setShareEmails()
+ await this.sendEmails()
+ showSuccess(this.t('files_sharing', 'File request created and emails sent'))
+ this.$emit('close')
},
async createShare() {
@@ -244,7 +254,7 @@ export default defineComponent({
try {
const request = await axios.post(shareUrl, {
shareType: Type.SHARE_TYPE_EMAIL,
- publicUpload: 'true',
+ permissions: Permission.CREATE,
label: this.label,
path: this.destination,
@@ -253,13 +263,13 @@ export default defineComponent({
password: this.password || undefined,
expireDate,
- // Empty string to fallback to the attributes
- sharedWith: '',
- attributes: JSON.stringify({
- value: this.emails,
- key: 'emails',
- scope: 'sharedWith',
- })
+ // Empty string
+ shareWith: '',
+ attributes: JSON.stringify([{
+ value: true,
+ key: 'enabled',
+ scope: 'fileRequest',
+ }])
})
// If not an ocs request
@@ -288,6 +298,74 @@ export default defineComponent({
this.loading = false
}
},
+
+ async setShareEmails() {
+ this.loading = true
+
+ // This should never happen™
+ if (!this.share || !this.share?.id) {
+ throw new Error('Share ID is missing')
+ }
+
+ const shareUrl = generateOcsUrl('apps/files_sharing/api/v1/shares/' + this.share.id)
+ try {
+ // Convert link share to email share
+ const request = await axios.put(shareUrl, {
+ attributes: JSON.stringify([{
+ value: this.emails,
+ key: 'emails',
+ scope: 'shareWith',
+ }])
+ })
+
+ // If not an ocs request
+ if (!request?.data?.ocs) {
+ throw request
+ }
+ } catch (error) {
+ this.onEmailSendError(error)
+ throw error
+ } finally {
+ this.loading = false
+ }
+ },
+
+ async sendEmails () {
+ this.loading = true
+
+ // This should never happen™
+ if (!this.share || !this.share?.id) {
+ throw new Error('Share ID is missing')
+ }
+
+ const shareUrl = generateOcsUrl('apps/files_sharing/api/v1/shares/' + this.share.id + '/send-email')
+ try {
+ // Convert link share to email share
+ const request = await axios.post(shareUrl, {
+ password: this.password || undefined,
+ })
+
+ // If not an ocs request
+ if (!request?.data?.ocs) {
+ throw request
+ }
+ } catch (error) {
+ this.onEmailSendError(error)
+ throw error
+ } finally {
+ this.loading = false
+ }
+ },
+
+ onEmailSendError(error: AxiosError<OCSResponse>|any) {
+ const errorMessage = error.response?.data?.ocs?.meta?.message
+ showError(
+ errorMessage
+ ? this.t('files_sharing', 'Error sending emails: {errorMessage}', { errorMessage })
+ : this.t('files_sharing', 'Error sending emails'),
+ )
+ logger.error('Error while sending emails', { error, errorMessage })
+ },
},
})
</script>
diff --git a/apps/files_sharing/src/components/NewFileRequestDialog/FileRequestDatePassword.vue b/apps/files_sharing/src/components/NewFileRequestDialog/FileRequestDatePassword.vue
index 6da342da0f1..cf7cf4bcb08 100644
--- a/apps/files_sharing/src/components/NewFileRequestDialog/FileRequestDatePassword.vue
+++ b/apps/files_sharing/src/components/NewFileRequestDialog/FileRequestDatePassword.vue
@@ -68,7 +68,7 @@
<NcButton :aria-label="t('files_sharing', 'Generate a new password')"
:title="t('files_sharing', 'Generate a new password')"
type="tertiary-no-background"
- @click="generatePassword(); showPassword()">
+ @click="onGeneratePassword">
<template #icon>
<IconPasswordGen :size="20" />
</template>
@@ -90,8 +90,11 @@ import NcPasswordField from '@nextcloud/vue/dist/Components/NcPasswordField.js'
import IconPasswordGen from 'vue-material-design-icons/AutoFix.vue'
+import Config from '../../services/ConfigService'
import GeneratePassword from '../../utils/GeneratePassword'
+const sharingConfig = new Config()
+
export default defineComponent({
name: 'FileRequestDatePassword',
@@ -132,16 +135,16 @@ export default defineComponent({
t: translate,
// Default expiration date if defaultExpireDateEnabled is true
- defaultExpireDate: window.OC.appConfig.core.defaultExpireDate as number,
+ defaultExpireDate: sharingConfig.defaultExpireDate,
// Default expiration date is enabled for public links (can be disabled)
- defaultExpireDateEnabled: window.OC.appConfig.core.defaultExpireDateEnabled === true,
+ defaultExpireDateEnabled: sharingConfig.isDefaultExpireDateEnabled,
// Default expiration date is enforced for public links (can't be disabled)
- defaultExpireDateEnforced: window.OC.appConfig.core.defaultExpireDateEnforced === true,
+ defaultExpireDateEnforced: sharingConfig.isDefaultExpireDateEnforced,
// Default password protection is enabled for public links (can be disabled)
- enableLinkPasswordByDefault: window.OC.appConfig.core.enableLinkPasswordByDefault === true,
+ enableLinkPasswordByDefault: sharingConfig.enableLinkPasswordByDefault,
// Password protection is enforced for public links (can't be disabled)
- enforcePasswordForPublicLink: window.OC.appConfig.core.enforcePasswordForPublicLink === true,
+ enforcePasswordForPublicLink: sharingConfig.enforcePasswordForPublicLink,
}
},
@@ -176,13 +179,13 @@ export default defineComponent({
mounted() {
// If defined, we set the default expiration date
- if (this.defaultExpireDate > 0) {
- this.$emit('update:deadline', new Date(new Date().setDate(new Date().getDate() + this.defaultExpireDate)))
+ if (this.defaultExpireDate) {
+ this.$emit('update:deadline', sharingConfig.defaultExpirationDate)
}
// If enforced, we cannot set a date before the default expiration days (see admin settings)
if (this.defaultExpireDateEnforced) {
- this.maxDate = new Date(new Date().setDate(new Date().getDate() + this.defaultExpireDate))
+ this.maxDate = sharingConfig.defaultExpirationDate
}
// If enabled by default, we generate a valid password
@@ -204,8 +207,14 @@ export default defineComponent({
this.$emit('update:password', null)
},
- generatePassword() {
- GeneratePassword().then(password => {
+
+ async onGeneratePassword() {
+ await this.generatePassword()
+ this.showPassword()
+ },
+
+ async generatePassword() {
+ await GeneratePassword().then(password => {
this.$emit('update:password', password)
})
},
diff --git a/apps/files_sharing/src/components/NewFileRequestDialog/FileRequestFinish.vue b/apps/files_sharing/src/components/NewFileRequestDialog/FileRequestFinish.vue
index 1162414e049..0c30a8bf261 100644
--- a/apps/files_sharing/src/components/NewFileRequestDialog/FileRequestFinish.vue
+++ b/apps/files_sharing/src/components/NewFileRequestDialog/FileRequestFinish.vue
@@ -7,7 +7,7 @@
<div>
<!-- Request note -->
<NcNoteCard type="success">
- {{ t('files_sharing', 'You can now share the link below to allow others to upload files to your directory.') }}
+ {{ t('files_sharing', 'Once created, you can share the link below to allow people to upload files to your directory.') }}
</NcNoteCard>
<!-- Copy share link -->
@@ -71,7 +71,6 @@ import NcChip from '@nextcloud/vue/dist/Components/NcChip.js'
import IconCheck from 'vue-material-design-icons/Check.vue'
import IconClipboard from 'vue-material-design-icons/Clipboard.vue'
-import { getCapabilities } from '@nextcloud/capabilities'
export default defineComponent({
name: 'FileRequestFinish',
@@ -95,6 +94,10 @@ export default defineComponent({
type: Array as PropType<string[]>,
required: true,
},
+ isShareByMailEnabled: {
+ type: Boolean,
+ required: true,
+ },
},
emits: ['add-email', 'remove-email'],
@@ -103,7 +106,6 @@ export default defineComponent({
return {
n: translatePlural,
t: translate,
- isShareByMailEnabled: getCapabilities()?.files_sharing?.sharebymail?.enabled === true,
}
},
diff --git a/apps/files_sharing/src/components/SharingEntryLink.vue b/apps/files_sharing/src/components/SharingEntryLink.vue
index 210029f617b..e9b7ee44815 100644
--- a/apps/files_sharing/src/components/SharingEntryLink.vue
+++ b/apps/files_sharing/src/components/SharingEntryLink.vue
@@ -327,6 +327,11 @@ export default {
}
if (this.share.label && this.share.label.trim() !== '') {
if (this.isEmailShareType) {
+ if (this.isFileRequest) {
+ return t('files_sharing', 'File request ({label})', {
+ label: this.share.label.trim(),
+ })
+ }
return t('files_sharing', 'Mail share ({label})', {
label: this.share.label.trim(),
})
@@ -336,6 +341,11 @@ export default {
})
}
if (this.isEmailShareType) {
+ if (!this.share.shareWith || this.share.shareWith.trim() === '') {
+ return this.isFileRequest
+ ? t('files_sharing', 'File request')
+ : t('files_sharing', 'Mail share')
+ }
return this.share.shareWith
}
}
@@ -554,9 +564,13 @@ export default {
},
canChangeHideDownload() {
- const hasDisabledDownload = (shareAttribute) => shareAttribute.key === 'download' && shareAttribute.scope === 'permissions' && shareAttribute.value === false
+ const hasDisabledDownload = (shareAttribute) => shareAttribute.scope === 'permissions' && shareAttribute.key === 'download'&& shareAttribute.value === false
return this.fileInfo.shareAttributes.some(hasDisabledDownload)
},
+
+ isFileRequest() {
+ return this.share.isFileRequest
+ },
},
methods: {
diff --git a/apps/files_sharing/src/components/SharingEntryQuickShareSelect.vue b/apps/files_sharing/src/components/SharingEntryQuickShareSelect.vue
index 0746e9ce61f..f0c2c4f3812 100644
--- a/apps/files_sharing/src/components/SharingEntryQuickShareSelect.vue
+++ b/apps/files_sharing/src/components/SharingEntryQuickShareSelect.vue
@@ -80,7 +80,7 @@ export default {
return t('files_sharing', 'Can edit')
},
fileDropText() {
- return t('files_sharing', 'File requests')
+ return t('files_sharing', 'File request')
},
customPermissionsText() {
return t('files_sharing', 'Custom permissions')
diff --git a/apps/files_sharing/src/components/SharingInput.vue b/apps/files_sharing/src/components/SharingInput.vue
index e986ff4491f..d9054bc7fc6 100644
--- a/apps/files_sharing/src/components/SharingInput.vue
+++ b/apps/files_sharing/src/components/SharingInput.vue
@@ -34,7 +34,7 @@ import axios from '@nextcloud/axios'
import debounce from 'debounce'
import NcSelect from '@nextcloud/vue/dist/Components/NcSelect.js'
-import Config from '../services/ConfigService.js'
+import Config from '../services/ConfigService.ts'
import GeneratePassword from '../utils/GeneratePassword.ts'
import Share from '../models/Share.js'
import ShareRequests from '../mixins/ShareRequests.js'
diff --git a/apps/files_sharing/src/mixins/ShareDetails.js b/apps/files_sharing/src/mixins/ShareDetails.js
index 6c936b393ea..62b7aea182f 100644
--- a/apps/files_sharing/src/mixins/ShareDetails.js
+++ b/apps/files_sharing/src/mixins/ShareDetails.js
@@ -4,7 +4,7 @@
*/
import Share from '../models/Share.js'
-import Config from '../services/ConfigService.js'
+import Config from '../services/ConfigService.ts'
export default {
methods: {
diff --git a/apps/files_sharing/src/mixins/SharesMixin.js b/apps/files_sharing/src/mixins/SharesMixin.js
index 0d570b16918..ccac8300840 100644
--- a/apps/files_sharing/src/mixins/SharesMixin.js
+++ b/apps/files_sharing/src/mixins/SharesMixin.js
@@ -14,7 +14,7 @@ import debounce from 'debounce'
import Share from '../models/Share.js'
import SharesRequests from './ShareRequests.js'
import ShareTypes from './ShareTypes.js'
-import Config from '../services/ConfigService.js'
+import Config from '../services/ConfigService.ts'
import logger from '../services/logger.ts'
import {
diff --git a/apps/files_sharing/src/models/Share.js b/apps/files_sharing/src/models/Share.js
index 479d55ca241..dc0f8da082e 100644
--- a/apps/files_sharing/src/models/Share.js
+++ b/apps/files_sharing/src/models/Share.js
@@ -532,16 +532,27 @@ export default class Share {
* @memberof Share
*/
get hasDownloadPermission() {
- for (const i in this._share.attributes) {
- const attr = this._share.attributes[i]
- if (attr.scope === 'permissions' && attr.key === 'download') {
- return attr.value
- }
+ const hasDisabledDownload = (attribute) => {
+ return attribute.scope === 'permissions' && attribute.key === 'download' && attribute.value === false
}
+ return this.attributes.some(hasDisabledDownload)
+ }
- return true
+ /**
+ * Is this mail share a file request ?
+ *
+ * @return {boolean}
+ * @readonly
+ * @memberof Share
+ */
+ get isFileRequest() {
+ const isFileRequest = (attribute) => {
+ return attribute.scope === 'fileRequest' && attribute.key === 'enabled' && attribute.value === true
+ }
+ return this.attributes.some(isFileRequest)
}
+
set hasDownloadPermission(enabled) {
this.setAttribute('permissions', 'download', !!enabled)
}
diff --git a/apps/files_sharing/src/services/ConfigService.js b/apps/files_sharing/src/services/ConfigService.js
deleted file mode 100644
index 3d9e949724e..00000000000
--- a/apps/files_sharing/src/services/ConfigService.js
+++ /dev/null
@@ -1,322 +0,0 @@
-/**
- * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
- * SPDX-License-Identifier: AGPL-3.0-or-later
- */
-import { getCapabilities } from '@nextcloud/capabilities'
-
-export default class Config {
-
- constructor() {
- this._capabilities = getCapabilities()
- }
-
- /**
- * Get default share permissions, if any
- *
- * @return {boolean}
- * @readonly
- * @memberof Config
- */
- get defaultPermissions() {
- return this._capabilities.files_sharing?.default_permissions
- }
-
- /**
- * Is public upload allowed on link shares ?
- *
- * @return {boolean}
- * @readonly
- * @memberof Config
- */
- get isPublicUploadEnabled() {
- return this._capabilities.files_sharing?.public.upload
- }
-
- /**
- * Are link share allowed ?
- *
- * @return {boolean}
- * @readonly
- * @memberof Config
- */
- get isShareWithLinkAllowed() {
- return document.getElementById('allowShareWithLink')
- && document.getElementById('allowShareWithLink').value === 'yes'
- }
-
- /**
- * Get the federated sharing documentation link
- *
- * @return {string}
- * @readonly
- * @memberof Config
- */
- get federatedShareDocLink() {
- return OC.appConfig.core.federatedCloudShareDoc
- }
-
- /**
- * Get the default link share expiration date
- *
- * @return {Date|null}
- * @readonly
- * @memberof Config
- */
- get defaultExpirationDate() {
- if (this.isDefaultExpireDateEnabled) {
- return new Date(new Date().setDate(new Date().getDate() + this.defaultExpireDate))
- }
- return null
- }
-
- /**
- * Get the default internal expiration date
- *
- * @return {Date|null}
- * @readonly
- * @memberof Config
- */
- get defaultInternalExpirationDate() {
- if (this.isDefaultInternalExpireDateEnabled) {
- return new Date(new Date().setDate(new Date().getDate() + this.defaultInternalExpireDate))
- }
- return null
- }
-
- /**
- * Get the default remote expiration date
- *
- * @return {Date|null}
- * @readonly
- * @memberof Config
- */
- get defaultRemoteExpirationDateString() {
- if (this.isDefaultRemoteExpireDateEnabled) {
- return new Date(new Date().setDate(new Date().getDate() + this.defaultRemoteExpireDate))
- }
- return null
- }
-
- /**
- * Are link shares password-enforced ?
- *
- * @return {boolean}
- * @readonly
- * @memberof Config
- */
- get enforcePasswordForPublicLink() {
- return OC.appConfig.core.enforcePasswordForPublicLink === true
- }
-
- /**
- * Is password asked by default on link shares ?
- *
- * @return {boolean}
- * @readonly
- * @memberof Config
- */
- get enableLinkPasswordByDefault() {
- return OC.appConfig.core.enableLinkPasswordByDefault === true
- }
-
- /**
- * Is link shares expiration enforced ?
- *
- * @return {boolean}
- * @readonly
- * @memberof Config
- */
- get isDefaultExpireDateEnforced() {
- return OC.appConfig.core.defaultExpireDateEnforced === true
- }
-
- /**
- * Is there a default expiration date for new link shares ?
- *
- * @return {boolean}
- * @readonly
- * @memberof Config
- */
- get isDefaultExpireDateEnabled() {
- return OC.appConfig.core.defaultExpireDateEnabled === true
- }
-
- /**
- * Is internal shares expiration enforced ?
- *
- * @return {boolean}
- * @readonly
- * @memberof Config
- */
- get isDefaultInternalExpireDateEnforced() {
- return OC.appConfig.core.defaultInternalExpireDateEnforced === true
- }
-
- /**
- * Is remote shares expiration enforced ?
- *
- * @return {boolean}
- * @readonly
- * @memberof Config
- */
- get isDefaultRemoteExpireDateEnforced() {
- return OC.appConfig.core.defaultRemoteExpireDateEnforced === true
- }
-
- /**
- * Is there a default expiration date for new internal shares ?
- *
- * @return {boolean}
- * @readonly
- * @memberof Config
- */
- get isDefaultInternalExpireDateEnabled() {
- return OC.appConfig.core.defaultInternalExpireDateEnabled === true
- }
-
- /**
- * Is there a default expiration date for new remote shares ?
- *
- * @return {boolean}
- * @readonly
- * @memberof Config
- */
- get isDefaultRemoteExpireDateEnabled() {
- return OC.appConfig.core.defaultRemoteExpireDateEnabled === true
- }
-
- /**
- * Are users on this server allowed to send shares to other servers ?
- *
- * @return {boolean}
- * @readonly
- * @memberof Config
- */
- get isRemoteShareAllowed() {
- return OC.appConfig.core.remoteShareAllowed === true
- }
-
- /**
- * Is sharing my mail (link share) enabled ?
- *
- * @return {boolean}
- * @readonly
- * @memberof Config
- */
- get isMailShareAllowed() {
- // eslint-disable-next-line camelcase
- return this._capabilities?.files_sharing?.sharebymail !== undefined
- // eslint-disable-next-line camelcase
- && this._capabilities?.files_sharing?.public?.enabled === true
- }
-
- /**
- * Get the default days to link shares expiration
- *
- * @return {number}
- * @readonly
- * @memberof Config
- */
- get defaultExpireDate() {
- return OC.appConfig.core.defaultExpireDate
- }
-
- /**
- * Get the default days to internal shares expiration
- *
- * @return {number}
- * @readonly
- * @memberof Config
- */
- get defaultInternalExpireDate() {
- return OC.appConfig.core.defaultInternalExpireDate
- }
-
- /**
- * Get the default days to remote shares expiration
- *
- * @return {number}
- * @readonly
- * @memberof Config
- */
- get defaultRemoteExpireDate() {
- return OC.appConfig.core.defaultRemoteExpireDate
- }
-
- /**
- * Is resharing allowed ?
- *
- * @return {boolean}
- * @readonly
- * @memberof Config
- */
- get isResharingAllowed() {
- return OC.appConfig.core.resharingAllowed === true
- }
-
- /**
- * Is password enforced for mail shares ?
- *
- * @return {boolean}
- * @readonly
- * @memberof Config
- */
- get isPasswordForMailSharesRequired() {
- return (this._capabilities.files_sharing.sharebymail === undefined) ? false : this._capabilities.files_sharing.sharebymail.password.enforced
- }
-
- /**
- * @return {boolean}
- * @readonly
- * @memberof Config
- */
- get shouldAlwaysShowUnique() {
- return (this._capabilities.files_sharing?.sharee?.always_show_unique === true)
- }
-
- /**
- * Is sharing with groups allowed ?
- *
- * @return {boolean}
- * @readonly
- * @memberof Config
- */
- get allowGroupSharing() {
- return OC.appConfig.core.allowGroupSharing === true
- }
-
- /**
- * Get the maximum results of a share search
- *
- * @return {number}
- * @readonly
- * @memberof Config
- */
- get maxAutocompleteResults() {
- return parseInt(OC.config['sharing.maxAutocompleteResults'], 10) || 25
- }
-
- /**
- * Get the minimal string length
- * to initiate a share search
- *
- * @return {number}
- * @readonly
- * @memberof Config
- */
- get minSearchStringLength() {
- return parseInt(OC.config['sharing.minSearchStringLength'], 10) || 0
- }
-
- /**
- * Get the password policy config
- *
- * @return {object}
- * @readonly
- * @memberof Config
- */
- get passwordPolicy() {
- return this._capabilities.password_policy ? this._capabilities.password_policy : {}
- }
-
-}
diff --git a/apps/files_sharing/src/services/ConfigService.ts b/apps/files_sharing/src/services/ConfigService.ts
new file mode 100644
index 00000000000..916de5959c2
--- /dev/null
+++ b/apps/files_sharing/src/services/ConfigService.ts
@@ -0,0 +1,293 @@
+/**
+ * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+import { getCapabilities } from '@nextcloud/capabilities'
+
+export default class Config {
+ _capabilities: Capabilities
+
+ constructor() {
+ this._capabilities = getCapabilities() as Capabilities
+ }
+
+ /**
+ * Get default share permissions, if any
+ */
+ get defaultPermissions(): number {
+ return this._capabilities.files_sharing?.default_permissions
+ }
+
+ /**
+ * Is public upload allowed on link shares ?
+ * This covers File request and Full upload/edit option.
+ */
+ get isPublicUploadEnabled(): boolean {
+ return this._capabilities.files_sharing?.public?.upload === true
+ }
+
+ /**
+ * Get the federated sharing documentation link
+ */
+ get federatedShareDocLink() {
+ return window.OC.appConfig.core.federatedCloudShareDoc
+ }
+
+ /**
+ * Get the default link share expiration date
+ */
+ get defaultExpirationDate(): Date|null {
+ if (this.isDefaultExpireDateEnabled && this.defaultExpireDate !== null) {
+ return new Date(new Date().setDate(new Date().getDate() + this.defaultExpireDate))
+ }
+ return null
+ }
+
+ /**
+ * Get the default internal expiration date
+ */
+ get defaultInternalExpirationDate(): Date|null {
+ if (this.isDefaultInternalExpireDateEnabled && this.defaultInternalExpireDate !== null) {
+ return new Date(new Date().setDate(new Date().getDate() + this.defaultInternalExpireDate))
+ }
+ return null
+ }
+
+ /**
+ * Get the default remote expiration date
+ */
+ get defaultRemoteExpirationDateString(): Date|null {
+ if (this.isDefaultRemoteExpireDateEnabled && this.defaultRemoteExpireDate !== null) {
+ return new Date(new Date().setDate(new Date().getDate() + this.defaultRemoteExpireDate))
+ }
+ return null
+ }
+
+ /**
+ * Are link shares password-enforced ?
+ */
+ get enforcePasswordForPublicLink(): boolean {
+ return window.OC.appConfig.core.enforcePasswordForPublicLink === true
+ }
+
+ /**
+ * Is password asked by default on link shares ?
+ */
+ get enableLinkPasswordByDefault(): boolean {
+ return window.OC.appConfig.core.enableLinkPasswordByDefault === true
+ }
+
+ /**
+ * Is link shares expiration enforced ?
+ */
+ get isDefaultExpireDateEnforced(): boolean {
+ return window.OC.appConfig.core.defaultExpireDateEnforced === true
+ }
+
+ /**
+ * Is there a default expiration date for new link shares ?
+ */
+ get isDefaultExpireDateEnabled(): boolean {
+ return window.OC.appConfig.core.defaultExpireDateEnabled === true
+ }
+
+ /**
+ * Is internal shares expiration enforced ?
+ */
+ get isDefaultInternalExpireDateEnforced(): boolean {
+ return window.OC.appConfig.core.defaultInternalExpireDateEnforced === true
+ }
+
+ /**
+ * Is there a default expiration date for new internal shares ?
+ */
+ get isDefaultInternalExpireDateEnabled(): boolean {
+ return window.OC.appConfig.core.defaultInternalExpireDateEnabled === true
+ }
+
+ /**
+ * Is remote shares expiration enforced ?
+ */
+ get isDefaultRemoteExpireDateEnforced(): boolean {
+ return window.OC.appConfig.core.defaultRemoteExpireDateEnforced === true
+ }
+
+ /**
+ * Is there a default expiration date for new remote shares ?
+ */
+ get isDefaultRemoteExpireDateEnabled(): boolean {
+ return window.OC.appConfig.core.defaultRemoteExpireDateEnabled === true
+ }
+
+ /**
+ * Are users on this server allowed to send shares to other servers ?
+ */
+ get isRemoteShareAllowed(): boolean {
+ return window.OC.appConfig.core.remoteShareAllowed === true
+ }
+
+ /**
+ * Is sharing my mail (link share) enabled ?
+ */
+ get isMailShareAllowed(): boolean {
+ // eslint-disable-next-line camelcase
+ return this._capabilities?.files_sharing?.sharebymail?.enabled === true
+ // eslint-disable-next-line camelcase
+ && this._capabilities?.files_sharing?.public?.enabled === true
+ }
+
+ /**
+ * Get the default days to link shares expiration
+ */
+ get defaultExpireDate(): number|null {
+ return window.OC.appConfig.core.defaultExpireDate
+ }
+
+ /**
+ * Get the default days to internal shares expiration
+ */
+ get defaultInternalExpireDate(): number|null {
+ return window.OC.appConfig.core.defaultInternalExpireDate
+ }
+
+ /**
+ * Get the default days to remote shares expiration
+ */
+ get defaultRemoteExpireDate(): number|null {
+ return window.OC.appConfig.core.defaultRemoteExpireDate
+ }
+
+ /**
+ * Is resharing allowed ?
+ */
+ get isResharingAllowed(): boolean {
+ return window.OC.appConfig.core.resharingAllowed === true
+ }
+
+ /**
+ * Is password enforced for mail shares ?
+ */
+ get isPasswordForMailSharesRequired(): boolean {
+ return this._capabilities.files_sharing?.sharebymail?.password?.enforced === true
+ }
+
+ /**
+ * Always show the email or userid unique sharee label if enabled by the admin
+ */
+ get shouldAlwaysShowUnique(): boolean {
+ return this._capabilities.files_sharing?.sharee?.always_show_unique === true
+ }
+
+ /**
+ * Is sharing with groups allowed ?
+ */
+ get allowGroupSharing(): boolean {
+ return window.OC.appConfig.core.allowGroupSharing === true
+ }
+
+ /**
+ * Get the maximum results of a share search
+ */
+ get maxAutocompleteResults(): number {
+ return parseInt(window.OC.config['sharing.maxAutocompleteResults'], 10) || 25
+ }
+
+ /**
+ * Get the minimal string length
+ * to initiate a share search
+ */
+ get minSearchStringLength(): number {
+ return parseInt(window.OC.config['sharing.minSearchStringLength'], 10) || 0
+ }
+
+ /**
+ * Get the password policy configuration
+ */
+ get passwordPolicy(): PasswordPolicyCapabilities {
+ return this._capabilities?.password_policy || {}
+ }
+
+}
+
+type PasswordPolicyCapabilities = {
+ enforceNonCommonPassword: boolean
+ enforceNumericCharacters: boolean
+ enforceSpecialCharacters: boolean
+ enforceUpperLowerCase: boolean
+ minLength: number
+}
+
+type FileSharingCapabilities = {
+ api_enabled: boolean,
+ public: {
+ enabled: boolean,
+ password: {
+ enforced: boolean,
+ askForOptionalPassword: boolean
+ },
+ expire_date: {
+ enabled: boolean,
+ days: number,
+ enforced: boolean
+ },
+ multiple_links: boolean,
+ expire_date_internal: {
+ enabled: boolean
+ },
+ expire_date_remote: {
+ enabled: boolean
+ },
+ send_mail: boolean,
+ upload: boolean,
+ upload_files_drop: boolean
+ },
+ resharing: boolean,
+ user: {
+ send_mail: boolean,
+ expire_date: {
+ enabled: boolean
+ }
+ },
+ group_sharing: boolean,
+ group: {
+ enabled: boolean,
+ expire_date: {
+ enabled: true
+ }
+ },
+ default_permissions: number,
+ federation: {
+ outgoing: boolean,
+ incoming: boolean,
+ expire_date: {
+ enabled: boolean
+ },
+ expire_date_supported: {
+ enabled: boolean
+ }
+ },
+ sharee: {
+ query_lookup_default: boolean,
+ always_show_unique: boolean
+ },
+ sharebymail: {
+ enabled: boolean,
+ send_password_by_mail: boolean,
+ upload_files_drop: {
+ enabled: boolean
+ },
+ password: {
+ enabled: boolean,
+ enforced: boolean
+ },
+ expire_date: {
+ enabled: boolean,
+ enforced: boolean
+ }
+ }
+}
+
+type Capabilities = {
+ files_sharing: FileSharingCapabilities
+ password_policy: PasswordPolicyCapabilities
+}
diff --git a/apps/files_sharing/src/utils/GeneratePassword.ts b/apps/files_sharing/src/utils/GeneratePassword.ts
index c7839fe6302..bbfa5e7b27d 100644
--- a/apps/files_sharing/src/utils/GeneratePassword.ts
+++ b/apps/files_sharing/src/utils/GeneratePassword.ts
@@ -4,7 +4,7 @@
*/
import axios from '@nextcloud/axios'
-import Config from '../services/ConfigService.js'
+import Config from '../services/ConfigService.ts'
import { showError, showSuccess } from '@nextcloud/dialogs'
import { translate as t } from '@nextcloud/l10n'
diff --git a/apps/files_sharing/src/views/SharingDetailsTab.vue b/apps/files_sharing/src/views/SharingDetailsTab.vue
index 610f9b99eac..023c137a254 100644
--- a/apps/files_sharing/src/views/SharingDetailsTab.vue
+++ b/apps/files_sharing/src/views/SharingDetailsTab.vue
@@ -62,7 +62,7 @@
type="radio"
button-variant-grouped="vertical"
@update:checked="toggleCustomPermissions">
- {{ t('files_sharing', 'File requests') }}
+ {{ t('files_sharing', 'File request') }}
<small class="subline">{{ t('files_sharing', 'Upload only') }}</small>
<template #icon>
<UploadIcon :size="20" />
diff --git a/apps/files_sharing/src/views/SharingTab.vue b/apps/files_sharing/src/views/SharingTab.vue
index 7e58cb6401e..98c40a0a933 100644
--- a/apps/files_sharing/src/views/SharingTab.vue
+++ b/apps/files_sharing/src/views/SharingTab.vue
@@ -88,7 +88,7 @@ import NcAvatar from '@nextcloud/vue/dist/Components/NcAvatar.js'
import axios from '@nextcloud/axios'
import { loadState } from '@nextcloud/initial-state'
-import Config from '../services/ConfigService.js'
+import Config from '../services/ConfigService.ts'
import { shareWithTitle } from '../utils/SharedWithMe.js'
import Share from '../models/Share.js'
import ShareTypes from '../mixins/ShareTypes.js'