Merge pull request #59042 from nextcloud/backport/59033/stable33

[stable33] fix(files_external): properly handle API errors
This commit is contained in:
Ferdinand Thiessen 2026-03-18 17:22:02 +01:00 committed by GitHub
commit b96e0aa67b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
31 changed files with 88 additions and 46 deletions

View file

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

View file

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

View file

@ -3,7 +3,7 @@
* 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'
@ -11,6 +11,7 @@ import { addPasswordConfirmationInterceptors, PwdConfirmationMode } from '@nextc
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')
@ -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))
}
/**
@ -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))
}
/**
@ -77,7 +78,7 @@ export const useStorages = defineStore('files_external--storages', () => {
{ confirmPassword: PwdConfirmationMode.Strict },
)
overrideStorage(data)
overrideStorage(parseStorage(data))
}
/**
@ -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
@ -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)
}
/**
@ -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'
}

View file

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

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1,4 +1,4 @@
import{c as u}from"./index-IPON9qO1.chunk.mjs";import{g as y,e as c}from"./index-Bndk0DrU.chunk.mjs";import{t as o}from"./translation-DoG5ZELJ-XUrtIRvk.chunk.mjs";import{c as f}from"./index-BgRPS0vK.chunk.mjs";import{b as h}from"./createElementId-DhjFt1I9-D6sOOWeT.chunk.mjs";import{g as b}from"./dav-C7ZXSSpl.chunk.mjs";const r=y().setApp("systemtags").detectUser().build(),V={userVisible:!0,userAssignable:!0,canAssign:!0},x=Object.freeze({"display-name":"displayName","user-visible":"userVisible","user-assignable":"userAssignable","can-assign":"canAssign"});function p(t){return t.map(({props:s})=>Object.fromEntries(Object.entries(s).map(([e,a])=>(e=x[e]??e,a=e==="displayName"?String(a):a,[e,a]))))}function w(t){const s=t.indexOf("?");s>0&&(t=t.substring(0,s));const e=t.split("/");let a;do a=e[e.length-1],e.pop();while(!a&&e.length>0);return Number(a)}function v(t){if("name"in t&&!("displayName"in t))return{...t};const s={...t};return s.name=s.displayName,delete s.displayName,s}function N(t){const s=t.attributes?.["system-tags"]?.["system-tag"];return s===void 0?[]:[s].flat().map(e=>typeof e=="string"?e:e.text)}function P(t,s){t.attributes["system-tags"]={"system-tag":s},c("files:node:updated",t)}const n=b(),l=`<?xml version="1.0"?>
import{c as u}from"./index-IPON9qO1.chunk.mjs";import{g as y,e as c}from"./index-Bndk0DrU.chunk.mjs";import{t as o}from"./translation-DoG5ZELJ-XUrtIRvk.chunk.mjs";import{c as f}from"./index-dkOkc1OB.chunk.mjs";import{b as h}from"./createElementId-DhjFt1I9-D6sOOWeT.chunk.mjs";import{g as b}from"./dav-C7ZXSSpl.chunk.mjs";const r=y().setApp("systemtags").detectUser().build(),V={userVisible:!0,userAssignable:!0,canAssign:!0},x=Object.freeze({"display-name":"displayName","user-visible":"userVisible","user-assignable":"userAssignable","can-assign":"canAssign"});function p(t){return t.map(({props:s})=>Object.fromEntries(Object.entries(s).map(([e,a])=>(e=x[e]??e,a=e==="displayName"?String(a):a,[e,a]))))}function w(t){const s=t.indexOf("?");s>0&&(t=t.substring(0,s));const e=t.split("/");let a;do a=e[e.length-1],e.pop();while(!a&&e.length>0);return Number(a)}function v(t){if("name"in t&&!("displayName"in t))return{...t};const s={...t};return s.name=s.displayName,delete s.displayName,s}function N(t){const s=t.attributes?.["system-tags"]?.["system-tag"];return s===void 0?[]:[s].flat().map(e=>typeof e=="string"?e:e.text)}function P(t,s){t.attributes["system-tags"]={"system-tag":s},c("files:node:updated",t)}const n=b(),l=`<?xml version="1.0"?>
<d:propfind xmlns:d="DAV:" xmlns:oc="http://owncloud.org/ns" xmlns:nc="http://nextcloud.org/ns">
<d:prop>
<oc:id />
@ -40,4 +40,4 @@ import{c as u}from"./index-IPON9qO1.chunk.mjs";import{g as y,e as c}from"./index
</d:prop>
</d:remove>
</d:propertyupdate>`),await n.customRequest(i,{method:"PROPPATCH",data:d,headers:{"if-match":a}})}async function H(t){const s=t?"1":"0",e=h("/apps/provisioning_api/api/v1/config/apps/{appId}/{key}",{appId:"systemtags",key:"restrict_creation_to_admin"});await f();const{data:a}=await u.post(e,{value:s});return a}export{_ as a,H as b,R as c,V as d,N as e,D as f,q as g,P as h,C as i,r as l,k as s,T as u};
//# sourceMappingURL=api-s1xKvR10.chunk.mjs.map
//# sourceMappingURL=api-ydRla5ss.chunk.mjs.map

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

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

File diff suppressed because one or more lines are too long

2
dist/index-dkOkc1OB.chunk.mjs vendored Normal file

File diff suppressed because one or more lines are too long

View file

@ -3,5 +3,5 @@ SPDX-FileCopyrightText: Nextcloud GmbH and Nextcloud contributors
This file is generated from multiple sources. Included packages:
- @nextcloud/password-confirmation
- version: 6.0.3
- version: 6.1.0
- license: MIT

1
dist/index-dkOkc1OB.chunk.mjs.map vendored Normal file

File diff suppressed because one or more lines are too long

View file

@ -3,5 +3,5 @@ SPDX-FileCopyrightText: Nextcloud GmbH and Nextcloud contributors
This file is generated from multiple sources. Included packages:
- @nextcloud/password-confirmation
- version: 6.0.3
- version: 6.1.0
- license: MIT

View file

@ -1,2 +1,2 @@
import{f as p,c as u,o as b,w as i,e as l,g as m,t as d,h as f}from"./runtime-dom.esm-bundler-CgYXkLV7.chunk.mjs";import{c as w}from"./index-IPON9qO1.chunk.mjs";import{a as g}from"./index-C1xmmKTZ-DHV8JZOG.chunk.mjs";import{a as S,l as c}from"./index-BgmsSgl5.chunk.mjs";import{t as h}from"./translation-DoG5ZELJ-XUrtIRvk.chunk.mjs";import{c as I}from"./index-BgRPS0vK.chunk.mjs";import{b as M}from"./createElementId-DhjFt1I9-D6sOOWeT.chunk.mjs";import{N as k}from"./NcCheckboxRadioSwitch-D0gFwEVl-DCiJhL6I.chunk.mjs";import{N}from"./ContentCopy-BDBVtVf4.chunk.mjs";import{g as R}from"./index-Bndk0DrU.chunk.mjs";import"./index-sH3U_332.chunk.mjs";import"./index-C493a1t-.chunk.mjs";import"./logger-D3RVzcfQ-88xHyoDn.chunk.mjs";import"./mdi-36VzJ0Uy.chunk.mjs";import"./NcNoteCard-CWiO3Dse-DJ5wV2Sw.chunk.mjs";import"./NcPasswordField-BOLzDHBJ-Cgi99HhR.chunk.mjs";import"./NcInputField-CPL-a_MM-6ClrUH-f.chunk.mjs";const T=R().detectLogLevel().setApp("sharebymail").build(),V={name:"AdminSettings",components:{NcCheckboxRadioSwitch:k,NcSettingsSection:N},setup(){return{t:h}},data(){return{sendPasswordMail:c("sharebymail","sendPasswordMail"),replyToInitiator:c("sharebymail","replyToInitiator")}},watch:{sendPasswordMail(e){this.update("sendpasswordmail",e)},replyToInitiator(e){this.update("replyToInitiator",e)}},methods:{async update(e,a){await I();const s=M("/apps/provisioning_api/api/v1/config/apps/{appId}/{key}",{appId:"sharebymail",key:e}),o=a?"yes":"no";try{const{data:t}=await w.post(s,{value:o});this.handleResponse({status:t.ocs?.meta?.status})}catch(t){this.handleResponse({errorMessage:h("sharebymail","Unable to update share by mail config"),error:t})}},async handleResponse({status:e,errorMessage:a,error:s}){e!=="ok"&&(g(a),T.error(a,{error:s}))}}};function v(e,a,s,o,t,x){const n=p("NcCheckboxRadioSwitch"),y=p("NcSettingsSection");return b(),u(y,{name:o.t("sharebymail","Share by mail"),description:o.t("sharebymail","Allows people to share a personalized link to a file or folder by putting in an email address.")},{default:i(()=>[l(n,{modelValue:t.sendPasswordMail,"onUpdate:modelValue":a[0]||(a[0]=r=>t.sendPasswordMail=r),type:"switch"},{default:i(()=>[m(d(o.t("sharebymail","Send password by mail")),1)]),_:1},8,["modelValue"]),l(n,{modelValue:t.replyToInitiator,"onUpdate:modelValue":a[1]||(a[1]=r=>t.replyToInitiator=r),type:"switch"},{default:i(()=>[m(d(o.t("sharebymail","Reply to initiator")),1)]),_:1},8,["modelValue"])]),_:1},8,["name","description"])}const P=S(V,[["render",v]]),_=f(P);_.mount("#vue-admin-sharebymail");
import{f as p,c as u,o as b,w as i,e as l,g as m,t as d,h as f}from"./runtime-dom.esm-bundler-CgYXkLV7.chunk.mjs";import{c as w}from"./index-IPON9qO1.chunk.mjs";import{a as g}from"./index-C1xmmKTZ-DHV8JZOG.chunk.mjs";import{a as S,l as c}from"./index-BgmsSgl5.chunk.mjs";import{t as h}from"./translation-DoG5ZELJ-XUrtIRvk.chunk.mjs";import{c as I}from"./index-dkOkc1OB.chunk.mjs";import{b as M}from"./createElementId-DhjFt1I9-D6sOOWeT.chunk.mjs";import{N as k}from"./NcCheckboxRadioSwitch-D0gFwEVl-DCiJhL6I.chunk.mjs";import{N}from"./ContentCopy-BDBVtVf4.chunk.mjs";import{g as R}from"./index-Bndk0DrU.chunk.mjs";import"./index-sH3U_332.chunk.mjs";import"./index-C493a1t-.chunk.mjs";import"./logger-D3RVzcfQ-88xHyoDn.chunk.mjs";import"./mdi-36VzJ0Uy.chunk.mjs";import"./NcNoteCard-CWiO3Dse-DJ5wV2Sw.chunk.mjs";import"./NcPasswordField-BOLzDHBJ-Cgi99HhR.chunk.mjs";import"./NcInputField-CPL-a_MM-6ClrUH-f.chunk.mjs";const T=R().detectLogLevel().setApp("sharebymail").build(),V={name:"AdminSettings",components:{NcCheckboxRadioSwitch:k,NcSettingsSection:N},setup(){return{t:h}},data(){return{sendPasswordMail:c("sharebymail","sendPasswordMail"),replyToInitiator:c("sharebymail","replyToInitiator")}},watch:{sendPasswordMail(e){this.update("sendpasswordmail",e)},replyToInitiator(e){this.update("replyToInitiator",e)}},methods:{async update(e,a){await I();const s=M("/apps/provisioning_api/api/v1/config/apps/{appId}/{key}",{appId:"sharebymail",key:e}),o=a?"yes":"no";try{const{data:t}=await w.post(s,{value:o});this.handleResponse({status:t.ocs?.meta?.status})}catch(t){this.handleResponse({errorMessage:h("sharebymail","Unable to update share by mail config"),error:t})}},async handleResponse({status:e,errorMessage:a,error:s}){e!=="ok"&&(g(a),T.error(a,{error:s}))}}};function v(e,a,s,o,t,x){const n=p("NcCheckboxRadioSwitch"),y=p("NcSettingsSection");return b(),u(y,{name:o.t("sharebymail","Share by mail"),description:o.t("sharebymail","Allows people to share a personalized link to a file or folder by putting in an email address.")},{default:i(()=>[l(n,{modelValue:t.sendPasswordMail,"onUpdate:modelValue":a[0]||(a[0]=r=>t.sendPasswordMail=r),type:"switch"},{default:i(()=>[m(d(o.t("sharebymail","Send password by mail")),1)]),_:1},8,["modelValue"]),l(n,{modelValue:t.replyToInitiator,"onUpdate:modelValue":a[1]||(a[1]=r=>t.replyToInitiator=r),type:"switch"},{default:i(()=>[m(d(o.t("sharebymail","Reply to initiator")),1)]),_:1},8,["modelValue"])]),_:1},8,["name","description"])}const P=S(V,[["render",v]]),_=f(P);_.mount("#vue-admin-sharebymail");
//# sourceMappingURL=sharebymail-admin-settings.mjs.map

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1,5 +1,5 @@
/* extracted by css-entry-points-plugin */
@import './theming-theming-settings-personal-BGvZ2soH.chunk.css';
@import './theming-theming-settings-personal-Tw2nBJ_u.chunk.css';
@import './createElementId-DhjFt1I9-C_oBIsvc.chunk.css';
@import './logger-D3RVzcfQ-D7L4ZBkR.chunk.css';
@import './mdi-BYHcrfvW.chunk.css';

