Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[full-ci] Access denied page change message / load common theme #9263

Merged
merged 10 commits into from
Jun 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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