Skip to content

Commit e395cc8

Browse files
Merge pull request #50736 from nextcloud/backport/50680/stable31
[stable31] fix(files): only send config update requests if user is logged in
2 parents 8144ab6 + 9d665f6 commit e395cc8

9 files changed

+132
-133
lines changed

apps/files/src/eventbus.d.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ import type { IFileListFilter, Node } from '@nextcloud/files'
77
declare module '@nextcloud/event-bus' {
88
export interface NextcloudEvents {
99
// mapping of 'event name' => 'event type'
10-
'files:config:updated': { key: string, value: unknown }
10+
'files:config:updated': { key: string, value: boolean }
11+
'files:view-config:updated': { key: string, value: string|number|boolean, view: string }
1112

1213
'files:favorites:removed': Node
1314
'files:favorites:added': Node

apps/files/src/store/userconfig.ts

+36-42
Original file line numberDiff line numberDiff line change
@@ -2,61 +2,55 @@
22
* SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
33
* SPDX-License-Identifier: AGPL-3.0-or-later
44
*/
5-
import type { UserConfig, UserConfigStore } from '../types'
6-
import { defineStore } from 'pinia'
5+
import type { UserConfig } from '../types'
6+
import { getCurrentUser } from '@nextcloud/auth'
77
import { emit, subscribe } from '@nextcloud/event-bus'
8-
import { generateUrl } from '@nextcloud/router'
98
import { loadState } from '@nextcloud/initial-state'
9+
import { generateUrl } from '@nextcloud/router'
10+
import { defineStore } from 'pinia'
11+
import { ref, set } from 'vue'
1012
import axios from '@nextcloud/axios'
11-
import Vue from 'vue'
1213

13-
const userConfig = loadState<UserConfig>('files', 'config', {
14+
const initialUserConfig = loadState<UserConfig>('files', 'config', {
1415
show_hidden: false,
1516
crop_image_previews: true,
1617
sort_favorites_first: true,
1718
sort_folders_first: true,
1819
grid_view: false,
1920
})
2021

21-
export const useUserConfigStore = function(...args) {
22-
const store = defineStore('userconfig', {
23-
state: () => ({
24-
userConfig,
25-
} as UserConfigStore),
22+
export const useUserConfigStore = defineStore('userconfig', () => {
23+
const userConfig = ref<UserConfig>({ ...initialUserConfig })
2624

27-
actions: {
28-
/**
29-
* Update the user config local store
30-
* @param key
31-
* @param value
32-
*/
33-
onUpdate(key: string, value: boolean) {
34-
Vue.set(this.userConfig, key, value)
35-
},
25+
/**
26+
* Update the user config local store
27+
* @param key The config key
28+
* @param value The new value
29+
*/
30+
function onUpdate(key: string, value: boolean): void {
31+
set(userConfig.value, key, value)
32+
}
3633

37-
/**
38-
* Update the user config local store AND on server side
39-
* @param key
40-
* @param value
41-
*/
42-
async update(key: string, value: boolean) {
43-
await axios.put(generateUrl('/apps/files/api/v1/config/' + key), {
44-
value,
45-
})
46-
emit('files:config:updated', { key, value })
47-
},
48-
},
49-
})
34+
/**
35+
* Update the user config local store AND on server side
36+
* @param key The config key
37+
* @param value The new value
38+
*/
39+
async function update(key: string, value: boolean): Promise<void> {
40+
// only update if a user is logged in (not the case for public shares)
41+
if (getCurrentUser() !== null) {
42+
await axios.put(generateUrl('/apps/files/api/v1/config/{key}', { key }), {
43+
value,
44+
})
45+
}
46+
emit('files:config:updated', { key, value })
47+
}
5048

51-
const userConfigStore = store(...args)
49+
// Register the event listener
50+
subscribe('files:config:updated', ({ key, value }) => onUpdate(key, value))
5251

53-
// Make sure we only register the listeners once
54-
if (!userConfigStore._initialized) {
55-
subscribe('files:config:updated', function({ key, value }: { key: string, value: boolean }) {
56-
userConfigStore.onUpdate(key, value)
57-
})
58-
userConfigStore._initialized = true
52+
return {
53+
userConfig,
54+
update,
5955
}
60-
61-
return userConfigStore
62-
}
56+
})

apps/files/src/store/viewConfig.ts

+75-75
Original file line numberDiff line numberDiff line change
@@ -2,95 +2,95 @@
22
* SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
33
* SPDX-License-Identifier: AGPL-3.0-or-later
44
*/
5-
import { defineStore } from 'pinia'
5+
import type { ViewConfigs, ViewId, ViewConfig } from '../types'
6+
7+
import { getCurrentUser } from '@nextcloud/auth'
68
import { emit, subscribe } from '@nextcloud/event-bus'
7-
import { generateUrl } from '@nextcloud/router'
89
import { loadState } from '@nextcloud/initial-state'
10+
import { generateUrl } from '@nextcloud/router'
11+
import { defineStore } from 'pinia'
12+
import { ref, set } from 'vue'
913
import axios from '@nextcloud/axios'
10-
import Vue from 'vue'
1114

12-
import type { ViewConfigs, ViewConfigStore, ViewId, ViewConfig } from '../types'
15+
const initialViewConfig = loadState('files', 'viewConfigs', {}) as ViewConfigs
1316

14-
const viewConfig = loadState('files', 'viewConfigs', {}) as ViewConfigs
17+
export const useViewConfigStore = defineStore('viewconfig', () => {
1518

16-
export const useViewConfigStore = function(...args) {
17-
const store = defineStore('viewconfig', {
18-
state: () => ({
19-
viewConfig,
20-
} as ViewConfigStore),
19+
const viewConfigs = ref({ ...initialViewConfig })
2120

22-
getters: {
23-
getConfig: (state) => (view: ViewId): ViewConfig => state.viewConfig[view] || {},
21+
/**
22+
* Get the config for a specific view
23+
* @param viewid Id of the view to fet the config for
24+
*/
25+
function getConfig(viewid: ViewId): ViewConfig {
26+
return viewConfigs.value[viewid] || {}
27+
}
2428

25-
getConfigs: (state) => (): ViewConfigs => state.viewConfig,
26-
},
29+
/**
30+
* Update the view config local store
31+
* @param viewId The id of the view to update
32+
* @param key The config key to update
33+
* @param value The new value
34+
*/
35+
function onUpdate(viewId: ViewId, key: string, value: string | number | boolean): void {
36+
if (!(viewId in viewConfigs.value)) {
37+
set(viewConfigs.value, viewId, {})
38+
}
39+
set(viewConfigs.value[viewId], key, value)
40+
}
2741

28-
actions: {
29-
/**
30-
* Update the view config local store
31-
* @param view
32-
* @param key
33-
* @param value
34-
*/
35-
onUpdate(view: ViewId, key: string, value: string | number | boolean) {
36-
if (!this.viewConfig[view]) {
37-
Vue.set(this.viewConfig, view, {})
38-
}
39-
Vue.set(this.viewConfig[view], key, value)
40-
},
42+
/**
43+
* Update the view config local store AND on server side
44+
* @param view Id of the view to update
45+
* @param key Config key to update
46+
* @param value New value
47+
*/
48+
async function update(view: ViewId, key: string, value: string | number | boolean): Promise<void> {
49+
if (getCurrentUser() !== null) {
50+
await axios.put(generateUrl('/apps/files/api/v1/views'), {
51+
value,
52+
view,
53+
key,
54+
})
55+
}
4156

42-
/**
43-
* Update the view config local store AND on server side
44-
* @param view
45-
* @param key
46-
* @param value
47-
*/
48-
async update(view: ViewId, key: string, value: string | number | boolean) {
49-
axios.put(generateUrl('/apps/files/api/v1/views'), {
50-
value,
51-
view,
52-
key,
53-
})
57+
emit('files:view-config:updated', { view, key, value })
58+
}
5459

55-
emit('files:viewconfig:updated', { view, key, value })
56-
},
60+
/**
61+
* Set the sorting key AND sort by ASC
62+
* The key param must be a valid key of a File object
63+
* If not found, will be searched within the File attributes
64+
* @param key Key to sort by
65+
* @param view View to set the sorting key for
66+
*/
67+
function setSortingBy(key = 'basename', view = 'files'): void {
68+
// Save new config
69+
update(view, 'sorting_mode', key)
70+
update(view, 'sorting_direction', 'asc')
71+
}
5772

58-
/**
59-
* Set the sorting key AND sort by ASC
60-
* The key param must be a valid key of a File object
61-
* If not found, will be searched within the File attributes
62-
* @param key Key to sort by
63-
* @param view View to set the sorting key for
64-
*/
65-
setSortingBy(key = 'basename', view = 'files') {
66-
// Save new config
67-
this.update(view, 'sorting_mode', key)
68-
this.update(view, 'sorting_direction', 'asc')
69-
},
73+
/**
74+
* Toggle the sorting direction
75+
* @param viewId id of the view to set the sorting order for
76+
*/
77+
function toggleSortingDirection(viewId = 'files'): void {
78+
const config = viewConfigs.value[viewId] || { sorting_direction: 'asc' }
79+
const newDirection = config.sorting_direction === 'asc' ? 'desc' : 'asc'
7080

71-
/**
72-
* Toggle the sorting direction
73-
* @param view view to set the sorting order for
74-
*/
75-
toggleSortingDirection(view = 'files') {
76-
const config = this.getConfig(view) || { sorting_direction: 'asc' }
77-
const newDirection = config.sorting_direction === 'asc' ? 'desc' : 'asc'
81+
// Save new config
82+
update(viewId, 'sorting_direction', newDirection)
83+
}
7884

79-
// Save new config
80-
this.update(view, 'sorting_direction', newDirection)
81-
},
82-
},
83-
})
85+
// Initialize event listener
86+
subscribe('files:view-config:updated', ({ view, key, value }) => onUpdate(view, key, value))
8487

85-
const viewConfigStore = store(...args)
88+
return {
89+
viewConfigs,
8690

87-
// Make sure we only register the listeners once
88-
if (!viewConfigStore._initialized) {
89-
subscribe('files:viewconfig:updated', function({ view, key, value }: { view: ViewId, key: string, value: boolean }) {
90-
viewConfigStore.onUpdate(view, key, value)
91-
})
92-
viewConfigStore._initialized = true
91+
getConfig,
92+
setSortingBy,
93+
toggleSortingDirection,
94+
update,
9395
}
94-
95-
return viewConfigStore
96-
}
96+
})

apps/files/src/types.ts

+7-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,13 @@ export interface PathOptions {
5050

5151
// User config store
5252
export interface UserConfig {
53-
[key: string]: boolean
53+
[key: string]: boolean|undefined
54+
55+
show_hidden: boolean
56+
crop_image_previews: boolean
57+
sort_favorites_first: boolean
58+
sort_folders_first: boolean
59+
grid_view: boolean
5460
}
5561
export interface UserConfigStore {
5662
userConfig: UserConfig

apps/files/src/views/Navigation.vue

+6-8
Original file line numberDiff line numberDiff line change
@@ -159,14 +159,12 @@ export default defineComponent({
159159

160160
methods: {
161161
async loadExpandedViews() {
162-
const viewConfigs = this.viewConfigStore.getConfigs()
163-
const viewsToLoad: View[] = (Object.entries(viewConfigs) as Array<[string, ViewConfig]>)
164-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
165-
.filter(([viewId, config]) => config.expanded === true)
166-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
167-
.map(([viewId, config]) => this.views.find(view => view.id === viewId))
168-
.filter(Boolean) // Only registered views
169-
.filter(view => view.loadChildViews && !view.loaded)
162+
const viewsToLoad: View[] = (Object.entries(this.viewConfigStore.viewConfigs) as Array<[string, ViewConfig]>)
163+
.filter(([, config]) => config.expanded === true)
164+
.map(([viewId]) => this.views.find(view => view.id === viewId))
165+
// eslint-disable-next-line no-use-before-define
166+
.filter(Boolean as unknown as ((u: unknown) => u is View))
167+
.filter((view) => view.loadChildViews && !view.loaded)
170168
for (const view of viewsToLoad) {
171169
await view.loadChildViews(view)
172170
}

dist/files-init.js

+2-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/files-init.js.map

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/files-main.js

+2-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/files-main.js.map

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)