fix(filetransfer): implement user permissions for file download and upload in client.

This commit is contained in:
Miroslav Šedivý
2026-08-05 18:45:17 +02:00
parent d0fb21d507
commit 27a31aaa75
9 changed files with 69 additions and 18 deletions
+10 -1
View File
@@ -9,7 +9,7 @@
<i :class="fileIcon(item)" /> <i :class="fileIcon(item)" />
<p class="file-name" :title="item.name">{{ item.name }}</p> <p class="file-name" :title="item.name">{{ item.name }}</p>
<p class="file-size">{{ fileSize(item.size) }}</p> <p class="file-size">{{ fileSize(item.size) }}</p>
<i v-if="item.type !== 'dir'" class="fas fa-download download" @click="download(item)" /> <i v-if="item.type !== 'dir' && canDownload" class="fas fa-download download" @click="download(item)" />
</div> </div>
</div> </div>
<div class="transfer-area"> <div class="transfer-area">
@@ -73,6 +73,7 @@
</div> </div>
</div> </div>
<div <div
v-if="canUpload"
class="upload-area" class="upload-area"
:class="{ 'upload-area-drag': uploadAreaDrag }" :class="{ 'upload-area-drag': uploadAreaDrag }"
@dragover.prevent="uploadAreaDrag = true" @dragover.prevent="uploadAreaDrag = true"
@@ -281,6 +282,14 @@
export default class extends Vue { export default class extends Vue {
public uploadAreaDrag: boolean = false public uploadAreaDrag: boolean = false
get canDownload() {
return this.$accessor.user.admin || this.$accessor.files.userDownload
}
get canUpload() {
return this.$accessor.user.admin || this.$accessor.files.userUpload
}
get cwd() { get cwd() {
return this.$accessor.files.cwd return this.$accessor.files.cwd
} }
+11 -1
View File
@@ -94,9 +94,19 @@
}, },
}) })
export default class extends Vue { export default class extends Vue {
get canDownload() {
return this.$accessor.user.admin || this.$accessor.files.userDownload
}
get canUpload() {
return this.$accessor.user.admin || this.$accessor.files.userUpload
}
get filetransferAllowed() { get filetransferAllowed() {
return ( return (
this.$accessor.remote.fileTransfer && (this.$accessor.user.admin || !this.$accessor.isLocked('file_transfer')) this.$accessor.remote.fileTransfer &&
(this.$accessor.user.admin || !this.$accessor.isLocked('file_transfer')) &&
(this.canDownload || this.canUpload)
) )
} }
+3 -1
View File
@@ -361,9 +361,11 @@ export class NekoClient extends BaseClient implements EventEmitter<NekoEvents> {
///////////////////////////// /////////////////////////////
// File Transfer Events // File Transfer Events
///////////////////////////// /////////////////////////////
protected [EVENT.FILETRANSFER.LIST]({ cwd, files }: FileTransferListPayload) { protected [EVENT.FILETRANSFER.LIST]({ cwd, user_download, user_upload, files }: FileTransferListPayload) {
this.$accessor.files.setCwd(cwd) this.$accessor.files.setCwd(cwd)
this.$accessor.files.setFileList(files) this.$accessor.files.setFileList(files)
this.$accessor.files.setUserDownload(user_download)
this.$accessor.files.setUserUpload(user_upload)
} }
///////////////////////////// /////////////////////////////
+2
View File
@@ -204,6 +204,8 @@ export interface FileTransferListMessage extends WebSocketMessage, FileTransferL
export interface FileTransferListPayload { export interface FileTransferListPayload {
cwd: string cwd: string
user_download: boolean
user_upload: boolean
files: FileListItem[] files: FileListItem[]
} }
+18
View File
@@ -7,6 +7,8 @@ export const state = () => ({
cwd: '', cwd: '',
files: [] as FileListItem[], files: [] as FileListItem[],
transfers: [] as FileTransfer[], transfers: [] as FileTransfer[],
userDownload: false,
userUpload: false,
}) })
export const getters = getterTree(state, { export const getters = getterTree(state, {
@@ -22,6 +24,14 @@ export const mutations = mutationTree(state, {
state.files = files state.files = files
}, },
_setUserDownload(state, val: boolean) {
state.userDownload = val
},
_setUserUpload(state, val: boolean) {
state.userUpload = val
},
_addTransfer(state, transfer: FileTransfer) { _addTransfer(state, transfer: FileTransfer) {
state.transfers = [...state.transfers, transfer] state.transfers = [...state.transfers, transfer]
}, },
@@ -42,6 +52,14 @@ export const actions = actionTree(
accessor.files._setFileList(files) accessor.files._setFileList(files)
}, },
setUserDownload(store, val: boolean) {
accessor.files._setUserDownload(val)
},
setUserUpload(store, val: boolean) {
accessor.files._setUserUpload(val)
},
addTransfer(store, transfer: FileTransfer) { addTransfer(store, transfer: FileTransfer) {
if (transfer.status !== 'pending') { if (transfer.status !== 'pending') {
return return
@@ -109,9 +109,11 @@ type EmoteSend struct {
} }
type FileTransferList struct { type FileTransferList struct {
Event string `json:"event"` Event string `json:"event"`
Cwd string `json:"cwd"` Cwd string `json:"cwd"`
Files []types.FileListItem `json:"files"` UserDownload bool `json:"user_download"`
UserUpload bool `json:"user_upload"`
Files []types.FileListItem `json:"files"`
} }
type Admin struct { type Admin struct {
+5 -3
View File
@@ -607,9 +607,11 @@ func (s *session) wsToClient(msg []byte) error {
} }
return s.toClient(&oldMessage.FileTransferList{ return s.toClient(&oldMessage.FileTransferList{
Event: oldEvent.FILETRANSFER_LIST, Event: oldEvent.FILETRANSFER_LIST,
Cwd: request.RootDir, Cwd: request.RootDir,
Files: files, UserDownload: request.UserDownload,
UserUpload: request.UserUpload,
Files: files,
}) })
// Screen Events // Screen Events
@@ -103,9 +103,11 @@ func (m *Manager) broadcastUpdate() {
m.mu.RUnlock() m.mu.RUnlock()
m.sessions.Broadcast(FILETRANSFER_UPDATE, Message{ m.sessions.Broadcast(FILETRANSFER_UPDATE, Message{
Enabled: m.config.Enabled, Enabled: m.config.Enabled,
RootDir: m.config.RootDir, RootDir: m.config.RootDir,
Files: fileList, UserDownload: m.config.UserDownload,
UserUpload: m.config.UserUpload,
Files: fileList,
}) })
} }
@@ -115,9 +117,11 @@ func (m *Manager) sendUpdate(session types.Session) {
m.mu.RUnlock() m.mu.RUnlock()
session.Send(FILETRANSFER_UPDATE, Message{ session.Send(FILETRANSFER_UPDATE, Message{
Enabled: m.config.Enabled, Enabled: m.config.Enabled,
RootDir: m.config.RootDir, RootDir: m.config.RootDir,
Files: fileList, UserDownload: m.config.UserDownload,
UserUpload: m.config.UserUpload,
Files: fileList,
}) })
} }
@@ -11,9 +11,11 @@ const (
) )
type Message struct { type Message struct {
Enabled bool `json:"enabled"` Enabled bool `json:"enabled"`
RootDir string `json:"root_dir"` RootDir string `json:"root_dir"`
Files []Item `json:"files"` UserDownload bool `json:"user_download"`
UserUpload bool `json:"user_upload"`
Files []Item `json:"files"`
} }
type ItemType string type ItemType string