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

Preferences for not logged in users (public link context) #10207

Merged
merged 6 commits into from
Jan 15, 2024
Merged
Show file tree
Hide file tree
Changes from 5 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: Enable user preferences in public links

We've enabled user preferences in public links, so any user even without an account can open
preferences in a public link context and for example change the current language.

https://github.com/owncloud/web/pull/10207
8 changes: 7 additions & 1 deletion packages/web-app-admin-settings/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,13 @@ export default defineWebApplication({
isFileEditor: false,
applicationMenu: {
enabled: () => {
return userStore.user && can('read-all', 'Setting')
return (
userStore.user &&
(can('read-all', 'Setting') ||
can('read-all', 'Account') ||
can('read-all', 'Group') ||
can('read-all', 'Drive'))
)
},
priority: 40
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,11 @@ export default defineComponent({
})
})
const showWebDavDetails = computed(() => {
return store.getters['Files/areWebDavDetailsShown']
/**
* webDavPath might not be set when user is navigating on public link,
* even if the user is authenticated and the file owner.
*/
return store.getters['Files/areWebDavDetailsShown'] && unref(resource).webDavPath
})
const formatDateRelative = (date) => {
return formatRelativeDateFromJSDate(new Date(date), language.current)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,13 @@ export default defineComponent({
if (unref(resource)?.tags) {
selectedTags.value = unref(currentTags)
}
loadAvailableTagsTask.perform()

/**
* If the user can't edit the tags, for example on a public link, there is no need to load the available tags
*/
if (!unref(readonly)) {
loadAvailableTagsTask.perform()
}
})

const keydownMethods = (map, vm) => {
Expand Down
19 changes: 13 additions & 6 deletions packages/web-app-files/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,9 @@ const appInfo = {
icon: 'resource-type-folder',
color: 'var(--oc-color-swatch-primary-muted)',
isFileEditor: false,
extensions: [],
applicationMenu: {
enabled: () => true,
priority: 10
}
extensions: []
}

export const navItems = (context): AppNavigationItem[] => {
const spacesStores = useSpacesStore()
const userStore = useUserStore()
Expand Down Expand Up @@ -127,8 +124,18 @@ export const navItems = (context): AppNavigationItem[] => {

export default defineWebApplication({
setup() {
const userStore = useUserStore()

return {
appInfo,
appInfo: {
...appInfo,
applicationMenu: {
enabled: () => {
return !!userStore.user
},
priority: 10
}
},
store,
routes: buildRoutes({
App,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ describe('DriveResolver view', () => {
space,
internalSpace,
mocks: { $clientService: clientService },
isUserContextReady: true
userContextReady: true
})

await wrapper.vm.$nextTick()
Expand All @@ -94,7 +94,7 @@ describe('DriveResolver view', () => {
const { wrapper, mocks } = getMountedWrapper({
space,
mocks: { $clientService: clientService },
isUserContextReady: true
userContextReady: true
})

await wrapper.vm.$nextTick()
Expand All @@ -121,7 +121,7 @@ function getMountedWrapper({
space = undefined,
internalSpace = undefined,
currentRouteName = 'files-spaces-generic',
isUserContextReady = false,
userContextReady = false,
driveAliasAndItem = 'personal/einstein/file',
fileId = '1'
} = {}) {
Expand Down Expand Up @@ -157,7 +157,7 @@ function getMountedWrapper({
global: {
plugins: [
...defaultPlugins({
piniaOptions: { authState: { userContextReady: isUserContextReady } }
piniaOptions: { authState: { userContextReady: userContextReady } }
}),
store
],
Expand Down
10 changes: 8 additions & 2 deletions packages/web-app-ocm/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import App from './views/App.vue'
import { defineWebApplication, useRouter } from '@ownclouders/web-pkg'
import { defineWebApplication, useRouter, useUserStore } from '@ownclouders/web-pkg'
import translations from '../l10n/translations.json'
import { extensions } from './extensions'
import { RouteRecordRaw } from 'vue-router'
Expand Down Expand Up @@ -27,13 +27,19 @@ export default defineWebApplication({
setup() {
const { $gettext } = useGettext()
const router = useRouter()
const userStore = useUserStore()

const appInfo = {
name: $gettext('ScienceMesh'),
id: 'ocm',
color: '#AE291D',
icon: 'contacts-book',
isFileEditor: false
isFileEditor: false,
applicationMenu: {
enabled: () => {
return !!userStore.user
}
}
}

router.addRoute({
Expand Down
6 changes: 3 additions & 3 deletions packages/web-app-search/tests/unit/portals/SearchBar.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ describe('Search Bar portal component', () => {
expect(wrapper.find(selectors.search).exists()).toBeFalsy()
})
test('does not render a search field if no user given', () => {
wrapper = getMountedWrapper({ isUserContextReady: false }).wrapper
wrapper = getMountedWrapper({ userContextReady: false }).wrapper
expect(wrapper.find(selectors.search).exists()).toBeFalsy()
})
test('updates the search term on input', () => {
Expand Down Expand Up @@ -228,7 +228,7 @@ describe('Search Bar portal component', () => {

function getMountedWrapper({
mocks = {},
isUserContextReady = true,
userContextReady = true,
providers = [providerFiles, providerContacts]
} = {}) {
jest.mocked(useAvailableProviders).mockReturnValue(ref(providers))
Expand All @@ -253,7 +253,7 @@ function getMountedWrapper({
global: {
plugins: [
...defaultPlugins({
piniaOptions: { authState: { userContextReady: isUserContextReady } }
piniaOptions: { authState: { userContextReady: userContextReady } }
}),
store
],
Expand Down
2 changes: 1 addition & 1 deletion packages/web-pkg/src/apps/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ export interface ApplicationQuickAction {
export type AppConfigObject = Record<string, any>

export interface ApplicationMenuItem {
enabled?: () => boolean
enabled: () => boolean
priority?: number
openAsEditor?: boolean
}
Expand Down
2 changes: 1 addition & 1 deletion packages/web-pkg/src/composables/piniaStores/apps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export const useAppsStore = defineStore('apps', () => {
}

unref(apps)[appInfo.id] = {
applicationMenu: appInfo.applicationMenu || {},
applicationMenu: appInfo.applicationMenu || { enabled: () => false },
defaultExtension: appInfo.defaultExtension || '',
icon: 'check_box_outline_blank',
name: appInfo.name || appInfo.id,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -422,7 +422,7 @@ describe('ResourceTable', () => {
const resource = mockDeep<Resource>({ id: '1', tags: ['1'] })
const { wrapper } = getMountedWrapper({
props: { resources: [resource] },
isUserContextReady: false
userContextReady: false
})
const resourceRow = wrapper.find(`[data-item-id="${resource.id}"]`)
expect(resourceRow.find('.resource-table-tag-wrapper').element.tagName).toEqual('SPAN')
Expand Down Expand Up @@ -456,7 +456,7 @@ describe('ResourceTable', () => {

function getMountedWrapper({
props = {},
isUserContextReady = true,
userContextReady = true,
addProcessingResources = false
} = {}) {
const storeOptions = defaultStoreMockOptions
Expand Down Expand Up @@ -494,7 +494,7 @@ function getMountedWrapper({
plugins: [
...defaultPlugins({
piniaOptions: {
authState: { userContextReady: isUserContextReady },
authState: { userContextReady: userContextReady },
capabilityState: { capabilities }
}
}),
Expand Down
43 changes: 24 additions & 19 deletions packages/web-runtime/src/components/Topbar/TopBar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@
v-if="appMenuItems.length && !isEmbedModeEnabled"
:applications-list="appMenuItems"
/>
<router-link
ref="navigationSidebarLogo"
v-oc-tooltip="$gettext('Back to home')"
to="/"
class="oc-width-1-1"
>
<oc-img :src="currentTheme.logo.topbar" :alt="sidebarLogoAlt" class="oc-logo-image" />
<router-link ref="navigationSidebarLogo" :to="homeLink" class="oc-width-1-1">
<oc-img
v-oc-tooltip="$gettext('Back to home')"
:src="currentTheme.logo.topbar"
:alt="sidebarLogoAlt"
class="oc-logo-image"
/>
</router-link>
</div>
<div v-if="!contentOnLeftPortal" class="oc-topbar-center">
Expand Down Expand Up @@ -56,13 +56,11 @@ import {
useAuthStore,
useCapabilityStore,
useEmbedMode,
useExtensionRegistry,
useRouter,
useStore,
useThemeStore
} from '@ownclouders/web-pkg'
import { isRuntimeRoute } from '../../router'
import { getExtensionNavItems } from '../../helpers/navItems'

export default {
components: {
Expand All @@ -83,7 +81,6 @@ export default {
setup(props) {
const store = useStore()
const capabilityStore = useCapabilityStore()
const extensionRegistry = useExtensionRegistry()
const themeStore = useThemeStore()
const { currentTheme } = storeToRefs(themeStore)

Expand All @@ -100,6 +97,17 @@ export default {
)
})

const homeLink = computed(() => {
if (authStore.publicLinkContextReady && !authStore.userContextReady) {
return {
name: 'resolvePublicLink',
params: { token: authStore.publicLinkToken }
}
}

return '/'
})

const isSideBarToggleVisible = computed(() => {
return authStore.userContextReady || authStore.publicLinkContextReady
})
Expand All @@ -115,7 +123,7 @@ export default {
}

/**
* Returns well formed menuItem objects by a list of extensions.
* Returns well-formed menuItem objects by a list of extensions.
* The following properties must be accessible in the wrapping code:
* - applicationsList
* - $language
Expand All @@ -128,14 +136,10 @@ export default {
return props.applicationsList
.filter((app) => {
if (app.type === 'extension') {
// check if the extension has at least one navItem with a matching menuId
return (
getExtensionNavItems({ extensionRegistry, appId: app.id }).filter((navItem) =>
isNavItemPermitted(permittedMenus, navItem)
).length > 0 ||
(app.applicationMenu.enabled instanceof Function &&
app.applicationMenu.enabled(store, ability) &&
!permittedMenus.includes('user'))
app.applicationMenu.enabled instanceof Function &&
AlexAndBear marked this conversation as resolved.
Show resolved Hide resolved
app.applicationMenu.enabled(store, ability) &&
!permittedMenus.includes('user')
)
}
return isNavItemPermitted(permittedMenus, app)
Expand Down Expand Up @@ -209,7 +213,8 @@ export default {
logoWidth,
isEmbedModeEnabled,
isSideBarToggleVisible,
isSideBarToggleDisabled
isSideBarToggleDisabled,
homeLink
}
},
computed: {
Expand Down
Loading