fix: add input validation in filemanagers to prevent overwriting existing files (#1087)
This commit is contained in:
parent
e411175b7f
commit
3ec2ee2793
@ -374,12 +374,16 @@
|
|||||||
v-model="dialogCreateDirectory.name"
|
v-model="dialogCreateDirectory.name"
|
||||||
:label="$t('Files.Name')"
|
:label="$t('Files.Name')"
|
||||||
required
|
required
|
||||||
|
:rules="nameInputRules"
|
||||||
|
@update:error="isInvalidName = !isInvalidName"
|
||||||
@keypress.enter="createDirectoryAction"></v-text-field>
|
@keypress.enter="createDirectoryAction"></v-text-field>
|
||||||
</v-card-text>
|
</v-card-text>
|
||||||
<v-card-actions>
|
<v-card-actions>
|
||||||
<v-spacer></v-spacer>
|
<v-spacer></v-spacer>
|
||||||
<v-btn color="" text @click="dialogCreateDirectory.show = false">{{ $t('Files.Cancel') }}</v-btn>
|
<v-btn color="" text @click="dialogCreateDirectory.show = false">{{ $t('Files.Cancel') }}</v-btn>
|
||||||
<v-btn color="primary" text @click="createDirectoryAction">{{ $t('Files.Create') }}</v-btn>
|
<v-btn :disabled="isInvalidName" color="primary" text @click="createDirectoryAction">
|
||||||
|
{{ $t('Files.Create') }}
|
||||||
|
</v-btn>
|
||||||
</v-card-actions>
|
</v-card-actions>
|
||||||
</panel>
|
</panel>
|
||||||
</v-dialog>
|
</v-dialog>
|
||||||
@ -399,12 +403,16 @@
|
|||||||
v-model="dialogRenameFile.newName"
|
v-model="dialogRenameFile.newName"
|
||||||
:label="$t('Files.Name').toString()"
|
:label="$t('Files.Name').toString()"
|
||||||
required
|
required
|
||||||
|
:rules="nameInputRules"
|
||||||
|
@update:error="isInvalidName = !isInvalidName"
|
||||||
@keyup.enter="renameFileAction"></v-text-field>
|
@keyup.enter="renameFileAction"></v-text-field>
|
||||||
</v-card-text>
|
</v-card-text>
|
||||||
<v-card-actions>
|
<v-card-actions>
|
||||||
<v-spacer></v-spacer>
|
<v-spacer></v-spacer>
|
||||||
<v-btn color="" text @click="dialogRenameFile.show = false">{{ $t('Files.Cancel') }}</v-btn>
|
<v-btn color="" text @click="dialogRenameFile.show = false">{{ $t('Files.Cancel') }}</v-btn>
|
||||||
<v-btn color="primary" text @click="renameFileAction">{{ $t('Files.Rename') }}</v-btn>
|
<v-btn :disabled="isInvalidName" color="primary" text @click="renameFileAction">
|
||||||
|
{{ $t('Files.Rename') }}
|
||||||
|
</v-btn>
|
||||||
</v-card-actions>
|
</v-card-actions>
|
||||||
</panel>
|
</panel>
|
||||||
</v-dialog>
|
</v-dialog>
|
||||||
@ -424,12 +432,16 @@
|
|||||||
v-model="dialogRenameDirectory.newName"
|
v-model="dialogRenameDirectory.newName"
|
||||||
:label="$t('Files.Name')"
|
:label="$t('Files.Name')"
|
||||||
required
|
required
|
||||||
|
:rules="nameInputRules"
|
||||||
|
@update:error="isInvalidName = !isInvalidName"
|
||||||
@keyup.enter="renameDirectoryAction"></v-text-field>
|
@keyup.enter="renameDirectoryAction"></v-text-field>
|
||||||
</v-card-text>
|
</v-card-text>
|
||||||
<v-card-actions>
|
<v-card-actions>
|
||||||
<v-spacer></v-spacer>
|
<v-spacer></v-spacer>
|
||||||
<v-btn color="" text @click="dialogRenameDirectory.show = false">{{ $t('Files.Cancel') }}</v-btn>
|
<v-btn color="" text @click="dialogRenameDirectory.show = false">{{ $t('Files.Cancel') }}</v-btn>
|
||||||
<v-btn color="primary" text @click="renameDirectoryAction">{{ $t('Files.Rename') }}</v-btn>
|
<v-btn :disabled="isInvalidName" color="primary" text @click="renameDirectoryAction">
|
||||||
|
{{ $t('Files.Rename') }}
|
||||||
|
</v-btn>
|
||||||
</v-card-actions>
|
</v-card-actions>
|
||||||
</panel>
|
</panel>
|
||||||
</v-dialog>
|
</v-dialog>
|
||||||
@ -647,6 +659,16 @@ export default class GcodefilesPanel extends Mixins(BaseMixin, ControlMixin) {
|
|||||||
|
|
||||||
private deleteSelectedDialog = false
|
private deleteSelectedDialog = false
|
||||||
|
|
||||||
|
private isInvalidName = true
|
||||||
|
private nameInputRules = [
|
||||||
|
(value: string) => !!value || this.$t('Files.InvalidNameEmpty'),
|
||||||
|
(value: string) => !this.existsFilename(value) || this.$t('Files.InvalidNameAlreadyExists'),
|
||||||
|
]
|
||||||
|
|
||||||
|
existsFilename(name: string) {
|
||||||
|
return this.files.findIndex((file) => file.filename === name) >= 0
|
||||||
|
}
|
||||||
|
|
||||||
get currentPath() {
|
get currentPath() {
|
||||||
const path = this.$store.state.gui.view.gcodefiles.currentPath
|
const path = this.$store.state.gui.view.gcodefiles.currentPath
|
||||||
if (path === 'gcodes') return ''
|
if (path === 'gcodes') return ''
|
||||||
|
@ -277,6 +277,8 @@
|
|||||||
v-model="dialogCreateFile.name"
|
v-model="dialogCreateFile.name"
|
||||||
:label="$t('Machine.ConfigFilesPanel.Name')"
|
:label="$t('Machine.ConfigFilesPanel.Name')"
|
||||||
required
|
required
|
||||||
|
:rules="nameInputRules"
|
||||||
|
@update:error="isInvalidName = !isInvalidName"
|
||||||
@keyup.enter="createFileAction"></v-text-field>
|
@keyup.enter="createFileAction"></v-text-field>
|
||||||
</v-card-text>
|
</v-card-text>
|
||||||
<v-card-actions>
|
<v-card-actions>
|
||||||
@ -284,7 +286,7 @@
|
|||||||
<v-btn color="" text @click="dialogCreateFile.show = false">
|
<v-btn color="" text @click="dialogCreateFile.show = false">
|
||||||
{{ $t('Machine.ConfigFilesPanel.Cancel') }}
|
{{ $t('Machine.ConfigFilesPanel.Cancel') }}
|
||||||
</v-btn>
|
</v-btn>
|
||||||
<v-btn color="primary" text @click="createFileAction">
|
<v-btn :disabled="isInvalidName" color="primary" text @click="createFileAction">
|
||||||
{{ $t('Machine.ConfigFilesPanel.Create') }}
|
{{ $t('Machine.ConfigFilesPanel.Create') }}
|
||||||
</v-btn>
|
</v-btn>
|
||||||
</v-card-actions>
|
</v-card-actions>
|
||||||
@ -306,6 +308,8 @@
|
|||||||
v-model="dialogRenameFile.newName"
|
v-model="dialogRenameFile.newName"
|
||||||
:label="$t('Machine.ConfigFilesPanel.Name')"
|
:label="$t('Machine.ConfigFilesPanel.Name')"
|
||||||
required
|
required
|
||||||
|
:rules="nameInputRules"
|
||||||
|
@update:error="isInvalidName = !isInvalidName"
|
||||||
@keyup.enter="renameFileAction"></v-text-field>
|
@keyup.enter="renameFileAction"></v-text-field>
|
||||||
</v-card-text>
|
</v-card-text>
|
||||||
<v-card-actions>
|
<v-card-actions>
|
||||||
@ -313,7 +317,7 @@
|
|||||||
<v-btn color="" text @click="dialogRenameFile.show = false">
|
<v-btn color="" text @click="dialogRenameFile.show = false">
|
||||||
{{ $t('Machine.ConfigFilesPanel.Cancel') }}
|
{{ $t('Machine.ConfigFilesPanel.Cancel') }}
|
||||||
</v-btn>
|
</v-btn>
|
||||||
<v-btn color="primary" text @click="renameFileAction">
|
<v-btn :disabled="isInvalidName" color="primary" text @click="renameFileAction">
|
||||||
{{ $t('Machine.ConfigFilesPanel.Rename') }}
|
{{ $t('Machine.ConfigFilesPanel.Rename') }}
|
||||||
</v-btn>
|
</v-btn>
|
||||||
</v-card-actions>
|
</v-card-actions>
|
||||||
@ -335,6 +339,8 @@
|
|||||||
v-model="dialogCreateDirectory.name"
|
v-model="dialogCreateDirectory.name"
|
||||||
:label="$t('Machine.ConfigFilesPanel.Name')"
|
:label="$t('Machine.ConfigFilesPanel.Name')"
|
||||||
required
|
required
|
||||||
|
:rules="nameInputRules"
|
||||||
|
@update:error="isInvalidName = !isInvalidName"
|
||||||
@keyup.enter="createDirectoryAction"></v-text-field>
|
@keyup.enter="createDirectoryAction"></v-text-field>
|
||||||
</v-card-text>
|
</v-card-text>
|
||||||
<v-card-actions>
|
<v-card-actions>
|
||||||
@ -342,7 +348,7 @@
|
|||||||
<v-btn color="" text @click="dialogCreateDirectory.show = false">
|
<v-btn color="" text @click="dialogCreateDirectory.show = false">
|
||||||
{{ $t('Machine.ConfigFilesPanel.Cancel') }}
|
{{ $t('Machine.ConfigFilesPanel.Cancel') }}
|
||||||
</v-btn>
|
</v-btn>
|
||||||
<v-btn color="primary" text @click="createDirectoryAction">
|
<v-btn :disabled="isInvalidName" color="primary" text @click="createDirectoryAction">
|
||||||
{{ $t('Machine.ConfigFilesPanel.Create') }}
|
{{ $t('Machine.ConfigFilesPanel.Create') }}
|
||||||
</v-btn>
|
</v-btn>
|
||||||
</v-card-actions>
|
</v-card-actions>
|
||||||
@ -364,6 +370,8 @@
|
|||||||
v-model="dialogRenameDirectory.newName"
|
v-model="dialogRenameDirectory.newName"
|
||||||
:label="$t('Machine.ConfigFilesPanel.Name')"
|
:label="$t('Machine.ConfigFilesPanel.Name')"
|
||||||
required
|
required
|
||||||
|
:rules="nameInputRules"
|
||||||
|
@update:error="isInvalidName = !isInvalidName"
|
||||||
@keyup.enter="renameDirectoryAction"></v-text-field>
|
@keyup.enter="renameDirectoryAction"></v-text-field>
|
||||||
</v-card-text>
|
</v-card-text>
|
||||||
<v-card-actions>
|
<v-card-actions>
|
||||||
@ -371,7 +379,7 @@
|
|||||||
<v-btn color="" text @click="dialogRenameDirectory.show = false">
|
<v-btn color="" text @click="dialogRenameDirectory.show = false">
|
||||||
{{ $t('Machine.ConfigFilesPanel.Cancel') }}
|
{{ $t('Machine.ConfigFilesPanel.Cancel') }}
|
||||||
</v-btn>
|
</v-btn>
|
||||||
<v-btn color="primary" text @click="renameDirectoryAction">
|
<v-btn :disabled="isInvalidName" color="primary" text @click="renameDirectoryAction">
|
||||||
{{ $t('Machine.ConfigFilesPanel.Rename') }}
|
{{ $t('Machine.ConfigFilesPanel.Rename') }}
|
||||||
</v-btn>
|
</v-btn>
|
||||||
</v-card-actions>
|
</v-card-actions>
|
||||||
@ -639,6 +647,16 @@ export default class ConfigFilesPanel extends Mixins(BaseMixin) {
|
|||||||
|
|
||||||
private deleteSelectedDialog = false
|
private deleteSelectedDialog = false
|
||||||
|
|
||||||
|
private isInvalidName = true
|
||||||
|
private nameInputRules = [
|
||||||
|
(value: string) => !!value || this.$t('Files.InvalidNameEmpty'),
|
||||||
|
(value: string) => !this.existsFilename(value) || this.$t('Files.InvalidNameAlreadyExists'),
|
||||||
|
]
|
||||||
|
|
||||||
|
existsFilename(name: string) {
|
||||||
|
return this.files.findIndex((file) => file.filename === name) >= 0
|
||||||
|
}
|
||||||
|
|
||||||
get blockFileUpload() {
|
get blockFileUpload() {
|
||||||
return this.$store.state.gui.view.blockFileUpload ?? false
|
return this.$store.state.gui.view.blockFileUpload ?? false
|
||||||
}
|
}
|
||||||
|
@ -237,12 +237,16 @@
|
|||||||
v-model="dialogRenameFile.newName"
|
v-model="dialogRenameFile.newName"
|
||||||
:label="$t('Timelapse.Name')"
|
:label="$t('Timelapse.Name')"
|
||||||
required
|
required
|
||||||
|
:rules="nameInputRules"
|
||||||
|
@update:error="isInvalidName = !isInvalidName"
|
||||||
@keypress.enter="renameFileAction"></v-text-field>
|
@keypress.enter="renameFileAction"></v-text-field>
|
||||||
</v-card-text>
|
</v-card-text>
|
||||||
<v-card-actions>
|
<v-card-actions>
|
||||||
<v-spacer></v-spacer>
|
<v-spacer></v-spacer>
|
||||||
<v-btn color="" text @click="dialogRenameFile.show = false">{{ $t('Timelapse.Cancel') }}</v-btn>
|
<v-btn color="" text @click="dialogRenameFile.show = false">{{ $t('Timelapse.Cancel') }}</v-btn>
|
||||||
<v-btn color="primary" text @click="renameFileAction">{{ $t('Timelapse.Rename') }}</v-btn>
|
<v-btn :disabled="isInvalidName" color="primary" text @click="renameFileAction">
|
||||||
|
{{ $t('Timelapse.Rename') }}
|
||||||
|
</v-btn>
|
||||||
</v-card-actions>
|
</v-card-actions>
|
||||||
</panel>
|
</panel>
|
||||||
</v-dialog>
|
</v-dialog>
|
||||||
@ -261,8 +265,9 @@
|
|||||||
ref="inputFieldCreateDirectory"
|
ref="inputFieldCreateDirectory"
|
||||||
v-model="dialogCreateDirectory.name"
|
v-model="dialogCreateDirectory.name"
|
||||||
:label="$t('Timelapse.Name')"
|
:label="$t('Timelapse.Name')"
|
||||||
:rules="input_rules"
|
|
||||||
required
|
required
|
||||||
|
:rules="nameInputRules"
|
||||||
|
@update:error="isInvalidName = !isInvalidName"
|
||||||
@keypress.enter="createDirectoryAction"></v-text-field>
|
@keypress.enter="createDirectoryAction"></v-text-field>
|
||||||
</v-card-text>
|
</v-card-text>
|
||||||
<v-card-actions>
|
<v-card-actions>
|
||||||
@ -270,7 +275,9 @@
|
|||||||
<v-btn color="" text @click="dialogCreateDirectory.show = false">
|
<v-btn color="" text @click="dialogCreateDirectory.show = false">
|
||||||
{{ $t('Timelapse.Cancel') }}
|
{{ $t('Timelapse.Cancel') }}
|
||||||
</v-btn>
|
</v-btn>
|
||||||
<v-btn color="primary" text @click="createDirectoryAction">{{ $t('Timelapse.Create') }}</v-btn>
|
<v-btn :disabled="isInvalidName" color="primary" text @click="createDirectoryAction">
|
||||||
|
{{ $t('Timelapse.Create') }}
|
||||||
|
</v-btn>
|
||||||
</v-card-actions>
|
</v-card-actions>
|
||||||
</panel>
|
</panel>
|
||||||
</v-dialog>
|
</v-dialog>
|
||||||
@ -290,6 +297,8 @@
|
|||||||
v-model="dialogRenameDirectory.newName"
|
v-model="dialogRenameDirectory.newName"
|
||||||
:label="$t('Timelapse.Name')"
|
:label="$t('Timelapse.Name')"
|
||||||
required
|
required
|
||||||
|
:rules="nameInputRules"
|
||||||
|
@update:error="isInvalidName = !isInvalidName"
|
||||||
@keyup.enter="renameDirectoryAction"></v-text-field>
|
@keyup.enter="renameDirectoryAction"></v-text-field>
|
||||||
</v-card-text>
|
</v-card-text>
|
||||||
<v-card-actions>
|
<v-card-actions>
|
||||||
@ -297,7 +306,9 @@
|
|||||||
<v-btn color="" text @click="dialogRenameDirectory.show = false">
|
<v-btn color="" text @click="dialogRenameDirectory.show = false">
|
||||||
{{ $t('Timelapse.Cancel') }}
|
{{ $t('Timelapse.Cancel') }}
|
||||||
</v-btn>
|
</v-btn>
|
||||||
<v-btn color="primary" text @click="renameDirectoryAction">{{ $t('Timelapse.Rename') }}</v-btn>
|
<v-btn :disabled="isInvalidName" color="primary" text @click="renameDirectoryAction">
|
||||||
|
{{ $t('Timelapse.Rename') }}
|
||||||
|
</v-btn>
|
||||||
</v-card-actions>
|
</v-card-actions>
|
||||||
</panel>
|
</panel>
|
||||||
</v-dialog>
|
</v-dialog>
|
||||||
@ -496,7 +507,15 @@ export default class TimelapseFilesPanel extends Mixins(BaseMixin) {
|
|||||||
|
|
||||||
private deleteSelectedDialog = false
|
private deleteSelectedDialog = false
|
||||||
|
|
||||||
private input_rules = [(value: string) => value.indexOf(' ') === -1 || 'Name contains spaces!']
|
private isInvalidName = true
|
||||||
|
private nameInputRules = [
|
||||||
|
(value: string) => !!value || this.$t('Files.InvalidNameEmpty'),
|
||||||
|
(value: string) => !this.existsFilename(value) || this.$t('Files.InvalidNameAlreadyExists'),
|
||||||
|
]
|
||||||
|
|
||||||
|
existsFilename(name: string) {
|
||||||
|
return this.files.findIndex((file) => file.filename === name) >= 0
|
||||||
|
}
|
||||||
|
|
||||||
get headers() {
|
get headers() {
|
||||||
return [
|
return [
|
||||||
@ -593,14 +612,15 @@ export default class TimelapseFilesPanel extends Mixins(BaseMixin) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
createDirectoryAction() {
|
createDirectoryAction() {
|
||||||
if (this.dialogCreateDirectory.name.length && this.dialogCreateDirectory.name.indexOf(' ') === -1) {
|
this.dialogCreateDirectory.show = false
|
||||||
this.dialogCreateDirectory.show = false
|
|
||||||
this.$socket.emit(
|
this.$socket.emit(
|
||||||
'server.files.post_directory',
|
'server.files.post_directory',
|
||||||
{ path: this.currentPath + '/' + this.dialogCreateDirectory.name },
|
{
|
||||||
{ action: 'files/getCreateDir' }
|
path: this.currentPath + '/' + this.dialogCreateDirectory.name,
|
||||||
)
|
},
|
||||||
}
|
{ action: 'files/getCreateDir' }
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
refreshFileList() {
|
refreshFileList() {
|
||||||
|
@ -181,6 +181,8 @@
|
|||||||
"GCodeFiles": "G-Code Dateien",
|
"GCodeFiles": "G-Code Dateien",
|
||||||
"GcodesRootDirectoryDoesntExists": "Keinen G-Code Ordner gefunden. Bitte überprüfe die Option \"path\" im Abschnitt [virtual_sdcard] in der Klipper Konfiguration.",
|
"GcodesRootDirectoryDoesntExists": "Keinen G-Code Ordner gefunden. Bitte überprüfe die Option \"path\" im Abschnitt [virtual_sdcard] in der Klipper Konfiguration.",
|
||||||
"HiddenFiles": "Versteckte Dateien",
|
"HiddenFiles": "Versteckte Dateien",
|
||||||
|
"InvalidNameEmpty": "Feld darf nicht leer sein!",
|
||||||
|
"InvalidNameAlreadyExists": "Name existiert bereits, bitte wähle einen anderen Namen.",
|
||||||
"LastEndTime": "Letzte Endzeit",
|
"LastEndTime": "Letzte Endzeit",
|
||||||
"LastFilamentUsed": "Letzter Filamentverbrauch",
|
"LastFilamentUsed": "Letzter Filamentverbrauch",
|
||||||
"LastModified": "Zuletzt geändert",
|
"LastModified": "Zuletzt geändert",
|
||||||
|
@ -181,6 +181,8 @@
|
|||||||
"GCodeFiles": "G-Code Files",
|
"GCodeFiles": "G-Code Files",
|
||||||
"GcodesRootDirectoryDoesntExists": "No G-Code directory found. Please check option \"path\" in the [virtual_sdcard] section of the Klipper configuration.",
|
"GcodesRootDirectoryDoesntExists": "No G-Code directory found. Please check option \"path\" in the [virtual_sdcard] section of the Klipper configuration.",
|
||||||
"HiddenFiles": "Hidden files",
|
"HiddenFiles": "Hidden files",
|
||||||
|
"InvalidNameEmpty": "Input must not be empty!",
|
||||||
|
"InvalidNameAlreadyExists": "Name already exists, please choose another name.",
|
||||||
"LastEndTime": "Last End Time",
|
"LastEndTime": "Last End Time",
|
||||||
"LastFilamentUsed": "Last Filament Used",
|
"LastFilamentUsed": "Last Filament Used",
|
||||||
"LastModified": "Last modified",
|
"LastModified": "Last modified",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user