View file

@ -1 +0,0 @@
.theming__preview[data-v-13bf6aae]{--ratio: 16;position:relative;display:flex;justify-content:flex-start}.theming__preview[data-v-13bf6aae],.theming__preview[data-v-13bf6aae] *{-webkit-user-select:none;user-select:none}.theming__preview-image[data-v-13bf6aae]{flex-basis:calc(16px * var(--ratio));flex-shrink:0;height:calc(10px * var(--ratio));margin-inline-end:var(--gap);cursor:pointer;border-radius:var(--border-radius);background-repeat:no-repeat;background-position:top left;background-size:cover}.theming__preview-explanation[data-v-13bf6aae]{margin-bottom:10px}.theming__preview-description[data-v-13bf6aae]{display:flex;flex-direction:column}.theming__preview-description h3[data-v-13bf6aae]{font-weight:700;margin-bottom:0}.theming__preview-description label[data-v-13bf6aae]{padding:12px 0}.theming__preview-warning[data-v-13bf6aae]{background-color:var(--color-warning);color:var(--color-warning-text)}@media(max-width:682.6666666667px){.theming__preview[data-v-13bf6aae]{flex-direction:column}.theming__preview-image[data-v-13bf6aae]{margin:0}}._userSectionAppMenu__selector_1hkl7_2{margin-block:12px}._backgroundSelect_l1nhm_2{display:flex;flex-wrap:wrap;justify-content:center}._backgroundSelect_l1nhm_2 ._backgroundSelect__entry_l1nhm_7{display:flex;flex-direction:column;justify-content:center;align-items:center;overflow:hidden;height:96px;width:168px;margin:var(--default-grid-baseline);text-align:center;overflow-wrap:break-word;-webkit-hyphens:auto;hyphens:auto;border:2px solid var(--color-main-background);border-radius:var(--border-radius-large);background-position:center center;background-size:cover;--color-content: var(--color-background-plain-text)}._backgroundSelect_l1nhm_2 ._backgroundSelect__entry_l1nhm_7:hover,._backgroundSelect_l1nhm_2 ._backgroundSelect__entry_l1nhm_7:focus{outline:2px solid var(--color-main-text)!important;border-color:var(--color-main-background)!important}._backgroundSelect_l1nhm_2 ._backgroundSelect__entry_l1nhm_7>*{color:var(--color-content);opacity:1}._backgroundSelect_l1nhm_2 ._backgroundSelect__entryColor_l1nhm_38{background-color:var(--color-background-plain)}._backgroundSelect_l1nhm_2 ._backgroundSelect__entryFilePicker_l1nhm_42{--color-content: var(--color-main-text);background-color:var(--color-background-dark)}._backgroundSelect_l1nhm_2 ._backgroundSelect__entryFilePicker_l1nhm_42[aria-pressed=true]{--color-content: var(--color-background-plain-text);background-image:var(--image-background)}._backgroundSelect_l1nhm_2 ._backgroundSelect__entryDefault_l1nhm_52{background-image:linear-gradient(to bottom,#17171780,#17171780),var(--cf2ff408)}._userPrimaryColor_3oh6f_1{display:flex;flex-direction:row;flex-wrap:wrap;gap:12px}._userPrimaryColor_3oh6f_1 ._userPrimaryColor__trigger_3oh6f_8{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:8px;margin:0!important;background-color:var(--color-primary);color:var(--color-primary-text);height:96px;width:168px;overflow-wrap:break-word;-webkit-hyphens:auto;hyphens:auto;border:2px solid var(--color-main-background);border-radius:var(--border-radius-large)}._userPrimaryColor_3oh6f_1 ._userPrimaryColor__trigger_3oh6f_8:active{background-color:var(--color-primary-hover)!important}._userPrimaryColor_3oh6f_1 ._userPrimaryColor__trigger_3oh6f_8:hover,._userPrimaryColor_3oh6f_1 ._userPrimaryColor__trigger_3oh6f_8:focus,._userPrimaryColor_3oh6f_1 ._userPrimaryColor__trigger_3oh6f_8:focus-visible{border-color:var(--color-main-background)!important;outline:2px solid var(--color-main-text)!important}.theming p[data-v-50195b4f]{max-width:800px}.theming[data-v-50195b4f] a{font-weight:700}.theming[data-v-50195b4f] a:hover,.theming[data-v-50195b4f] a:focus{text-decoration:underline}.theming__preview-list[data-v-50195b4f]{--gap: 30px;display:grid;margin-top:var(--gap);column-gap:var(--gap);row-gap:var(--gap)}.background__grid[data-v-50195b4f]{margin-top:30px}@media(max-width:1440px){.theming__preview-list[data-v-50195b4f]{display:flex;flex-direction:column}}

View file

@ -0,0 +1 @@
.theming__preview[data-v-13bf6aae]{--ratio: 16;position:relative;display:flex;justify-content:flex-start}.theming__preview[data-v-13bf6aae],.theming__preview[data-v-13bf6aae] *{-webkit-user-select:none;user-select:none}.theming__preview-image[data-v-13bf6aae]{flex-basis:calc(16px * var(--ratio));flex-shrink:0;height:calc(10px * var(--ratio));margin-inline-end:var(--gap);cursor:pointer;border-radius:var(--border-radius);background-repeat:no-repeat;background-position:top left;background-size:cover}.theming__preview-explanation[data-v-13bf6aae]{margin-bottom:10px}.theming__preview-description[data-v-13bf6aae]{display:flex;flex-direction:column}.theming__preview-description h3[data-v-13bf6aae]{font-weight:700;margin-bottom:0}.theming__preview-description label[data-v-13bf6aae]{padding:12px 0}.theming__preview-warning[data-v-13bf6aae]{background-color:var(--color-warning);color:var(--color-warning-text)}@media(max-width:682.6666666667px){.theming__preview[data-v-13bf6aae]{flex-direction:column}.theming__preview-image[data-v-13bf6aae]{margin:0}}._userSectionAppMenu__selector_1hkl7_2{margin-block:12px}._backgroundSelect_l1nhm_2{display:flex;flex-wrap:wrap;justify-content:center}._backgroundSelect_l1nhm_2 ._backgroundSelect__entry_l1nhm_7{display:flex;flex-direction:column;justify-content:center;align-items:center;overflow:hidden;height:96px;width:168px;margin:var(--default-grid-baseline);text-align:center;overflow-wrap:break-word;hyphens:auto;border:2px solid var(--color-main-background);border-radius:var(--border-radius-large);background-position:center center;background-size:cover;--color-content: var(--color-background-plain-text)}._backgroundSelect_l1nhm_2 ._backgroundSelect__entry_l1nhm_7:hover,._backgroundSelect_l1nhm_2 ._backgroundSelect__entry_l1nhm_7:focus{outline:2px solid var(--color-main-text)!important;border-color:var(--color-main-background)!important}._backgroundSelect_l1nhm_2 ._backgroundSelect__entry_l1nhm_7>*{color:var(--color-content);opacity:1}._backgroundSelect_l1nhm_2 ._backgroundSelect__entryColor_l1nhm_38{background-color:var(--color-background-plain)}._backgroundSelect_l1nhm_2 ._backgroundSelect__entryFilePicker_l1nhm_42{--color-content: var(--color-main-text);background-color:var(--color-background-dark)}._backgroundSelect_l1nhm_2 ._backgroundSelect__entryFilePicker_l1nhm_42[aria-pressed=true]{--color-content: var(--color-background-plain-text);background-image:var(--image-background)}._backgroundSelect_l1nhm_2 ._backgroundSelect__entryDefault_l1nhm_52{background-image:linear-gradient(to bottom,#17171780,#17171780),var(--cf2ff408)}._userPrimaryColor_3oh6f_1{display:flex;flex-direction:row;flex-wrap:wrap;gap:12px}._userPrimaryColor_3oh6f_1 ._userPrimaryColor__trigger_3oh6f_8{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:8px;margin:0!important;background-color:var(--color-primary);color:var(--color-primary-text);height:96px;width:168px;overflow-wrap:break-word;hyphens:auto;border:2px solid var(--color-main-background);border-radius:var(--border-radius-large)}._userPrimaryColor_3oh6f_1 ._userPrimaryColor__trigger_3oh6f_8:active{background-color:var(--color-primary-hover)!important}._userPrimaryColor_3oh6f_1 ._userPrimaryColor__trigger_3oh6f_8:hover,._userPrimaryColor_3oh6f_1 ._userPrimaryColor__trigger_3oh6f_8:focus,._userPrimaryColor_3oh6f_1 ._userPrimaryColor__trigger_3oh6f_8:focus-visible{border-color:var(--color-main-background)!important;outline:2px solid var(--color-main-text)!important}.theming p[data-v-50195b4f]{max-width:800px}.theming[data-v-50195b4f] a{font-weight:700}.theming[data-v-50195b4f] a:hover,.theming[data-v-50195b4f] a:focus{text-decoration:underline}.theming__preview-list[data-v-50195b4f]{--gap: 30px;display:grid;margin-top:var(--gap);column-gap:var(--gap);row-gap:var(--gap)}.background__grid[data-v-50195b4f]{margin-top:30px}@media(max-width:1440px){.theming__preview-list[data-v-50195b4f]{display:flex;flex-direction:column}}

View file

@ -1,3 +1,3 @@
import{d as U,c as A}from"./pinia-DNqtMbGl.chunk.mjs";import{r as _,b as I,j as p,o as n,c as x,u as a,w as k,g as i,t as d,l as E,F as m,k as f,p as N,C as M,n as w,e as y,h as R}from"./runtime-dom.esm-bundler-CgYXkLV7.chunk.mjs";import{g as $,l as j,a as B}from"./index-BgmsSgl5.chunk.mjs";import{a as P}from"./index-C1xmmKTZ-DHV8JZOG.chunk.mjs";import{t as o}from"./translation-DoG5ZELJ-XUrtIRvk.chunk.mjs";import{c as F}from"./index-BgRPS0vK.chunk.mjs";import{N as g}from"./logger-D3RVzcfQ-88xHyoDn.chunk.mjs";import{N as G}from"./mdi-36VzJ0Uy.chunk.mjs";import{g as H}from"./index-Bndk0DrU.chunk.mjs";import{c as q}from"./index-IPON9qO1.chunk.mjs";import{g as z}from"./createElementId-DhjFt1I9-D6sOOWeT.chunk.mjs";import"./index-C493a1t-.chunk.mjs";import"./NcNoteCard-CWiO3Dse-DJ5wV2Sw.chunk.mjs";import"./NcPasswordField-BOLzDHBJ-Cgi99HhR.chunk.mjs";import"./NcInputField-CPL-a_MM-6ClrUH-f.chunk.mjs";import"./index-sH3U_332.chunk.mjs";const D=H().detectLogLevel().setApp("twofactor_backupcodes").build();function J(r){const c=$().theming.name||"Nextcloud",e=window.open("",o("twofactor_backupcodes","{name} backup codes",{name:c}));if(!e)throw P(o("twofactor_backupcodes","Unable to open a new tab for printing")),new Error("Unable to open a new tab for printing");const t=e.document.createElement("h1");t.textContent=o("twofactor_backupcodes","{name} backup codes",{name:c});const s=e.document.createElement("pre");for(const b of r){const u=e.document.createTextNode(b);s.appendChild(u),s.appendChild(e.document.createElement("br"))}e.document.body.innerHTML="",e.document.body.appendChild(t),e.document.body.appendChild(s),e.print(),e.close()}async function K(){const r=z("/apps/twofactor_backupcodes/settings/create"),{data:c}=await q.post(r);return c}const v=j("twofactor_backupcodes","state"),O=U("twofactor_backupcodes",()=>{const r=_(v.enabled),c=_(v.total),e=_(v.used),t=_([]);async function s(){r.value=!1;const{codes:b,state:u}=await K();r.value=u.enabled,c.value=u.total,e.value=u.used,t.value=b}return{enabled:r,total:c,used:e,codes:t,generate:s}}),Q=["aria-label"],V=I({__name:"PersonalSettings",setup(r){const c=$().theming.name??"Nextcloud",e=O(),t=_(!1),s=N(()=>e.codes&&e.codes.length>0),b=c+"-backup-codes.txt",u=N(()=>s.value?"data:text/plain,"+encodeURIComponent(e.codes.reduce((l,C)=>l+C+`
import{d as U,c as A}from"./pinia-DNqtMbGl.chunk.mjs";import{r as _,b as I,j as p,o as n,c as x,u as a,w as k,g as i,t as d,l as E,F as m,k as f,p as N,C as M,n as w,e as y,h as R}from"./runtime-dom.esm-bundler-CgYXkLV7.chunk.mjs";import{g as $,l as j,a as B}from"./index-BgmsSgl5.chunk.mjs";import{a as P}from"./index-C1xmmKTZ-DHV8JZOG.chunk.mjs";import{t as o}from"./translation-DoG5ZELJ-XUrtIRvk.chunk.mjs";import{c as F}from"./index-dkOkc1OB.chunk.mjs";import{N as g}from"./logger-D3RVzcfQ-88xHyoDn.chunk.mjs";import{N as G}from"./mdi-36VzJ0Uy.chunk.mjs";import{g as H}from"./index-Bndk0DrU.chunk.mjs";import{c as q}from"./index-IPON9qO1.chunk.mjs";import{g as z}from"./createElementId-DhjFt1I9-D6sOOWeT.chunk.mjs";import"./index-C493a1t-.chunk.mjs";import"./NcNoteCard-CWiO3Dse-DJ5wV2Sw.chunk.mjs";import"./NcPasswordField-BOLzDHBJ-Cgi99HhR.chunk.mjs";import"./NcInputField-CPL-a_MM-6ClrUH-f.chunk.mjs";import"./index-sH3U_332.chunk.mjs";const D=H().detectLogLevel().setApp("twofactor_backupcodes").build();function J(r){const c=$().theming.name||"Nextcloud",e=window.open("",o("twofactor_backupcodes","{name} backup codes",{name:c}));if(!e)throw P(o("twofactor_backupcodes","Unable to open a new tab for printing")),new Error("Unable to open a new tab for printing");const t=e.document.createElement("h1");t.textContent=o("twofactor_backupcodes","{name} backup codes",{name:c});const s=e.document.createElement("pre");for(const b of r){const u=e.document.createTextNode(b);s.appendChild(u),s.appendChild(e.document.createElement("br"))}e.document.body.innerHTML="",e.document.body.appendChild(t),e.document.body.appendChild(s),e.print(),e.close()}async function K(){const r=z("/apps/twofactor_backupcodes/settings/create"),{data:c}=await q.post(r);return c}const v=j("twofactor_backupcodes","state"),O=U("twofactor_backupcodes",()=>{const r=_(v.enabled),c=_(v.total),e=_(v.used),t=_([]);async function s(){r.value=!1;const{codes:b,state:u}=await K();r.value=u.enabled,c.value=u.total,e.value=u.used,t.value=b}return{enabled:r,total:c,used:e,codes:t,generate:s}}),Q=["aria-label"],V=I({__name:"PersonalSettings",setup(r){const c=$().theming.name??"Nextcloud",e=O(),t=_(!1),s=N(()=>e.codes&&e.codes.length>0),b=c+"-backup-codes.txt",u=N(()=>s.value?"data:text/plain,"+encodeURIComponent(e.codes.reduce((l,C)=>l+C+`
`,"")):"");async function h(){await F(),t.value=!0;try{await e.generate()}catch(l){D.error("Error generating backup codes",{error:l}),P(o("twofactor_backupcodes","An error occurred while generating your backup codes"))}finally{t.value=!1}}function T(){J(!e.codes||e.codes.length===0?[]:e.codes)}return(l,C)=>(n(),p("div",{class:w(l.$style.backupcodesSettings)},[a(e).enabled?(n(),p(m,{key:1},[f("p",null,[s.value?(n(),p(m,{key:1},[i(d(a(o)("twofactor_backupcodes","These are your backup codes. Please save and/or print them as you will not be able to read the codes again later."))+" ",1),f("ul",{"aria-label":a(o)("twofactor_backupcodes","List of backup codes")},[(n(!0),p(m,null,M(a(e).codes,S=>(n(),p("li",{key:S,class:w(l.$style.backupcodesSettings__code)},d(S),3))),128))],8,Q)],64)):(n(),p(m,{key:0},[i(d(a(o)("twofactor_backupcodes","Backup codes have been generated. {used} of {total} codes have been used.",{used:a(e).used,total:a(e).total})),1)],64))]),f("p",{class:w(l.$style.backupcodesSettings__actions)},[y(a(g),{id:"generate-backup-codes",variant:"error",onClick:h},{default:k(()=>[i(d(a(o)("twofactor_backupcodes","Regenerate backup codes")),1)]),_:1}),s.value?(n(),p(m,{key:0},[y(a(g),{onClick:T},{default:k(()=>[i(d(a(o)("twofactor_backupcodes","Print backup codes")),1)]),_:1}),y(a(g),{href:u.value,download:b,variant:"primary"},{default:k(()=>[i(d(a(o)("twofactor_backupcodes","Save backup codes")),1)]),_:1},8,["href"])],64)):E("",!0)],2),f("p",null,[f("em",null,d(a(o)("twofactor_backupcodes","If you regenerate backup codes, you automatically invalidate old codes.")),1)])],64)):(n(),x(a(g),{key:0,disabled:t.value,variant:"primary",onClick:h},{icon:k(()=>[t.value?(n(),x(a(G),{key:0})):E("",!0)]),default:k(()=>[i(" "+d(a(o)("twofactor_backupcodes","Generate backup codes")),1)]),_:1},8,["disabled"]))],2))}}),W="_backupcodesSettings_bnkw8_2",X="_backupcodesSettings__code_bnkw8_7",Y="_backupcodesSettings__actions_bnkw8_13",Z={backupcodesSettings:W,backupcodesSettings__code:X,backupcodesSettings__actions:Y},ee={$style:Z},ae=B(V,[["__cssModules",ee]]),oe=A(),L=R(ae);L.use(oe),L.mount("#twofactor-backupcodes-settings");
//# sourceMappingURL=twofactor_backupcodes-settings-personal.mjs.map

12
package-lock.json generated
View file

@ -22,7 +22,7 @@
"@nextcloud/initial-state": "^3.0.0",
"@nextcloud/l10n": "^3.4.1",
"@nextcloud/logger": "^3.0.3",
"@nextcloud/password-confirmation": "^6.0.3",
"@nextcloud/password-confirmation": "^6.1.0",
"@nextcloud/paths": "^3.1.0",
"@nextcloud/router": "^3.1.0",
"@nextcloud/sharing": "^0.4.0",
@ -2476,9 +2476,9 @@
}
},
"node_modules/@nextcloud/password-confirmation": {
"version": "6.0.3",
"resolved": "https://registry.npmjs.org/@nextcloud/password-confirmation/-/password-confirmation-6.0.3.tgz",
"integrity": "sha512-tgbzwfhlXXd9Eq8ZnYrTeH8bEkdyIgybN45Tkip01b3xABUlr0tMGGj8+ZNp2pozytcK+k1l6fyvRPc09g0rIw==",
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/@nextcloud/password-confirmation/-/password-confirmation-6.1.0.tgz",
"integrity": "sha512-N2ChXDbPcUcQCoAjj1yc65zfc61yiKpdM3qm/y3Y/y//NG7XWNNINwBg85lqJ2SISgmVStpsQ1d0blpFCoQXkQ==",
"license": "MIT",
"dependencies": {
"@nextcloud/auth": "^2.5.3",
@ -2486,8 +2486,8 @@
"@nextcloud/l10n": "^3.4.1",
"@nextcloud/logger": "^3.0.3",
"@nextcloud/router": "^3.1.0",
"@nextcloud/vue": "^9.5.0",
"vue": "^3.5.29"
"@nextcloud/vue": "^9.6.0",
"vue": "^3.5.30"
},
"engines": {
"node": "^20.0.0 || ^22.0.0 || ^24.0.0"

View file

@ -51,7 +51,7 @@
"@nextcloud/initial-state": "^3.0.0",
"@nextcloud/l10n": "^3.4.1",
"@nextcloud/logger": "^3.0.3",
"@nextcloud/password-confirmation": "^6.0.3",
"@nextcloud/password-confirmation": "^6.1.0",
"@nextcloud/paths": "^3.1.0",
"@nextcloud/router": "^3.1.0",
"@nextcloud/sharing": "^0.4.0",