Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ const open = defineModel<boolean>('open', { default: true })
const {
storage = { backendOptions: {}, mountOptions: {}, type: isAdmin ? 'system' : 'personal' },
} = defineProps<{
storage?: Partial<IStorage> & { backendOptions: IStorage['backendOptions'] }
storage?: Partial<IStorage>
}>()

defineEmits<{
Expand Down Expand Up @@ -88,7 +88,7 @@ watch(authMechanisms, () => {
:label="t('files_external', 'Folder name')"
required />

<MountOptions v-model="internalStorage.mountOptions" />
<MountOptions v-model="internalStorage.mountOptions!" />

<ApplicableEntities
v-if="isAdmin"
Expand All @@ -112,13 +112,13 @@ watch(authMechanisms, () => {
required />

<BackendConfiguration
v-if="backend"
v-if="backend && internalStorage.backendOptions"
v-model="internalStorage.backendOptions"
:class="$style.externalStorageDialog__configuration"
:configuration="backend.configuration" />

<AuthMechanismConfiguration
v-if="authMechanism"
v-if="authMechanism && internalStorage.backendOptions"
v-model="internalStorage.backendOptions"
:class="$style.externalStorageDialog__configuration"
:authMechanism="authMechanism" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,14 @@ import NcButton from '@nextcloud/vue/components/NcButton'
import NcCheckboxRadioSwitch from '@nextcloud/vue/components/NcCheckboxRadioSwitch'
import NcIconSvgWrapper from '@nextcloud/vue/components/NcIconSvgWrapper'
import NcSelect from '@nextcloud/vue/components/NcSelect'
import { parseMountOptions } from '../../store/storages.ts'
import { MountOptionsCheckFilesystem } from '../../types.ts'

const mountOptions = defineModel<Partial<IMountOptions>>({ required: true })
watchEffect(() => {
if (Object.keys(mountOptions.value).length === 0) {
mountOptions.value.encrypt = true
mountOptions.value.previews = true
mountOptions.value.enable_sharing = false
mountOptions.value.filesystem_check_changes = MountOptionsCheckFilesystem.OncePerRequest
mountOptions.value.encoding_compatibility = false
mountOptions.value.readonly = false
// parse and initialize with defaults if needed
mountOptions.value = parseMountOptions(mountOptions.value)
}
})

Expand Down
54 changes: 49 additions & 5 deletions apps/files_external/src/store/storages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

import type { IStorage } from '../types.d.ts'
import type { IStorage } from '../types.ts'

import axios from '@nextcloud/axios'
import { loadState } from '@nextcloud/initial-state'
import { addPasswordConfirmationInterceptors, PwdConfirmationMode } from '@nextcloud/password-confirmation'
import { generateUrl } from '@nextcloud/router'
import { defineStore } from 'pinia'
import { ref, toRaw } from 'vue'
import { MountOptionsCheckFilesystem } from '../types.ts'

const { isAdmin } = loadState<{ isAdmin: boolean }>('files_external', 'settings')

Expand All @@ -30,7 +31,7 @@ export const useStorages = defineStore('files_external--storages', () => {
toRaw(storage),
{ confirmPassword: PwdConfirmationMode.Strict },
)
globalStorages.value.push(data)
globalStorages.value.push(parseStorage(data))
}

/**
Expand All @@ -45,7 +46,7 @@ export const useStorages = defineStore('files_external--storages', () => {
toRaw(storage),
{ confirmPassword: PwdConfirmationMode.Strict },
)
userStorages.value.push(data)
userStorages.value.push(parseStorage(data))
}

/**
Expand Down Expand Up @@ -77,7 +78,7 @@ export const useStorages = defineStore('files_external--storages', () => {
{ confirmPassword: PwdConfirmationMode.Strict },
)

overrideStorage(data)
overrideStorage(parseStorage(data))
}

/**
Expand All @@ -87,7 +88,7 @@ export const useStorages = defineStore('files_external--storages', () => {
*/
async function reloadStorage(storage: IStorage) {
const { data } = await axios.get(getUrl(storage))
overrideStorage(data)
overrideStorage(parseStorage(data))
}

// initialize the store
Expand All @@ -111,6 +112,7 @@ export const useStorages = defineStore('files_external--storages', () => {
const url = `apps/files_external/${type}`
const { data } = await axios.get<Record<number, IStorage>>(generateUrl(url))
return Object.values(data)
.map(parseStorage)
}

/**
Expand Down Expand Up @@ -150,3 +152,45 @@ export const useStorages = defineStore('files_external--storages', () => {
}
}
})

/**
* @param storage - The storage from API
*/
function parseStorage(storage: IStorage) {
return {
...storage,
mountOptions: parseMountOptions(storage.mountOptions),
}
}

/**
* Parse the mount options and convert string boolean values to
* actual booleans and numeric strings to numbers
*
* @param options - The mount options to parse
*/
export function parseMountOptions(options: IStorage['mountOptions']) {
const mountOptions = { ...options }
mountOptions.encrypt = convertBooleanOptions(mountOptions.encrypt, true)
mountOptions.previews = convertBooleanOptions(mountOptions.previews, true)
mountOptions.enable_sharing = convertBooleanOptions(mountOptions.enable_sharing, false)
mountOptions.filesystem_check_changes = typeof mountOptions.filesystem_check_changes === 'string'
? Number.parseInt(mountOptions.filesystem_check_changes)
: (mountOptions.filesystem_check_changes ?? MountOptionsCheckFilesystem.OncePerRequest)
mountOptions.encoding_compatibility = convertBooleanOptions(mountOptions.encoding_compatibility, false)
mountOptions.readonly = convertBooleanOptions(mountOptions.readonly, false)
return mountOptions
}

/**
* Convert backend encoding of boolean options
*
* @param option - The option value from API
* @param fallback - The fallback (default) value
*/
function convertBooleanOptions(option: unknown, fallback = false) {
if (option === undefined) {
return fallback
}
return option === true || option === 'true' || option === '1'
}
5 changes: 3 additions & 2 deletions apps/files_external/src/views/ExternalStoragesSection.vue
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,8 @@ async function addStorage(storage?: Partial<IStorage>) {
}
newStorage.value = undefined
} catch (error) {
logger.error('Failed to add external storage', { error })
logger.error('Failed to add external storage', { error, storage })
newStorage.value = { ...storage }
showDialog.value = true
}
}
Expand Down Expand Up @@ -134,8 +135,8 @@ async function addStorage(storage?: Partial<IStorage>) {
</NcButton>

<AddExternalStorageDialog
v-model="newStorage"
v-model:open="showDialog"
:storage="newStorage"
@close="addStorage" />

<UserMountSettings v-if="settings.isAdmin" />
Expand Down
Loading
Loading