Merge pull request #50931 from nextcloud/backport/50910/stable30

This commit is contained in:
John Molakvoæ 2025-02-21 10:11:04 +01:00 committed by GitHub
commit 306fa8da91
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
19 changed files with 306 additions and 60 deletions

View file

@ -7,6 +7,7 @@ import type { AxiosResponse } from '@nextcloud/axios'
import type { Node } from '@nextcloud/files'
import type { StorageConfig } from '../services/externalStorage'
import { addPasswordConfirmationInterceptors, PwdConfirmationMode } from '@nextcloud/password-confirmation'
import { generateUrl } from '@nextcloud/router'
import { showError, showSuccess, spawnDialog } from '@nextcloud/dialogs'
import { translate as t } from '@nextcloud/l10n'
@ -18,20 +19,30 @@ import { FileAction, DefaultType } from '@nextcloud/files'
import { STORAGE_STATUS, isMissingAuthConfig } from '../utils/credentialsUtils'
import { isNodeExternalStorage } from '../utils/externalStorageUtils'
// Add password confirmation interceptors as
// the backend requires the user to confirm their password
addPasswordConfirmationInterceptors(axios)
type CredentialResponse = {
login?: string,
password?: string,
}
/**
* Set credentials for external storage
*
* @param node
* @param login
* @param password
* @param node The node for which to set the credentials
* @param login The username
* @param password The password
*/
async function setCredentials(node: Node, login: string, password: string): Promise<null|true> {
const configResponse = await axios.put(generateUrl('apps/files_external/userglobalstorages/{id}', node.attributes), {
backendOptions: { user: login, password },
const configResponse = await axios.request({
method: 'PUT',
url: generateUrl('apps/files_external/userglobalstorages/{id}', { id: node.attributes.id }),
confirmPassword: PwdConfirmationMode.Strict,
data: {
backendOptions: { user: login, password },
},
}) as AxiosResponse<StorageConfig>
const config = configResponse.data
@ -48,8 +59,10 @@ async function setCredentials(node: Node, login: string, password: string): Prom
return true
}
export const ACTION_CREDENTIALS_EXTERNAL_STORAGE = 'credentials-external-storage'
export const action = new FileAction({
id: 'credentials-external-storage',
id: ACTION_CREDENTIALS_EXTERNAL_STORAGE,
displayName: () => t('files', 'Enter missing credentials'),
iconSvgInline: () => LoginSvg,
@ -82,7 +95,14 @@ export const action = new FileAction({
))
if (login && password) {
return await setCredentials(node, login, password)
try {
await setCredentials(node, login, password)
showSuccess(t('files_external', 'Credentials successfully set'))
} catch (error) {
showError(t('files_external', 'Error while setting credentials: {error}', {
error: (error as Error).message,
}))
}
}
return null

View file

@ -6,6 +6,7 @@
import type { AxiosError } from '@nextcloud/axios'
import type { Node } from '@nextcloud/files'
import { FileAction } from '@nextcloud/files'
import { showWarning } from '@nextcloud/dialogs'
import { translate as t } from '@nextcloud/l10n'
import AlertSvg from '@mdi/svg/svg/alert-circle.svg?raw'
@ -15,7 +16,6 @@ import '../css/fileEntryStatus.scss'
import { getStatus, type StorageConfig } from '../services/externalStorage'
import { isMissingAuthConfig, STORAGE_STATUS } from '../utils/credentialsUtils'
import { isNodeExternalStorage } from '../utils/externalStorageUtils'
import { FileAction } from '@nextcloud/files'
export const action = new FileAction({
id: 'check-external-storage',
@ -33,45 +33,51 @@ export const action = new FileAction({
* @param node
*/
async renderInline(node: Node) {
const span = document.createElement('span')
span.className = 'files-list__row-status'
span.innerHTML = t('files_external', 'Checking storage...')
let config = null as unknown as StorageConfig
try {
const response = await getStatus(node.attributes.id, node.attributes.scope === 'system')
config = response.data
Vue.set(node.attributes, 'config', config)
getStatus(node.attributes.id, node.attributes.scope === 'system')
.then(response => {
if (config.status !== STORAGE_STATUS.SUCCESS) {
throw new Error(config?.statusMessage || t('files_external', 'There was an error with this external storage.'))
}
config = response.data
Vue.set(node.attributes, 'config', config)
return null
} catch (error) {
// If axios failed or if something else prevented
// us from getting the config
if ((error as AxiosError).response && !config) {
showWarning(t('files_external', 'We were unable to check the external storage {basename}', {
basename: node.basename,
}))
return null
}
if (config.status !== STORAGE_STATUS.SUCCESS) {
throw new Error(config?.statusMessage || t('files_external', 'There was an error with this external storage.'))
}
// Checking if we really have an error
const isWarning = isMissingAuthConfig(config)
const overlay = document.createElement('span')
overlay.classList.add(`files-list__row-status--${isWarning ? 'warning' : 'error'}`)
span.remove()
})
.catch(error => {
// If axios failed or if something else prevented
// us from getting the config
if ((error as AxiosError).response && !config) {
showWarning(t('files_external', 'We were unable to check the external storage {basename}', {
basename: node.basename,
}))
}
const span = document.createElement('span')
span.className = 'files-list__row-status'
// Reset inline status
span.innerHTML = ''
// Only show an icon for errors, warning like missing credentials
// have a dedicated inline action button
if (!isWarning) {
span.innerHTML = AlertSvg
span.title = (error as Error).message
}
// Checking if we really have an error
const isWarning = !config ? false : isMissingAuthConfig(config)
const overlay = document.createElement('span')
overlay.classList.add(`files-list__row-status--${isWarning ? 'warning' : 'error'}`)
span.prepend(overlay)
return span
}
// Only show an icon for errors, warning like missing credentials
// have a dedicated inline action button
if (!isWarning) {
span.innerHTML = AlertSvg
span.title = (error as Error).message
}
span.prepend(overlay)
})
return span
},
order: 10,

View file

@ -10,6 +10,7 @@ import { translate as t } from '@nextcloud/l10n'
import { FileAction, DefaultType } from '@nextcloud/files'
import { STORAGE_STATUS } from '../utils/credentialsUtils'
import { getCurrentUser } from '@nextcloud/auth'
export const action = new FileAction({
id: 'open-in-files-external-storage',
@ -32,7 +33,7 @@ export const action = new FileAction({
t('files_external', 'External mount error'),
(redirect) => {
if (redirect === true) {
const scope = node.attributes.scope === 'personal' ? 'user' : 'admin'
const scope = getCurrentUser()?.isAdmin ? 'admin' : 'user'
window.location.href = generateUrl(`/settings/${scope}/externalstorages`)
}
},

View file

@ -4,10 +4,13 @@
*/
.files-list__row-status {
display: flex;
width: 44px;
min-width: 44px;
justify-content: center;
align-items: center;
height: 100%;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
svg {
width: 24px;

View file

@ -76,7 +76,7 @@ export default defineComponent({
computed: {
dialogButtons() {
return [{
label: t('files_external', 'Submit'),
label: t('files_external', 'Confirm'),
type: 'primary',
nativeType: 'submit',
}]

View file

@ -53,6 +53,10 @@ export const startNextcloud = async function(branch: string = getCurrentGitBranc
reject(err)
}
}))
const digest = await (await docker.getImage(SERVER_IMAGE).inspect()).RepoDigests.at(0)
const sha = digest?.split('@').at(1)
console.log('├─ Using image ' + sha)
console.log('└─ Done')
} catch (e) {
console.log('└─ Failed to pull images')

View file

@ -11,23 +11,52 @@ export const getRowForFile = (filename: string) => cy.get(`[data-cy-files-list-r
export const getActionsForFileId = (fileid: number) => getRowForFileId(fileid).find('[data-cy-files-list-row-actions]')
export const getActionsForFile = (filename: string) => getRowForFile(filename).find('[data-cy-files-list-row-actions]')
export const getActionButtonForFileId = (fileid: number) => getActionsForFileId(fileid).find('button[aria-label="Actions"]')
export const getActionButtonForFile = (filename: string) => getActionsForFile(filename).find('button[aria-label="Actions"]')
export const getActionButtonForFileId = (fileid: number) => getActionsForFileId(fileid).findByRole('button', { name: 'Actions' })
export const getActionButtonForFile = (filename: string) => getActionsForFile(filename).findByRole('button', { name: 'Actions' })
const searchForActionInRow = (row: JQuery<HTMLElement>, actionId: string): Cypress.Chainable<JQuery<HTMLElement>> => {
const action = row.find(`[data-cy-files-list-row-action="${CSS.escape(actionId)}"]`)
if (action.length > 0) {
cy.log('Found action in row')
return cy.wrap(action)
}
// Else look in the action menu
const menuButtonId = row.find('button[aria-controls]').attr('aria-controls')
return cy.get(`#${menuButtonId} [data-cy-files-list-row-action="${CSS.escape(actionId)}"]`)
}
export const getActionEntryForFileId = (fileid: number, actionId: string): Cypress.Chainable<JQuery<HTMLElement>> => {
// If we cannot find the action in the row, it might be in the action menu
return getRowForFileId(fileid).should('be.visible')
.then(row => searchForActionInRow(row, actionId))
}
export const getActionEntryForFile = (filename: string, actionId: string): Cypress.Chainable<JQuery<HTMLElement>> => {
// If we cannot find the action in the row, it might be in the action menu
return getRowForFile(filename).should('be.visible')
.then(row => searchForActionInRow(row, actionId))
}
export const triggerActionForFileId = (fileid: number, actionId: string) => {
getActionButtonForFileId(fileid).click()
cy.get(`[data-cy-files-list-row-action="${CSS.escape(actionId)}"] > button`).should('exist').click()
// Even if it's inline, we open the action menu to get all actions visible
getActionButtonForFileId(fileid).click({ force: true })
getActionEntryForFileId(fileid, actionId)
.find('button').last()
.should('exist').click({ force: true })
}
export const triggerActionForFile = (filename: string, actionId: string) => {
getActionButtonForFile(filename).click()
cy.get(`[data-cy-files-list-row-action="${CSS.escape(actionId)}"] > button`).should('exist').click()
// Even if it's inline, we open the action menu to get all actions visible
getActionButtonForFile(filename).click({ force: true })
getActionEntryForFile(filename, actionId)
.find('button').last()
.should('exist').click({ force: true })
}
export const triggerInlineActionForFileId = (fileid: number, actionId: string) => {
getActionsForFileId(fileid).find(`button[data-cy-files-list-row-action="${CSS.escape(actionId)}"]`).should('exist').click()
}
export const triggerInlineActionForFile = (filename: string, actionId: string) => {
getActionsForFile(filename).get(`button[data-cy-files-list-row-action="${CSS.escape(actionId)}"]`).should('exist').click()
getActionsForFile(filename).find(`button[data-cy-files-list-row-action="${CSS.escape(actionId)}"]`).should('exist').click()
}
export const selectAllFiles = () => {

View file

@ -0,0 +1,38 @@
/**
* SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
import type { User } from "@nextcloud/cypress"
export type StorageConfig = {
[key: string]: string
}
export enum StorageBackend {
DAV = 'dav',
SMB = 'smb',
SFTP = 'sftp',
}
export enum AuthBackend {
GlobalAuth = 'password::global',
LoginCredentials = 'password::logincredentials',
Password = 'password::password',
SessionCredentials = 'password::sessioncredentials',
UserGlobalAuth = 'password::global::user',
UserProvided = 'password::userprovided',
}
/**
* Create a storage via occ
*/
export function createStorageWithConfig(mountPoint: string, storageBackend: StorageBackend, authBackend: AuthBackend, configs: StorageConfig, user?: User): Cypress.Chainable {
const configsFlag = Object.keys(configs).map(key => `--config "${key}=${configs[key]}"`).join(' ')
const userFlag = user ? `--user ${user.userId}` : ''
const command = `files_external:create "${mountPoint}" "${storageBackend}" "${authBackend}" ${configsFlag} ${userFlag}`
cy.log(`Creating storage with command: ${command}`)
return cy.runOccCommand(command)
}

View file

@ -0,0 +1,138 @@
/**
* SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
import { User } from '@nextcloud/cypress'
import { AuthBackend, createStorageWithConfig, StorageBackend } from './StorageUtils'
import { getActionEntryForFile, getRowForFile, navigateToFolder, triggerInlineActionForFile } from '../files/FilesUtils'
import { ACTION_CREDENTIALS_EXTERNAL_STORAGE } from '../../../apps/files_external/src/actions/enterCredentialsAction'
import { handlePasswordConfirmation } from '../settings/usersUtils'
describe('Files user credentials', { testIsolation: true }, () => {
let user1: User
let user2: User
let storageUser: User
beforeEach(() => {
})
before(() => {
cy.runOccCommand('app:enable files_external')
// Create some users
cy.createRandomUser().then((user) => user1 = user)
cy.createRandomUser().then((user) => user2 = user)
// This user will hold the webdav storage
cy.createRandomUser().then((user) => {
storageUser = user
cy.uploadFile(user, 'image.jpg')
})
})
after(() => {
// Cleanup global storages
cy.runOccCommand(`files_external:list --output=json`).then(({stdout}) => {
const list = JSON.parse(stdout)
list.forEach((storage) => cy.runOccCommand(`files_external:delete --yes ${storage.mount_id}`), { failOnNonZeroExit: false })
})
cy.runOccCommand('app:disable files_external')
})
it('Create a user storage with user credentials', () => {
const url = Cypress.config('baseUrl') + '/remote.php/dav/files/' + storageUser.userId
createStorageWithConfig(storageUser.userId, StorageBackend.DAV, AuthBackend.UserProvided, { host: url.replace('index.php/', ''), 'secure': 'false' })
cy.login(user1)
cy.visit('/apps/files/extstoragemounts')
getRowForFile(storageUser.userId).should('be.visible')
cy.intercept('PUT', '**/apps/files_external/userglobalstorages/*').as('setCredentials')
triggerInlineActionForFile(storageUser.userId, ACTION_CREDENTIALS_EXTERNAL_STORAGE)
// See credentials dialog
const storageDialog = cy.findByRole('dialog', { name: 'Storage credentials' })
storageDialog.should('be.visible')
storageDialog.findByRole('textbox', { name: 'Login' }).type(storageUser.userId)
storageDialog.get('input[type="password"]').type(storageUser.password)
storageDialog.get('button').contains('Confirm').click()
storageDialog.should('not.exist')
// Storage dialog now closed, the user auth dialog should be visible
const authDialog = cy.findByRole('dialog', { name: 'Confirm your password' })
authDialog.should('be.visible')
handlePasswordConfirmation(user1.password)
// Wait for the credentials to be set
cy.wait('@setCredentials')
// Auth dialog should be closed and the set credentials button should be gone
authDialog.should('not.exist', { timeout: 2000 })
getActionEntryForFile(storageUser.userId, ACTION_CREDENTIALS_EXTERNAL_STORAGE).should('not.exist')
// Finally, the storage should be accessible
cy.visit('/apps/files')
navigateToFolder(storageUser.userId)
getRowForFile('image.jpg').should('be.visible')
})
it('Create a user storage with GLOBAL user credentials', () => {
const url = Cypress.config('baseUrl') + '/remote.php/dav/files/' + storageUser.userId
createStorageWithConfig('storage1', StorageBackend.DAV, AuthBackend.UserGlobalAuth, { host: url.replace('index.php/', ''), 'secure': 'false' })
cy.login(user2)
cy.visit('/apps/files/extstoragemounts')
getRowForFile('storage1').should('be.visible')
cy.intercept('PUT', '**/apps/files_external/userglobalstorages/*').as('setCredentials')
triggerInlineActionForFile('storage1', ACTION_CREDENTIALS_EXTERNAL_STORAGE)
// See credentials dialog
const storageDialog = cy.findByRole('dialog', { name: 'Storage credentials' })
storageDialog.should('be.visible')
storageDialog.findByRole('textbox', { name: 'Login' }).type(storageUser.userId)
storageDialog.get('input[type="password"]').type(storageUser.password)
storageDialog.get('button').contains('Confirm').click()
storageDialog.should('not.exist')
// Storage dialog now closed, the user auth dialog should be visible
const authDialog = cy.findByRole('dialog', { name: 'Confirm your password' })
authDialog.should('be.visible')
handlePasswordConfirmation(user2.password)
// Wait for the credentials to be set
cy.wait('@setCredentials')
// Auth dialog should be closed and the set credentials button should be gone
authDialog.should('not.exist', { timeout: 2000 })
getActionEntryForFile('storage1', ACTION_CREDENTIALS_EXTERNAL_STORAGE).should('not.exist')
// Finally, the storage should be accessible
cy.visit('/apps/files')
navigateToFolder('storage1')
getRowForFile('image.jpg').should('be.visible')
})
it('Create another user storage while reusing GLOBAL user credentials', () => {
const url = Cypress.config('baseUrl') + '/remote.php/dav/files/' + storageUser.userId
createStorageWithConfig('storage2', StorageBackend.DAV, AuthBackend.UserGlobalAuth, { host: url.replace('index.php/', ''), 'secure': 'false' })
cy.login(user2)
cy.visit('/apps/files/extstoragemounts')
getRowForFile('storage2').should('be.visible')
// Since we already have set the credentials, the action should not be present
getActionEntryForFile('storage1', ACTION_CREDENTIALS_EXTERNAL_STORAGE).should('not.exist')
getActionEntryForFile('storage2', ACTION_CREDENTIALS_EXTERNAL_STORAGE).should('not.exist')
// Finally, the storage should be accessible
cy.visit('/apps/files')
navigateToFolder('storage2')
getRowForFile('image.jpg').should('be.visible')
})
})

View file

@ -1 +0,0 @@
5203-5203.js.license

View file

@ -1,2 +1,2 @@
"use strict";(self.webpackChunknextcloud=self.webpackChunknextcloud||[]).push([[5203],{95203:(e,t,a)=>{a.r(t),a.d(t,{default:()=>d});var s=a(85471),l=a(53334),o=a(94219),r=a(80910),n=a(16044),i=a(82182);const u=(0,s.pM)({name:"CredentialsDialog",components:{NcDialog:o.A,NcNoteCard:r.A,NcTextField:i.A,NcPasswordField:n.A},setup:()=>({t:l.t}),data:()=>({login:"",password:""}),computed:{dialogButtons:()=>[{label:(0,l.t)("files_external","Submit"),type:"primary",nativeType:"submit"}]}}),d=(0,a(14486).A)(u,(function(){var e=this,t=e._self._c;return e._self._setupProxy,t("NcDialog",{staticClass:"external-storage-auth",attrs:{buttons:e.dialogButtons,"close-on-click-outside":"","data-cy-external-storage-auth":"","is-form":"",name:e.t("files_external","Storage credentials"),"out-transition":""},on:{submit:function(t){return e.$emit("close",{login:e.login,password:e.password})},"update:open":function(t){return e.$emit("close")}}},[t("NcNoteCard",{staticClass:"external-storage-auth__header",attrs:{text:e.t("files_external","To access the storage, you need to provide the authentication credentials."),type:"info"}}),e._v(" "),t("NcTextField",{ref:"login",staticClass:"external-storage-auth__login",attrs:{"data-cy-external-storage-auth-dialog-login":"",label:e.t("files_external","Login"),placeholder:e.t("files_external","Enter the storage login"),minlength:"2",name:"login",required:"",value:e.login},on:{"update:value":function(t){e.login=t}}}),e._v(" "),t("NcPasswordField",{ref:"password",staticClass:"external-storage-auth__password",attrs:{"data-cy-external-storage-auth-dialog-password":"",label:e.t("files_external","Password"),placeholder:e.t("files_external","Enter the storage password"),name:"password",required:"",value:e.password},on:{"update:value":function(t){e.password=t}}})],1)}),[],!1,null,null,null).exports}}]);
//# sourceMappingURL=5203-5203.js.map?v=b7f7782ba581b3046e33
"use strict";(self.webpackChunknextcloud=self.webpackChunknextcloud||[]).push([[7367],{7367:(e,t,a)=>{a.r(t),a.d(t,{default:()=>u});var s=a(85471),l=a(53334),o=a(94219),r=a(80910),n=a(16044),i=a(82182);const d=(0,s.pM)({name:"CredentialsDialog",components:{NcDialog:o.A,NcNoteCard:r.A,NcTextField:i.A,NcPasswordField:n.A},setup:()=>({t:l.t}),data:()=>({login:"",password:""}),computed:{dialogButtons:()=>[{label:(0,l.t)("files_external","Confirm"),type:"primary",nativeType:"submit"}]}}),u=(0,a(14486).A)(d,(function(){var e=this,t=e._self._c;return e._self._setupProxy,t("NcDialog",{staticClass:"external-storage-auth",attrs:{buttons:e.dialogButtons,"close-on-click-outside":"","data-cy-external-storage-auth":"","is-form":"",name:e.t("files_external","Storage credentials"),"out-transition":""},on:{submit:function(t){return e.$emit("close",{login:e.login,password:e.password})},"update:open":function(t){return e.$emit("close")}}},[t("NcNoteCard",{staticClass:"external-storage-auth__header",attrs:{text:e.t("files_external","To access the storage, you need to provide the authentication credentials."),type:"info"}}),e._v(" "),t("NcTextField",{ref:"login",staticClass:"external-storage-auth__login",attrs:{"data-cy-external-storage-auth-dialog-login":"",label:e.t("files_external","Login"),placeholder:e.t("files_external","Enter the storage login"),minlength:"2",name:"login",required:"",value:e.login},on:{"update:value":function(t){e.login=t}}}),e._v(" "),t("NcPasswordField",{ref:"password",staticClass:"external-storage-auth__password",attrs:{"data-cy-external-storage-auth-dialog-password":"",label:e.t("files_external","Password"),placeholder:e.t("files_external","Enter the storage password"),name:"password",required:"",value:e.password},on:{"update:value":function(t){e.password=t}}})],1)}),[],!1,null,null,null).exports}}]);
//# sourceMappingURL=7367-7367.js.map?v=1378e249b074821c3454

View file

@ -1 +1 @@
{"version":3,"file":"5203-5203.js?v=b7f7782ba581b3046e33","mappings":"qIAAA,I,kEAMA,MCNiQ,GDMlPA,EAAAA,EAAAA,IAAgB,CAC3BC,KAAM,oBACNC,WAAY,CACRC,SAAQ,IACRC,WAAU,IACVC,YAAW,IACXC,gBAAeA,EAAAA,GAEnBC,MAAKA,KACM,CACHC,EAACA,EAAAA,IAGTC,KAAIA,KACO,CACHC,MAAO,GACPC,SAAU,KAGlBC,SAAU,CACNC,cAAaA,IACF,CAAC,CACAC,OAAON,EAAAA,EAAAA,GAAE,iBAAkB,UAC3BO,KAAM,UACNC,WAAY,cEZhC,GAXgB,E,SAAA,GACd,GFRW,WAAkB,IAAIC,EAAIC,KAAKC,EAAGF,EAAIG,MAAMD,GAAgC,OAAtBF,EAAIG,MAAMC,YAAmBF,EAAG,WAAW,CAACG,YAAY,wBAAwBC,MAAM,CAAC,QAAUN,EAAIJ,cAAc,yBAAyB,GAAG,gCAAgC,GAAG,UAAU,GAAG,KAAOI,EAAIT,EAAE,iBAAkB,uBAAuB,iBAAiB,IAAIgB,GAAG,CAAC,OAAS,SAASC,GAAQ,OAAOR,EAAIS,MAAM,QAAS,CAAChB,MAAOO,EAAIP,MAAOC,SAAUM,EAAIN,UAAU,EAAE,cAAc,SAASc,GAAQ,OAAOR,EAAIS,MAAM,QAAQ,IAAI,CAACP,EAAG,aAAa,CAACG,YAAY,gCAAgCC,MAAM,CAAC,KAAON,EAAIT,EAAE,iBAAkB,8EAA8E,KAAO,UAAUS,EAAIU,GAAG,KAAKR,EAAG,cAAc,CAACS,IAAI,QAAQN,YAAY,+BAA+BC,MAAM,CAAC,6CAA6C,GAAG,MAAQN,EAAIT,EAAE,iBAAkB,SAAS,YAAcS,EAAIT,EAAE,iBAAkB,2BAA2B,UAAY,IAAI,KAAO,QAAQ,SAAW,GAAG,MAAQS,EAAIP,OAAOc,GAAG,CAAC,eAAe,SAASC,GAAQR,EAAIP,MAAMe,CAAM,KAAKR,EAAIU,GAAG,KAAKR,EAAG,kBAAkB,CAACS,IAAI,WAAWN,YAAY,kCAAkCC,MAAM,CAAC,gDAAgD,GAAG,MAAQN,EAAIT,EAAE,iBAAkB,YAAY,YAAcS,EAAIT,EAAE,iBAAkB,8BAA8B,KAAO,WAAW,SAAW,GAAG,MAAQS,EAAIN,UAAUa,GAAG,CAAC,eAAe,SAASC,GAAQR,EAAIN,SAASc,CAAM,MAAM,EAC55C,GACsB,IESpB,EACA,KACA,KACA,MAI8B,O","sources":["webpack:///nextcloud/apps/files_external/src/views/CredentialsDialog.vue","webpack:///nextcloud/apps/files_external/src/views/CredentialsDialog.vue?vue&type=script&lang=ts","webpack://nextcloud/./apps/files_external/src/views/CredentialsDialog.vue?7767"],"sourcesContent":["var render = function render(){var _vm=this,_c=_vm._self._c,_setup=_vm._self._setupProxy;return _c('NcDialog',{staticClass:\"external-storage-auth\",attrs:{\"buttons\":_vm.dialogButtons,\"close-on-click-outside\":\"\",\"data-cy-external-storage-auth\":\"\",\"is-form\":\"\",\"name\":_vm.t('files_external', 'Storage credentials'),\"out-transition\":\"\"},on:{\"submit\":function($event){return _vm.$emit('close', {login: _vm.login, password: _vm.password})},\"update:open\":function($event){return _vm.$emit('close')}}},[_c('NcNoteCard',{staticClass:\"external-storage-auth__header\",attrs:{\"text\":_vm.t('files_external', 'To access the storage, you need to provide the authentication credentials.'),\"type\":\"info\"}}),_vm._v(\" \"),_c('NcTextField',{ref:\"login\",staticClass:\"external-storage-auth__login\",attrs:{\"data-cy-external-storage-auth-dialog-login\":\"\",\"label\":_vm.t('files_external', 'Login'),\"placeholder\":_vm.t('files_external', 'Enter the storage login'),\"minlength\":\"2\",\"name\":\"login\",\"required\":\"\",\"value\":_vm.login},on:{\"update:value\":function($event){_vm.login=$event}}}),_vm._v(\" \"),_c('NcPasswordField',{ref:\"password\",staticClass:\"external-storage-auth__password\",attrs:{\"data-cy-external-storage-auth-dialog-password\":\"\",\"label\":_vm.t('files_external', 'Password'),\"placeholder\":_vm.t('files_external', 'Enter the storage password'),\"name\":\"password\",\"required\":\"\",\"value\":_vm.password},on:{\"update:value\":function($event){_vm.password=$event}}})],1)\n}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","import mod from \"-!../../../../node_modules/babel-loader/lib/index.js!../../../../node_modules/ts-loader/index.js??clonedRuleSet-4.use[1]!../../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./CredentialsDialog.vue?vue&type=script&lang=ts\"; export default mod; export * from \"-!../../../../node_modules/babel-loader/lib/index.js!../../../../node_modules/ts-loader/index.js??clonedRuleSet-4.use[1]!../../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./CredentialsDialog.vue?vue&type=script&lang=ts\"","import { render, staticRenderFns } from \"./CredentialsDialog.vue?vue&type=template&id=be6428e4\"\nimport script from \"./CredentialsDialog.vue?vue&type=script&lang=ts\"\nexport * from \"./CredentialsDialog.vue?vue&type=script&lang=ts\"\n\n\n/* normalize component */\nimport normalizer from \"!../../../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n null,\n null\n \n)\n\nexport default component.exports"],"names":["defineComponent","name","components","NcDialog","NcNoteCard","NcTextField","NcPasswordField","setup","t","data","login","password","computed","dialogButtons","label","type","nativeType","_vm","this","_c","_self","_setupProxy","staticClass","attrs","on","$event","$emit","_v","ref"],"sourceRoot":""}
{"version":3,"file":"7367-7367.js?v=1378e249b074821c3454","mappings":"oIAAA,I,kEAMA,MCNiQ,GDMlPA,EAAAA,EAAAA,IAAgB,CAC3BC,KAAM,oBACNC,WAAY,CACRC,SAAQ,IACRC,WAAU,IACVC,YAAW,IACXC,gBAAeA,EAAAA,GAEnBC,MAAKA,KACM,CACHC,EAACA,EAAAA,IAGTC,KAAIA,KACO,CACHC,MAAO,GACPC,SAAU,KAGlBC,SAAU,CACNC,cAAaA,IACF,CAAC,CACAC,OAAON,EAAAA,EAAAA,GAAE,iBAAkB,WAC3BO,KAAM,UACNC,WAAY,cEZhC,GAXgB,E,SAAA,GACd,GFRW,WAAkB,IAAIC,EAAIC,KAAKC,EAAGF,EAAIG,MAAMD,GAAgC,OAAtBF,EAAIG,MAAMC,YAAmBF,EAAG,WAAW,CAACG,YAAY,wBAAwBC,MAAM,CAAC,QAAUN,EAAIJ,cAAc,yBAAyB,GAAG,gCAAgC,GAAG,UAAU,GAAG,KAAOI,EAAIT,EAAE,iBAAkB,uBAAuB,iBAAiB,IAAIgB,GAAG,CAAC,OAAS,SAASC,GAAQ,OAAOR,EAAIS,MAAM,QAAS,CAAChB,MAAOO,EAAIP,MAAOC,SAAUM,EAAIN,UAAU,EAAE,cAAc,SAASc,GAAQ,OAAOR,EAAIS,MAAM,QAAQ,IAAI,CAACP,EAAG,aAAa,CAACG,YAAY,gCAAgCC,MAAM,CAAC,KAAON,EAAIT,EAAE,iBAAkB,8EAA8E,KAAO,UAAUS,EAAIU,GAAG,KAAKR,EAAG,cAAc,CAACS,IAAI,QAAQN,YAAY,+BAA+BC,MAAM,CAAC,6CAA6C,GAAG,MAAQN,EAAIT,EAAE,iBAAkB,SAAS,YAAcS,EAAIT,EAAE,iBAAkB,2BAA2B,UAAY,IAAI,KAAO,QAAQ,SAAW,GAAG,MAAQS,EAAIP,OAAOc,GAAG,CAAC,eAAe,SAASC,GAAQR,EAAIP,MAAMe,CAAM,KAAKR,EAAIU,GAAG,KAAKR,EAAG,kBAAkB,CAACS,IAAI,WAAWN,YAAY,kCAAkCC,MAAM,CAAC,gDAAgD,GAAG,MAAQN,EAAIT,EAAE,iBAAkB,YAAY,YAAcS,EAAIT,EAAE,iBAAkB,8BAA8B,KAAO,WAAW,SAAW,GAAG,MAAQS,EAAIN,UAAUa,GAAG,CAAC,eAAe,SAASC,GAAQR,EAAIN,SAASc,CAAM,MAAM,EAC55C,GACsB,IESpB,EACA,KACA,KACA,MAI8B,O","sources":["webpack:///nextcloud/apps/files_external/src/views/CredentialsDialog.vue","webpack:///nextcloud/apps/files_external/src/views/CredentialsDialog.vue?vue&type=script&lang=ts","webpack://nextcloud/./apps/files_external/src/views/CredentialsDialog.vue?7767"],"sourcesContent":["var render = function render(){var _vm=this,_c=_vm._self._c,_setup=_vm._self._setupProxy;return _c('NcDialog',{staticClass:\"external-storage-auth\",attrs:{\"buttons\":_vm.dialogButtons,\"close-on-click-outside\":\"\",\"data-cy-external-storage-auth\":\"\",\"is-form\":\"\",\"name\":_vm.t('files_external', 'Storage credentials'),\"out-transition\":\"\"},on:{\"submit\":function($event){return _vm.$emit('close', {login: _vm.login, password: _vm.password})},\"update:open\":function($event){return _vm.$emit('close')}}},[_c('NcNoteCard',{staticClass:\"external-storage-auth__header\",attrs:{\"text\":_vm.t('files_external', 'To access the storage, you need to provide the authentication credentials.'),\"type\":\"info\"}}),_vm._v(\" \"),_c('NcTextField',{ref:\"login\",staticClass:\"external-storage-auth__login\",attrs:{\"data-cy-external-storage-auth-dialog-login\":\"\",\"label\":_vm.t('files_external', 'Login'),\"placeholder\":_vm.t('files_external', 'Enter the storage login'),\"minlength\":\"2\",\"name\":\"login\",\"required\":\"\",\"value\":_vm.login},on:{\"update:value\":function($event){_vm.login=$event}}}),_vm._v(\" \"),_c('NcPasswordField',{ref:\"password\",staticClass:\"external-storage-auth__password\",attrs:{\"data-cy-external-storage-auth-dialog-password\":\"\",\"label\":_vm.t('files_external', 'Password'),\"placeholder\":_vm.t('files_external', 'Enter the storage password'),\"name\":\"password\",\"required\":\"\",\"value\":_vm.password},on:{\"update:value\":function($event){_vm.password=$event}}})],1)\n}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","import mod from \"-!../../../../node_modules/babel-loader/lib/index.js!../../../../node_modules/ts-loader/index.js??clonedRuleSet-4.use[1]!../../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./CredentialsDialog.vue?vue&type=script&lang=ts\"; export default mod; export * from \"-!../../../../node_modules/babel-loader/lib/index.js!../../../../node_modules/ts-loader/index.js??clonedRuleSet-4.use[1]!../../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./CredentialsDialog.vue?vue&type=script&lang=ts\"","import { render, staticRenderFns } from \"./CredentialsDialog.vue?vue&type=template&id=196d9300\"\nimport script from \"./CredentialsDialog.vue?vue&type=script&lang=ts\"\nexport * from \"./CredentialsDialog.vue?vue&type=script&lang=ts\"\n\n\n/* normalize component */\nimport normalizer from \"!../../../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n null,\n null\n \n)\n\nexport default component.exports"],"names":["defineComponent","name","components","NcDialog","NcNoteCard","NcTextField","NcPasswordField","setup","t","data","login","password","computed","dialogButtons","label","type","nativeType","_vm","this","_c","_self","_setupProxy","staticClass","attrs","on","$event","$emit","_v","ref"],"sourceRoot":""}

1
dist/7367-7367.js.map.license vendored Symbolic link
View file

@ -0,0 +1 @@
7367-7367.js.license

4
dist/core-common.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -6,6 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-or-later
SPDX-License-Identifier: (MPL-2.0 OR Apache-2.0)
SPDX-FileCopyrightText: inherits developers
SPDX-FileCopyrightText: escape-html developers
SPDX-FileCopyrightText: debounce developers
SPDX-FileCopyrightText: assert developers
SPDX-FileCopyrightText: Varun A P
SPDX-FileCopyrightText: Tobias Koppers @sokra
@ -69,6 +70,9 @@ This file is generated from multiple sources. Included packages:
- @nextcloud/logger
- version: 3.0.2
- license: GPL-3.0-or-later
- @nextcloud/password-confirmation
- version: 5.3.1
- license: MIT
- @nextcloud/paths
- version: 2.2.1
- license: GPL-3.0-or-later
@ -84,6 +88,9 @@ This file is generated from multiple sources. Included packages:
- @vueuse/shared
- version: 11.0.1
- license: MIT
- debounce
- version: 2.1.0
- license: MIT
- @nextcloud/vue
- version: 8.17.1
- license: AGPL-3.0-or-later

File diff suppressed because one or more lines are too long