mirror of
https://github.com/nextcloud/server.git
synced 2026-02-03 20:41:22 -05:00
1 line
No EOL
22 KiB
Text
1 line
No EOL
22 KiB
Text
{"version":3,"mappings":"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","names":["FolderNetworkSvg","LoginSvg","isMissingAuthConfig","config","StorageStatus","isNodeExternalStorage","node","FileType","attributes","addPasswordConfirmationInterceptors","axios","setCredentials","login","password","generateUrl","PwdConfirmationMode","showError","t","showSuccess","emit","ACTION_CREDENTIALS_EXTERNAL_STORAGE","action","FileAction","nodes","spawnDialog","defineAsyncComponent","error","DefaultType","AlertSvg","rootPath","getCurrentUser","entryToFolder","ocsEntry","path","Folder","generateRemoteUrl","Permission","getContents","contents","generateOcsUrl","getStatus","id","global","type","span","data","showWarning","isWarning","overlay","view","showConfirmation","scope","allowUserMounting","loadState","Navigation","getNavigation","View","Column","backend","registerFileAction","enterCredentialsAction","inlineStorageCheckAction","openInFilesAction"],"ignoreList":[0,1,5],"sources":["../node_modules/@mdi/svg/svg/folder-network-outline.svg?raw","../node_modules/@mdi/svg/svg/login.svg?raw","../build/frontend/apps/files_external/src/utils/credentialsUtils.ts","../build/frontend/apps/files_external/src/utils/externalStorageUtils.ts","../build/frontend/apps/files_external/src/actions/enterCredentialsAction.ts","../node_modules/@mdi/svg/svg/alert-circle.svg?raw","../build/frontend/apps/files_external/src/services/externalStorage.ts","../build/frontend/apps/files_external/src/actions/inlineStorageCheckAction.ts","../build/frontend/apps/files_external/src/actions/openInFilesAction.ts","../build/frontend/apps/files_external/src/init-files.ts"],"sourcesContent":["export default \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" id=\\\"mdi-folder-network-outline\\\" viewBox=\\\"0 0 24 24\\\"><path d=\\\"M15 20C15 19.45 14.55 19 14 19H13V17H19C20.11 17 21 16.11 21 15V7C21 5.9 20.11 5 19 5H13L11 3H5C3.9 3 3 3.9 3 5V15C3 16.11 3.9 17 5 17H11V19H10C9.45 19 9 19.45 9 20H2V22H9C9 22.55 9.45 23 10 23H14C14.55 23 15 22.55 15 22H22V20H15M5 15V7H19V15H5Z\\\" /></svg>\"","export default \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" id=\\\"mdi-login\\\" viewBox=\\\"0 0 24 24\\\"><path d=\\\"M11 7L9.6 8.4L12.2 11H2V13H12.2L9.6 15.6L11 17L16 12L11 7M20 19H12V21H20C21.1 21 22 20.1 22 19V5C22 3.9 21.1 3 20 3H12V5H20V19Z\\\" /></svg>\"","/*!\n * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors\n * SPDX-License-Identifier: AGPL-3.0-or-later\n */\n\nimport type { IStorage } from '../types.ts'\n\nimport { StorageStatus } from '../types.ts'\n\n/**\n * Check if the given storage configuration is missing authentication configuration\n *\n * @param config - The storage configuration to check\n */\nexport function isMissingAuthConfig(config: IStorage) {\n\t// If we don't know the status, assume it is ok\n\tif (config.status === undefined || config.status === StorageStatus.Success) {\n\t\treturn false\n\t}\n\n\treturn config.userProvided || config.authMechanism === 'password::global::user'\n}\n","/*!\n * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors\n * SPDX-License-Identifier: AGPL-3.0-or-later\n */\n\nimport type { INode } from '@nextcloud/files'\nimport type { MountEntry } from '../services/externalStorage.ts'\n\nimport { FileType } from '@nextcloud/files'\n\n/**\n * Check if the given node represents an external storage mount\n *\n * @param node - The node to check\n */\nexport function isNodeExternalStorage(node: INode) {\n\t// Not a folder, not a storage\n\tif (node.type === FileType.File) {\n\t\treturn false\n\t}\n\n\t// No backend or scope, not a storage\n\tconst attributes = node.attributes as MountEntry\n\tif (!attributes.scope || !attributes.backend) {\n\t\treturn false\n\t}\n\n\t// Specific markers that we're sure are ext storage only\n\treturn attributes.scope === 'personal' || attributes.scope === 'system'\n}\n","/*!\n * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors\n * SPDX-License-Identifier: AGPL-3.0-or-later\n */\n\nimport type { AxiosResponse } from '@nextcloud/axios'\nimport type { INode } from '@nextcloud/files'\nimport type { IStorage } from '../types.ts'\n\nimport LoginSvg from '@mdi/svg/svg/login.svg?raw'\nimport axios from '@nextcloud/axios'\nimport { showError, showSuccess } from '@nextcloud/dialogs'\nimport { emit } from '@nextcloud/event-bus'\nimport { DefaultType, FileAction } from '@nextcloud/files'\nimport { t } from '@nextcloud/l10n'\nimport { addPasswordConfirmationInterceptors, PwdConfirmationMode } from '@nextcloud/password-confirmation'\nimport { generateUrl } from '@nextcloud/router'\nimport { spawnDialog } from '@nextcloud/vue/functions/dialog'\nimport { defineAsyncComponent } from 'vue'\nimport { StorageStatus } from '../types.ts'\nimport { isMissingAuthConfig } from '../utils/credentialsUtils.ts'\nimport { isNodeExternalStorage } from '../utils/externalStorageUtils.ts'\n\n// Add password confirmation interceptors as\n// the backend requires the user to confirm their password\naddPasswordConfirmationInterceptors(axios)\n\n/**\n * Set credentials for external storage\n *\n * @param node The node for which to set the credentials\n * @param login The username\n * @param password The password\n */\nasync function setCredentials(node: INode, login: string, password: string): Promise<null | true> {\n\tconst configResponse = await axios.request({\n\t\tmethod: 'PUT',\n\t\turl: generateUrl('apps/files_external/userglobalstorages/{id}', { id: node.attributes.id }),\n\t\tconfirmPassword: PwdConfirmationMode.Strict,\n\t\tdata: {\n\t\t\tbackendOptions: { user: login, password },\n\t\t},\n\t}) as AxiosResponse<IStorage>\n\n\tconst config = configResponse.data\n\tif (config.status !== StorageStatus.Success) {\n\t\tshowError(t('files_external', 'Unable to update this external storage config. {statusMessage}', {\n\t\t\tstatusMessage: config?.statusMessage || '',\n\t\t}))\n\t\treturn null\n\t}\n\n\t// Success update config attribute\n\tshowSuccess(t('files_external', 'New configuration successfully saved'))\n\tnode.attributes.config = config\n\temit('files:node:updated', node)\n\n\treturn true\n}\n\nexport const ACTION_CREDENTIALS_EXTERNAL_STORAGE = 'credentials-external-storage'\n\nexport const action = new FileAction({\n\tid: ACTION_CREDENTIALS_EXTERNAL_STORAGE,\n\tdisplayName: () => t('files', 'Enter missing credentials'),\n\ticonSvgInline: () => LoginSvg,\n\n\tenabled: ({ nodes }) => {\n\t\t// Only works on single node\n\t\tif (nodes.length !== 1 || !nodes[0]) {\n\t\t\treturn false\n\t\t}\n\n\t\tconst node = nodes[0]\n\t\tif (!isNodeExternalStorage(node)) {\n\t\t\treturn false\n\t\t}\n\n\t\tconst config = (node.attributes?.config || {}) as IStorage\n\t\tif (isMissingAuthConfig(config)) {\n\t\t\treturn true\n\t\t}\n\n\t\treturn false\n\t},\n\n\tasync exec({ nodes }) {\n\t\tconst { login, password } = await spawnDialog(defineAsyncComponent(() => import('../views/CredentialsDialog.vue'))) ?? {}\n\t\tif (login && password) {\n\t\t\ttry {\n\t\t\t\tawait setCredentials(nodes[0]!, login, password)\n\t\t\t\tshowSuccess(t('files_external', 'Credentials successfully set'))\n\t\t\t} catch (error) {\n\t\t\t\tshowError(t('files_external', 'Error while setting credentials: {error}', {\n\t\t\t\t\terror: (error as Error).message,\n\t\t\t\t}))\n\t\t\t}\n\t\t}\n\n\t\treturn null\n\t},\n\n\t// Before openFolderAction\n\torder: -1000,\n\tdefault: DefaultType.DEFAULT,\n\tinline: () => true,\n})\n","export default \"<svg xmlns=\\\"http://www.w3.org/2000/svg\\\" id=\\\"mdi-alert-circle\\\" viewBox=\\\"0 0 24 24\\\"><path d=\\\"M13,13H11V7H13M13,17H11V15H13M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2Z\\\" /></svg>\"","/**\n * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors\n * SPDX-License-Identifier: AGPL-3.0-or-later\n */\n\nimport type { AxiosResponse } from '@nextcloud/axios'\nimport type { ContentsWithRoot } from '@nextcloud/files'\nimport type { OCSResponse } from '@nextcloud/typings/ocs'\nimport type { IStorage } from '../types.ts'\n\nimport { getCurrentUser } from '@nextcloud/auth'\nimport axios from '@nextcloud/axios'\nimport { Folder, Permission } from '@nextcloud/files'\nimport { generateOcsUrl, generateRemoteUrl, generateUrl } from '@nextcloud/router'\nimport { StorageStatus } from '../types.ts'\n\nexport const rootPath = `/files/${getCurrentUser()?.uid}`\n\n/**\n * https://github.com/nextcloud/server/blob/ac2bc2384efe3c15ff987b87a7432bc60d545c67/apps/files_external/lib/Controller/ApiController.php#L71-L97\n */\nexport type MountEntry = {\n\tname: string\n\tpath: string\n\ttype: 'dir'\n\tbackend: 'SFTP'\n\tscope: 'system' | 'personal'\n\tpermissions: number\n\tid: number\n\tclass: string\n\tconfig: IStorage\n}\n\n/**\n * Convert an OCS api result (mount entry) to a Folder instance\n *\n * @param ocsEntry - The OCS mount entry\n */\nfunction entryToFolder(ocsEntry: MountEntry): Folder {\n\tconst path = (ocsEntry.path + '/' + ocsEntry.name).replace(/^\\//gm, '')\n\treturn new Folder({\n\t\tid: ocsEntry.id,\n\t\tsource: generateRemoteUrl('dav' + rootPath + '/' + path),\n\t\troot: rootPath,\n\t\towner: getCurrentUser()?.uid || null,\n\t\tpermissions: ocsEntry.config.status !== StorageStatus.Success\n\t\t\t? Permission.NONE\n\t\t\t: ocsEntry?.permissions || Permission.READ,\n\t\tattributes: {\n\t\t\tdisplayName: path,\n\t\t\t...ocsEntry,\n\t\t},\n\t})\n}\n\n/**\n * Fetch the contents of external storage mounts\n */\nexport async function getContents(): Promise<ContentsWithRoot> {\n\tconst response = await axios.get(generateOcsUrl('apps/files_external/api/v1/mounts')) as AxiosResponse<OCSResponse<MountEntry[]>>\n\tconst contents = response.data.ocs.data.map(entryToFolder)\n\n\treturn {\n\t\tfolder: new Folder({\n\t\t\tid: 0,\n\t\t\tsource: generateRemoteUrl('dav' + rootPath),\n\t\t\troot: rootPath,\n\t\t\towner: getCurrentUser()?.uid || null,\n\t\t\tpermissions: Permission.READ,\n\t\t}),\n\t\tcontents,\n\t}\n}\n\n/**\n * Get the status of an external storage mount\n *\n * @param id - The storage ID\n * @param global - Whether the storage is global or user specific\n */\nexport function getStatus(id: number, global = true) {\n\tconst type = global ? 'userglobalstorages' : 'userstorages'\n\treturn axios.get(generateUrl(`apps/files_external/${type}/${id}?testOnly=false`)) as Promise<AxiosResponse<IStorage>>\n}\n","/*!\n * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors\n * SPDX-License-Identifier: AGPL-3.0-or-later\n */\n\nimport type { AxiosError } from '@nextcloud/axios'\nimport type { IStorage } from '../types.ts'\n\nimport AlertSvg from '@mdi/svg/svg/alert-circle.svg?raw'\nimport { showWarning } from '@nextcloud/dialogs'\nimport { emit } from '@nextcloud/event-bus'\nimport { FileAction } from '@nextcloud/files'\nimport { t } from '@nextcloud/l10n'\nimport { getStatus } from '../services/externalStorage.ts'\nimport { StorageStatus } from '../types.ts'\nimport { isMissingAuthConfig } from '../utils/credentialsUtils.ts'\nimport { isNodeExternalStorage } from '../utils/externalStorageUtils.ts'\n\nimport '../css/fileEntryStatus.scss'\n\nexport const action = new FileAction({\n\tid: 'check-external-storage',\n\tdisplayName: () => '',\n\ticonSvgInline: () => '',\n\n\tenabled: ({ nodes }) => {\n\t\treturn nodes.every((node) => isNodeExternalStorage(node) === true)\n\t},\n\texec: async () => null,\n\n\t/**\n\t * Use this function to check the storage availability\n\t * We then update the node attributes directly.\n\t *\n\t * @param context - The action context\n\t * @param context.nodes - The node to render inline\n\t */\n\tasync renderInline({ nodes }) {\n\t\tif (nodes.length !== 1 || !nodes[0]) {\n\t\t\treturn null\n\t\t}\n\n\t\tconst node = nodes[0]\n\t\tconst span = document.createElement('span')\n\t\tspan.className = 'files-list__row-status'\n\t\tspan.innerHTML = t('files_external', 'Checking storage …')\n\n\t\tlet config: IStorage | undefined\n\t\ttry {\n\t\t\tconst { data } = await getStatus(node.attributes.id, node.attributes.scope === 'system')\n\t\t\tconfig = data\n\t\t\tnode.attributes.config = config\n\t\t\temit('files:node:updated', node)\n\n\t\t\tif (config.status !== StorageStatus.Success) {\n\t\t\t\tthrow new Error(config?.statusMessage || t('files_external', 'There was an error with this external storage.'))\n\t\t\t}\n\n\t\t\tspan.remove()\n\t\t} catch (error) {\n\t\t\t// If axios failed or if something else prevented\n\t\t\t// us from getting the config\n\t\t\tif ((error as AxiosError).response && !config) {\n\t\t\t\tshowWarning(t('files_external', 'We were unable to check the external storage {basename}', {\n\t\t\t\t\tbasename: node.basename,\n\t\t\t\t}))\n\t\t\t}\n\n\t\t\t// Reset inline status\n\t\t\tspan.innerHTML = ''\n\n\t\t\t// Checking if we really have an error\n\t\t\tconst isWarning = !config ? false : isMissingAuthConfig(config)\n\t\t\tconst overlay = document.createElement('span')\n\t\t\toverlay.classList.add(`files-list__row-status--${isWarning ? 'warning' : 'error'}`)\n\n\t\t\t// Only show an icon for errors, warning like missing credentials\n\t\t\t// have a dedicated inline action button\n\t\t\tif (!isWarning) {\n\t\t\t\tspan.innerHTML = AlertSvg\n\t\t\t\tspan.title = (error as Error).message\n\t\t\t}\n\n\t\t\tspan.prepend(overlay)\n\t\t}\n\n\t\treturn span\n\t},\n\n\torder: 10,\n})\n","/*!\n * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors\n * SPDX-License-Identifier: AGPL-3.0-or-later\n */\n\nimport type { IStorage } from '../types.ts'\n\nimport { getCurrentUser } from '@nextcloud/auth'\nimport { showConfirmation } from '@nextcloud/dialogs'\nimport { DefaultType, FileAction } from '@nextcloud/files'\nimport { t } from '@nextcloud/l10n'\nimport { generateUrl } from '@nextcloud/router'\nimport { StorageStatus } from '../types.ts'\n\nexport const action = new FileAction({\n\tid: 'open-in-files-external-storage',\n\tdisplayName: ({ nodes }) => {\n\t\tconst config = nodes?.[0]?.attributes?.config as IStorage || { status: StorageStatus.Indeterminate }\n\t\tif (config.status !== StorageStatus.Success) {\n\t\t\treturn t('files_external', 'Examine this faulty external storage configuration')\n\t\t}\n\t\treturn t('files', 'Open in Files')\n\t},\n\ticonSvgInline: () => '',\n\n\tenabled: ({ view }) => view.id === 'extstoragemounts',\n\n\tasync exec({ nodes }) {\n\t\tconst config = nodes[0]?.attributes?.config as IStorage\n\t\tif (config?.status !== StorageStatus.Success) {\n\t\t\tconst redirect = await showConfirmation({\n\t\t\t\tname: t('files_external', 'External mount error'),\n\t\t\t\ttext: t('files_external', 'There was an error with this external storage. Do you want to review this mount point config in the settings page?'),\n\t\t\t\tlabelConfirm: t('files_external', 'Open settings'),\n\t\t\t\tlabelReject: t('files_external', 'Ignore'),\n\t\t\t})\n\t\t\tif (redirect === true) {\n\t\t\t\tconst scope = getCurrentUser()?.isAdmin ? 'admin' : 'user'\n\t\t\t\twindow.location.href = generateUrl(`/settings/${scope}/externalstorages`)\n\t\t\t}\n\t\t\treturn null\n\t\t}\n\n\t\t// Do not use fileid as we don't have that information\n\t\t// from the external storage api\n\t\twindow.OCP.Files.Router.goToRoute(\n\t\t\tnull, // use default route\n\t\t\t{ view: 'files' },\n\t\t\t{ dir: nodes[0].path },\n\t\t)\n\t\treturn null\n\t},\n\n\t// Before openFolderAction\n\torder: -1000,\n\tdefault: DefaultType.HIDDEN,\n})\n","/*\n * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors\n * SPDX-License-Identifier: AGPL-3.0-or-later\n */\n\nimport FolderNetworkSvg from '@mdi/svg/svg/folder-network-outline.svg?raw'\nimport { Column, getNavigation, registerFileAction, View } from '@nextcloud/files'\nimport { loadState } from '@nextcloud/initial-state'\nimport { translate as t } from '@nextcloud/l10n'\nimport { action as enterCredentialsAction } from './actions/enterCredentialsAction.ts'\nimport { action as inlineStorageCheckAction } from './actions/inlineStorageCheckAction.ts'\nimport { action as openInFilesAction } from './actions/openInFilesAction.ts'\nimport { getContents } from './services/externalStorage.ts'\n\nconst allowUserMounting = loadState('files_external', 'allowUserMounting', false)\n\n// Register view\nconst Navigation = getNavigation()\nNavigation.register(new View({\n\tid: 'extstoragemounts',\n\tname: t('files_external', 'External storage'),\n\tcaption: t('files_external', 'List of external storage.'),\n\n\temptyCaption: allowUserMounting\n\t\t? t('files_external', 'There is no external storage configured. You can configure them in your Personal settings.')\n\t\t: t('files_external', 'There is no external storage configured and you don\\'t have the permission to configure them.'),\n\temptyTitle: t('files_external', 'No external storage'),\n\n\ticon: FolderNetworkSvg,\n\torder: 30,\n\n\tcolumns: [\n\t\tnew Column({\n\t\t\tid: 'storage-type',\n\t\t\ttitle: t('files_external', 'Storage type'),\n\t\t\trender(node) {\n\t\t\t\tconst backend = node.attributes?.backend || t('files_external', 'Unknown')\n\t\t\t\tconst span = document.createElement('span')\n\t\t\t\tspan.textContent = backend\n\t\t\t\treturn span\n\t\t\t},\n\t\t}),\n\t\tnew Column({\n\t\t\tid: 'scope',\n\t\t\ttitle: t('files_external', 'Scope'),\n\t\t\trender(node) {\n\t\t\t\tconst span = document.createElement('span')\n\t\t\t\tlet scope = t('files_external', 'Personal')\n\t\t\t\tif (node.attributes?.scope === 'system') {\n\t\t\t\t\tscope = t('files_external', 'System')\n\t\t\t\t}\n\t\t\t\tspan.textContent = scope\n\t\t\t\treturn span\n\t\t\t},\n\t\t}),\n\t],\n\n\tgetContents,\n}))\n\n// Register actions\nregisterFileAction(enterCredentialsAction)\nregisterFileAction(inlineStorageCheckAction)\nregisterFileAction(openInFilesAction)\n"],"file":"files_external-init.mjs"} |