Skip to content

Commit

Permalink
[full-ci] Access denied page change message / load common theme (#9263)
Browse files Browse the repository at this point in the history
* Load common theme into store

* Implement url in access denied page

* Fix add return

* Add changelog

* Update/add unittests

* Update config.spec.ts

* Fix typo

* Rename accessDeniedHelpUrl

* Fix acceptance tests, remove dev leftover

* Rename more to readmore
  • Loading branch information
lookacat authored Jun 23, 2023
1 parent 5dcfd4c commit 5a46341
Show file tree
Hide file tree
Showing 9 changed files with 71 additions and 31 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Enhancement: Access denied page update message

We've updated the access denied page message to be more specific and give the user a link to a help page.

https://github.com/owncloud/web/pull/9263
https://github.com/owncloud/web/issues/9051
6 changes: 3 additions & 3 deletions packages/web-runtime/src/container/bootstrap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -217,13 +217,13 @@ export const announceTheme = async ({
designSystem: any
runtimeConfiguration?: RuntimeConfiguration
}): Promise<void> => {
const { theme } = await loadTheme(runtimeConfiguration?.theme)
await store.dispatch('loadThemes', { theme })
const { web, common } = await loadTheme(runtimeConfiguration?.theme)
await store.dispatch('loadThemes', { theme: web, common })
const currentThemeName = useLocalStorage('oc_currentThemeName', null) // note: use null as default so that we can fall back to system preferences
if (unref(currentThemeName) === null) {
currentThemeName.value = useDefaultThemeName()
}
await store.dispatch('loadTheme', { theme: theme[unref(currentThemeName)] || theme.default })
await store.dispatch('loadTheme', { theme: web[unref(currentThemeName)] || web.default })

app.use(designSystem, {
tokens: store.getters.theme.designTokens
Expand Down
4 changes: 2 additions & 2 deletions packages/web-runtime/src/helpers/theme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import defaultTheme from '../../themes/owncloud/theme.json'
import { v4 as uuidV4 } from 'uuid'

export const loadTheme = async (location = '') => {
const defaults = { theme: defaultTheme.web || defaultTheme }
const defaults = { web: defaultTheme.web || defaultTheme, common: defaultTheme.common || {} }

if (location.split('.').pop() !== 'json') {
if (isEqual(process.env.NODE_ENV, 'development')) {
Expand All @@ -18,7 +18,7 @@ export const loadTheme = async (location = '') => {
return defaults
}
const theme = await response.json()
return { theme: theme.web || theme }
return { web: theme.web || theme, common: theme.common || {} }
} catch (e) {
console.error(
`Failed to load theme '${location}' is not a valid json file, using default theme.`
Expand Down
24 changes: 21 additions & 3 deletions packages/web-runtime/src/pages/accessDenied.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,14 @@
<div class="oc-login-card-body oc-width-medium">
<h2 class="oc-login-card-title" v-text="cardTitle" />
<p v-text="cardHint" />
<oc-button
v-if="accessDeniedHelpUrl"
type="a"
appearance="raw"
:href="accessDeniedHelpUrl"
target="_blank"
><span v-text="$gettext('Read more')"
/></oc-button>
</div>
<div class="oc-login-card-footer oc-pt-rm">
<p>
Expand Down Expand Up @@ -39,11 +47,20 @@ export default defineComponent({
const logoImg = computed(() => {
return store.getters.configuration.currentTheme.logo.login
})
const accessDeniedHelpUrl = computed(() => {
return (
store.getters.configuration.commonTheme.accessDeniedHelpUrl ||
store.getters.configuration.options.accessDeniedHelpUrl
)
})
const cardTitle = computed(() => {
return $gettext('Logged out')
return $gettext('Not logged in')
})
const cardHint = computed(() => {
return $gettext('You were automatically logged out for security reasons.')
return $gettext(
'This could be because of a routine safety log out, or because your account is either inactive or not yet authorized for use. Please try logging in after a while or seek help from your Administrator.'
)
})
const footerSlogan = computed(() => {
return store.getters.configuration.currentTheme.general.slogan
Expand All @@ -57,7 +74,8 @@ export default defineComponent({
cardTitle,
cardHint,
footerSlogan,
navigateToLoginText
navigateToLoginText,
accessDeniedHelpUrl
}
}
})
Expand Down
15 changes: 13 additions & 2 deletions packages/web-runtime/src/store/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@ const state = {
authority: ''
},
themes: [],
commonTheme: {
name: '',
solgan: '',
logo: '',
accessDeniedHelpUrl: ''
},
currentTheme: {
general: {
name: '',
Expand Down Expand Up @@ -58,7 +64,8 @@ const state = {
runningOnEos: false,
cernFeatures: false,
sharingRecipientsPerPage: 200,
contextHelpersReadMore: true
contextHelpersReadMore: true,
accessDeniedHelpUrl: ''
}
}

Expand All @@ -81,8 +88,9 @@ const actions = {
loadTheme(context, { theme }) {
context.commit('LOAD_THEME', theme)
},
loadThemes(context, { theme }) {
loadThemes(context, { theme, common }) {
context.commit('LOAD_THEMES', theme)
context.commit('LOAD_COMMON', common)
}
}

Expand All @@ -106,6 +114,9 @@ const mutations = {
},
LOAD_THEMES(state, theme) {
state.themes = theme
},
LOAD_COMMON(state, common) {
state.commonTheme = common
}
}

Expand Down
29 changes: 17 additions & 12 deletions packages/web-runtime/tests/unit/helpers/theme.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,41 +7,46 @@ jest.spyOn(console, 'error').mockImplementation(() => undefined)

describe('theme loading and error reporting', () => {
it('should load the default theme if location is empty', async () => {
const { theme } = await loadTheme()
expect(theme).toMatchObject(defaultTheme.web)
const { web, common } = await loadTheme()
expect(web).toMatchObject(defaultTheme.web)
expect(common).toMatchObject(defaultTheme.common)
})

it('should load the default theme if location is not a json file extension', async () => {
const { theme } = await loadTheme('some_location_without_json_file_ending.xml')
expect(theme).toMatchObject(defaultTheme.web)
const { web, common } = await loadTheme('some_location_without_json_file_ending.xml')
expect(web).toMatchObject(defaultTheme.web)
expect(common).toMatchObject(defaultTheme.common)
})

it('should load the default theme if location is not found', async () => {
fetchMock.mockResponse(new Error() as any, { status: 404 })
const { theme } = await loadTheme('http://www.owncloud.com/unknown.json')
expect(theme).toMatchObject(defaultTheme.web)
const { web, common } = await loadTheme('http://www.owncloud.com/unknown.json')
expect(web).toMatchObject(defaultTheme.web)
expect(common).toMatchObject(defaultTheme.common)
})

it('should load the default theme if location is not a valid json file', async () => {
const customTheme = merge({}, defaultTheme, { default: { logo: { login: 'custom.svg' } } })
fetchMock.mockResponse(JSON.stringify(customTheme) + '-invalid')
const { theme } = await loadTheme('http://www.owncloud.com/invalid.json')
expect(theme).toMatchObject(defaultTheme.web)
const { web, common } = await loadTheme('http://www.owncloud.com/invalid.json')
expect(web).toMatchObject(defaultTheme.web)
expect(common).toMatchObject(defaultTheme.common)
})

it('should load the default theme if server errors', async () => {
fetchMock.mockReject(new Error())
const { theme } = await loadTheme('http://www.owncloud.com')
expect(theme).toMatchObject(defaultTheme.web)
const { web, common } = await loadTheme('http://www.owncloud.com')
expect(web).toMatchObject(defaultTheme.web)
expect(common).toMatchObject(defaultTheme.common)
})

it('should load the custom theme if a custom location is given', async () => {
const customTheme = merge({}, defaultTheme.web, { default: { logo: { login: 'custom.svg' } } })

fetchMock.mockResponse(JSON.stringify(customTheme))

const { theme: theme1 } = await loadTheme('http://www.owncloud.com/custom.json')
const { theme: theme2 } = await loadTheme('/custom.json')
const { web: theme1 } = await loadTheme('http://www.owncloud.com/custom.json')
const { web: theme2 } = await loadTheme('/custom.json')

expect(theme1).toMatchObject(customTheme)
expect(theme2).toMatchObject(customTheme)
Expand Down
10 changes: 5 additions & 5 deletions packages/web-runtime/tests/unit/store/config.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,20 @@ import { cloneDeep } from 'lodash-es'
describe('config theme bootstrap', () => {
it('should be able to loadTheme', async () => {
const store = getStoreInstance(cloneDeep(Store))
const { theme } = await loadTheme()
const defaultTheme = theme.default
const { web } = await loadTheme()
const defaultTheme = web.default

await store.dispatch('loadTheme', { defaultTheme })
objectKeys(defaultTheme).forEach((k) => {
expect(get(store.getters.configuration.theme, k)).toBe(get(theme, k))
expect(get(store.getters.configuration.theme, k)).toBe(get(web, k))
})
})

it('should not overwrite keys that are not part of theme', async () => {
const store = getStoreInstance(cloneDeep(Store))
const initialStoreTheme = { ...store.getters.configuration.theme }
const { theme } = await loadTheme()
const defaultTheme = theme.default
const { web } = await loadTheme()
const defaultTheme = web.default

const storeThemeKeys = objectKeys(store.getters.configuration.currentTheme)
const loadedThemeKeys = objectKeys(defaultTheme)
Expand Down
6 changes: 3 additions & 3 deletions packages/web-runtime/themes/owncloud/theme.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
{
"common": {
"name": "ownCloud",
"slogan": "ownCloud – A safe home for all your data",
"logo": "themes/owncloud/assets/logo.svg"
"name": "ownCloud",
"slogan": "ownCloud – A safe home for all your data",
"logo": "themes/owncloud/assets/logo.svg"
},
"ios": {},
"web": {
Expand Down
2 changes: 1 addition & 1 deletion tests/acceptance/pageObjects/loginErrorPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ module.exports = {
body: 'body',
loginErrorMessage: {
locateStrategy: 'xpath',
selector: '//h2[text()="Logged out"]'
selector: '//h2[text()="Not logged in"]'
},
exitButton: {
selector: '#exitAnchor'
Expand Down

0 comments on commit 5a46341

Please sign in to comment.