Skip to content

Commit

Permalink
Merge pull request #11077 from owncloud/perf/token-renewal
Browse files Browse the repository at this point in the history
perf: reduce network load on token renewal
  • Loading branch information
JammingBen committed Jun 21, 2024
2 parents fd97db0 + b83aa5e commit c9c60b1
Show file tree
Hide file tree
Showing 9 changed files with 132 additions and 77 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Enhancement: Reduce network load on token renewal

We've reduced the network load on token renewal, resulting in better overall performance of the Web client and less token renewal failures on slow network connections.

https://github.com/owncloud/web/pull/11077
https://github.com/owncloud/web/issues/11069
3 changes: 2 additions & 1 deletion packages/design-system/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { getSizeClass } from './utils/sizeClasses'
import './utils/webFontLoader'
import { App } from 'vue'

import * as components from './components'
Expand All @@ -20,6 +19,8 @@ export const applyCustomProp = (key: string, value: string | undefined) => {

export default {
install(app: App, options: any = {}) {
import('./utils/webFontLoader')

const themeOptions = options.tokens
initializeCustomProps(themeOptions?.breakpoints, 'breakpoint-')
initializeCustomProps(themeOptions?.colorPalette, 'color-')
Expand Down
37 changes: 35 additions & 2 deletions packages/web-runtime/src/container/bootstrap.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { registerClient } from '../services/clientRegistration'
import { buildApplication, NextApplication } from './application'
import { RouteLocationRaw, Router, RouteRecordNormalized } from 'vue-router'
import { App, watch } from 'vue'
import { App, computed, watch } from 'vue'
import { loadTheme } from '../helpers/theme'
import { createGettext, GetTextOptions, Language, Translations } from 'vue3-gettext'
import { getBackendVersion, getWebVersion } from './versions'
Expand All @@ -28,7 +28,8 @@ import {
ResourcesStore,
SpacesStore,
MessageStore,
SharesStore
SharesStore,
ArchiverService
} from '@ownclouders/web-pkg'
import { authService } from '../services/auth'
import {
Expand Down Expand Up @@ -75,6 +76,7 @@ import {
} from './sse'
import { useWebWorkersStore, WebWorkersStore } from '@ownclouders/web-pkg'
import { loadAppTranslations } from '../helpers/language'
import { urlJoin } from '@ownclouders/web-client'

const getEmbedConfigFromQuery = (
doesEmbedEnabledOptionExists: boolean
Expand Down Expand Up @@ -416,6 +418,37 @@ export const announceClientService = ({
app.provide('$clientService', clientService)
}

export const announceArchiverService = ({
app,
configStore,
userStore,
capabilityStore
}: {
app: App
configStore: ConfigStore
userStore: UserStore
capabilityStore: CapabilityStore
}): void => {
app.config.globalProperties.$archiverService = new ArchiverService(
app.config.globalProperties.$clientService,
userStore,
configStore.serverUrl,
computed(
() =>
capabilityStore.filesArchivers || [
{
enabled: true,
version: '1.0.0',
formats: ['tar', 'zip'],
archiver_url: urlJoin(configStore.serverUrl, 'index.php/apps/files/ajax/download.php')
}
]
)
)

app.provide('$archiverService', app.config.globalProperties.$archiverService)
}

/**
* @param vue
*/
Expand Down
18 changes: 13 additions & 5 deletions packages/web-runtime/src/defaults/index.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import merge from 'lodash-es/merge'
import App from '../App.vue'
import TokenRenewal from '../pages/tokenRenewal.vue'
import missingOrInvalidConfigPage from '../pages/missingOrInvalidConfig.vue'

// fontawesome-free attributions console message
import '@fortawesome/fontawesome-free/attribution'

export { default as DesignSystem } from 'design-system'
export * from './languages'

export const pages = { success: App, failure: missingOrInvalidConfigPage }
export const pages = {
success: App,
failure: missingOrInvalidConfigPage,
tokenRenewal: TokenRenewal
}

export const loadTranslations = async () => {
const { coreTranslations, clientTranslations, pkgTranslations, odsTranslations } = await import(
Expand All @@ -17,3 +18,10 @@ export const loadTranslations = async () => {

return merge({}, coreTranslations, clientTranslations, pkgTranslations, odsTranslations)
}

export const loadDesignSystem = async () => {
// fontawesome-free attributions console message
import('@fortawesome/fontawesome-free/attribution')

return (await import('design-system')).default
}
1 change: 1 addition & 0 deletions packages/web-runtime/src/helpers/silentRedirect.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const isSilentRedirectRoute = () => window.location.pathname === '/web-oidc-silent-redirect'
122 changes: 56 additions & 66 deletions packages/web-runtime/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,4 @@
import {
DesignSystem as designSystem,
pages,
loadTranslations,
supportedLanguages
} from './defaults'
import { loadDesignSystem, pages, loadTranslations, supportedLanguages } from './defaults'
import { router } from './router'
import { PortalTarget } from '@ownclouders/web-pkg'
import { createHead } from '@vueuse/head'
Expand Down Expand Up @@ -31,7 +26,8 @@ import {
announcePasswordPolicyService,
registerSSEEventListeners,
setViewOptions,
announceGettext
announceGettext,
announceArchiverService
} from './container/bootstrap'
import { applicationStore } from './container/store'
import {
Expand All @@ -41,18 +37,20 @@ import {
PublicSpaceResource
} from '@ownclouders/web-client'
import { loadCustomTranslations } from 'web-runtime/src/helpers/customTranslations'
import { computed, createApp, watch } from 'vue'
import { createApp, watch } from 'vue'
import PortalVue, { createWormhole } from 'portal-vue'
import { createPinia } from 'pinia'
import Avatar from './components/Avatar.vue'
import focusMixin from './mixins/focusMixin'
import { ArchiverService } from '@ownclouders/web-pkg'
import { UnifiedRoleDefinition } from '@ownclouders/web-client/graph/generated'
import { extensionPoints } from './extensionPoints'
import { isSilentRedirectRoute } from './helpers/silentRedirect'

export const bootstrapApp = async (configurationPath: string, appsReadyCallback: () => void) => {
const isSilentRedirect = isSilentRedirectRoute()

const pinia = createPinia()
const app = createApp(pages.success)
const app = createApp(isSilentRedirect ? pages.tokenRenewal : pages.success)
app.use(pinia)

const {
Expand All @@ -74,65 +72,12 @@ export const bootstrapApp = async (configurationPath: string, appsReadyCallback:
app.provide('$router', router)

await announceConfiguration({ path: configurationPath, configStore })
startSentry(configStore, app)

app.use(abilitiesPlugin, createMongoAbility([]), { useGlobalProperties: true })

const gettext = announceGettext({ app, availableLanguages: supportedLanguages })

announceUppyService({ app })
announceClientService({ app, configStore, authStore })

// TODO: move to announceArchiverService function
app.config.globalProperties.$archiverService = new ArchiverService(
app.config.globalProperties.$clientService,
userStore,
configStore.serverUrl,
computed(
() =>
capabilityStore.filesArchivers || [
{
enabled: true,
version: '1.0.0',
formats: ['tar', 'zip'],
archiver_url: `${configStore.serverUrl}index.php/apps/files/ajax/download.php`
}
]
)
)
app.provide('$archiverService', app.config.globalProperties.$archiverService)
announceLoadingService({ app })
announcePreviewService({
app,
configStore,
userStore,
authStore,
capabilityStore
})
announcePasswordPolicyService({ app })
await announceClient(configStore)

app.config.globalProperties.$wormhole = createWormhole()
app.use(PortalVue, {
wormhole: app.config.globalProperties.$wormhole,
// do not register portal-target component so we can register our own wrapper
portalTargetName: false
})
app.component('PortalTarget', PortalTarget)

const applicationsPromise = initializeApplications({ app, configStore, router })
const translationsPromise = loadTranslations()
const customTranslationsPromise = loadCustomTranslations({ configStore })
const themePromise = announceTheme({ app, designSystem, configStore })
const [coreTranslations, customTranslations] = await Promise.all([
translationsPromise,
customTranslationsPromise,
applicationsPromise,
themePromise
])

announceTranslations({ appsStore, gettext, coreTranslations, customTranslations })

announceAuthService({
app,
configStore,
Expand All @@ -142,9 +87,49 @@ export const bootstrapApp = async (configurationPath: string, appsReadyCallback:
capabilityStore,
webWorkersStore
})
announceCustomStyles({ configStore })
announceCustomScripts({ configStore })
announceDefaults({ appsStore, router, extensionRegistry, configStore })

if (!isSilentRedirect) {
const designSystem = await loadDesignSystem()

announceUppyService({ app })
startSentry(configStore, app)
announceArchiverService({ app, configStore, userStore, capabilityStore })
announceLoadingService({ app })
announcePreviewService({
app,
configStore,
userStore,
authStore,
capabilityStore
})
announcePasswordPolicyService({ app })
await announceClient(configStore)

app.config.globalProperties.$wormhole = createWormhole()
app.use(PortalVue, {
wormhole: app.config.globalProperties.$wormhole,
// do not register portal-target component so we can register our own wrapper
portalTargetName: false
})
app.component('PortalTarget', PortalTarget)

const applicationsPromise = initializeApplications({ app, configStore, router })
const translationsPromise = loadTranslations()
const customTranslationsPromise = loadCustomTranslations({ configStore })
const themePromise = announceTheme({ app, designSystem, configStore })
const [coreTranslations, customTranslations] = await Promise.all([
translationsPromise,
customTranslationsPromise,
applicationsPromise,
themePromise
])

announceTranslations({ appsStore, gettext, coreTranslations, customTranslations })

announceCustomStyles({ configStore })
announceCustomScripts({ configStore })
announceDefaults({ appsStore, router, extensionRegistry, configStore })
}

app.use(router)
app.use(createHead())
Expand All @@ -154,6 +139,10 @@ export const bootstrapApp = async (configurationPath: string, appsReadyCallback:

app.mount('#owncloud')

if (isSilentRedirect) {
return
}

setViewOptions({ resourcesStore })

const applications = Array.from(applicationStore.values())
Expand Down Expand Up @@ -273,6 +262,7 @@ export const bootstrapErrorApp = async (err: Error): Promise<void> => {
const { capabilityStore, configStore } = announcePiniaStores()
announceVersions({ capabilityStore })
const app = createApp(pages.failure)
const designSystem = await loadDesignSystem()
await announceTheme({ app, designSystem, configStore })
console.error(err)
const translations = await loadTranslations()
Expand Down
4 changes: 2 additions & 2 deletions packages/web-runtime/src/pages/oidcCallback.vue
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ export default defineComponent({
const error = ref(false)
const footerSlogan = computed(() => currentTheme.value.common.slogan)
const logoImg = computed(() => currentTheme.value.logo.login)
const footerSlogan = computed(() => unref(currentTheme)?.common.slogan)
const logoImg = computed(() => unref(currentTheme)?.logo.login)
const route = useRoute()
Expand Down
13 changes: 13 additions & 0 deletions packages/web-runtime/src/pages/tokenRenewal.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<template>
<router-view />
</template>
<script lang="ts">
import { defineComponent } from 'vue'
/**
* This page gets rendered in the iFrame for the silent token renewal to take place.
*/
export default defineComponent({
name: 'TokenRenewal'
})
</script>
5 changes: 4 additions & 1 deletion packages/web-runtime/src/services/auth/authService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import { Ability } from '@ownclouders/web-client'
import { Language } from 'vue3-gettext'
import { PublicLinkType } from '@ownclouders/web-client'
import { WebWorkersStore } from '@ownclouders/web-pkg'
import { isSilentRedirectRoute } from '../../helpers/silentRedirect'

export class AuthService implements AuthServiceInterface {
private clientService: ClientService
Expand Down Expand Up @@ -109,7 +110,9 @@ export class AuthService implements AuthServiceInterface {
accessTokenExpiryThreshold: this.accessTokenExpiryThreshold
})

if (!this.tokenTimerWorker) {
// don't load worker in the silent redirect iframe
const isSilentRedirect = isSilentRedirectRoute()
if (!this.tokenTimerWorker && !isSilentRedirect) {
const { options } = this.configStore

if (!options.embed?.enabled || !options.embed?.delegateAuthentication) {
Expand Down

0 comments on commit c9c60b1

Please sign in to comment.