chore(files_sharing): refactor sharing config

Signed-off-by: skjnldsv <skjnldsv@protonmail.com>
pull/46007/head
skjnldsv 2024-07-09 11:00:08 +07:00 committed by John Molakvoæ
parent 06462804f7
commit 208ff8013d
14 changed files with 463 additions and 378 deletions

@ -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>

@ -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)
})
},

@ -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,
}
},

@ -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: {

@ -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')

@ -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'

@ -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: {

@ -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 {

@ -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)
}

@ -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 : {}
}
}

@ -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
}

@ -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'

@ -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" />

@ -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'