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)" />
<p class="file-name" :title="item.name">{{ item.name }}</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 class="transfer-area">
@@ -73,6 +73,7 @@
</div>
</div>
<div
v-if="canUpload"
class="upload-area"
:class="{ 'upload-area-drag': uploadAreaDrag }"
@dragover.prevent="uploadAreaDrag = true"
@@ -281,6 +282,14 @@
export default class extends Vue {
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() {
return this.$accessor.files.cwd
}
+11 -1
View File
@@ -94,9 +94,19 @@
},
})
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() {
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
/////////////////////////////
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.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 {
cwd: string
user_download: boolean
user_upload: boolean
files: FileListItem[]
}
+18
View File
@@ -7,6 +7,8 @@ export const state = () => ({
cwd: '',
files: [] as FileListItem[],
transfers: [] as FileTransfer[],
userDownload: false,
userUpload: false,
})
export const getters = getterTree(state, {
@@ -22,6 +24,14 @@ export const mutations = mutationTree(state, {
state.files = files
},
_setUserDownload(state, val: boolean) {
state.userDownload = val
},
_setUserUpload(state, val: boolean) {
state.userUpload = val
},
_addTransfer(state, transfer: FileTransfer) {
state.transfers = [...state.transfers, transfer]
},
@@ -42,6 +52,14 @@ export const actions = actionTree(
accessor.files._setFileList(files)
},
setUserDownload(store, val: boolean) {
accessor.files._setUserDownload(val)
},
setUserUpload(store, val: boolean) {
accessor.files._setUserUpload(val)
},
addTransfer(store, transfer: FileTransfer) {
if (transfer.status !== 'pending') {
return
@@ -109,9 +109,11 @@ type EmoteSend struct {
}
type FileTransferList struct {
Event string `json:"event"`
Cwd string `json:"cwd"`
Files []types.FileListItem `json:"files"`
Event string `json:"event"`
Cwd string `json:"cwd"`
UserDownload bool `json:"user_download"`
UserUpload bool `json:"user_upload"`
Files []types.FileListItem `json:"files"`
}
type Admin struct {
+5 -3
View File
@@ -607,9 +607,11 @@ func (s *session) wsToClient(msg []byte) error {
}
return s.toClient(&oldMessage.FileTransferList{
Event: oldEvent.FILETRANSFER_LIST,
Cwd: request.RootDir,
Files: files,
Event: oldEvent.FILETRANSFER_LIST,
Cwd: request.RootDir,
UserDownload: request.UserDownload,
UserUpload: request.UserUpload,
Files: files,
})
// Screen Events
@@ -103,9 +103,11 @@ func (m *Manager) broadcastUpdate() {
m.mu.RUnlock()
m.sessions.Broadcast(FILETRANSFER_UPDATE, Message{
Enabled: m.config.Enabled,
RootDir: m.config.RootDir,
Files: fileList,
Enabled: m.config.Enabled,
RootDir: m.config.RootDir,
UserDownload: m.config.UserDownload,
UserUpload: m.config.UserUpload,
Files: fileList,
})
}
@@ -115,9 +117,11 @@ func (m *Manager) sendUpdate(session types.Session) {
m.mu.RUnlock()
session.Send(FILETRANSFER_UPDATE, Message{
Enabled: m.config.Enabled,
RootDir: m.config.RootDir,
Files: fileList,
Enabled: m.config.Enabled,
RootDir: m.config.RootDir,
UserDownload: m.config.UserDownload,
UserUpload: m.config.UserUpload,
Files: fileList,
})
}
@@ -11,9 +11,11 @@ const (
)
type Message struct {
Enabled bool `json:"enabled"`
RootDir string `json:"root_dir"`
Files []Item `json:"files"`
Enabled bool `json:"enabled"`
RootDir string `json:"root_dir"`
UserDownload bool `json:"user_download"`
UserUpload bool `json:"user_upload"`
Files []Item `json:"files"`
}
type ItemType string