fix: add input validation in filemanagers to prevent overwriting existing files (#1087)

This commit is contained in:
th33xitus 2022-09-16 23:18:22 +02:00 committed by GitHub
parent e411175b7f
commit 3ec2ee2793
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 84 additions and 20 deletions

View File

@ -374,12 +374,16 @@
v-model="dialogCreateDirectory.name"
:label="$t('Files.Name')"
required
:rules="nameInputRules"
@update:error="isInvalidName = !isInvalidName"
@keypress.enter="createDirectoryAction"></v-text-field>
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<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>
</panel>
</v-dialog>
@ -399,12 +403,16 @@
v-model="dialogRenameFile.newName"
:label="$t('Files.Name').toString()"
required
:rules="nameInputRules"
@update:error="isInvalidName = !isInvalidName"
@keyup.enter="renameFileAction"></v-text-field>
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<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>
</panel>
</v-dialog>
@ -424,12 +432,16 @@
v-model="dialogRenameDirectory.newName"
:label="$t('Files.Name')"
required
:rules="nameInputRules"
@update:error="isInvalidName = !isInvalidName"
@keyup.enter="renameDirectoryAction"></v-text-field>
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<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>
</panel>
</v-dialog>
@ -647,6 +659,16 @@ export default class GcodefilesPanel extends Mixins(BaseMixin, ControlMixin) {
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() {
const path = this.$store.state.gui.view.gcodefiles.currentPath
if (path === 'gcodes') return ''

View File

@ -277,6 +277,8 @@
v-model="dialogCreateFile.name"
:label="$t('Machine.ConfigFilesPanel.Name')"
required
:rules="nameInputRules"
@update:error="isInvalidName = !isInvalidName"
@keyup.enter="createFileAction"></v-text-field>
</v-card-text>
<v-card-actions>
@ -284,7 +286,7 @@
<v-btn color="" text @click="dialogCreateFile.show = false">
{{ $t('Machine.ConfigFilesPanel.Cancel') }}
</v-btn>
<v-btn color="primary" text @click="createFileAction">
<v-btn :disabled="isInvalidName" color="primary" text @click="createFileAction">
{{ $t('Machine.ConfigFilesPanel.Create') }}
</v-btn>
</v-card-actions>
@ -306,6 +308,8 @@
v-model="dialogRenameFile.newName"
:label="$t('Machine.ConfigFilesPanel.Name')"
required
:rules="nameInputRules"
@update:error="isInvalidName = !isInvalidName"
@keyup.enter="renameFileAction"></v-text-field>
</v-card-text>
<v-card-actions>
@ -313,7 +317,7 @@
<v-btn color="" text @click="dialogRenameFile.show = false">
{{ $t('Machine.ConfigFilesPanel.Cancel') }}
</v-btn>
<v-btn color="primary" text @click="renameFileAction">
<v-btn :disabled="isInvalidName" color="primary" text @click="renameFileAction">
{{ $t('Machine.ConfigFilesPanel.Rename') }}
</v-btn>
</v-card-actions>
@ -335,6 +339,8 @@
v-model="dialogCreateDirectory.name"
:label="$t('Machine.ConfigFilesPanel.Name')"
required
:rules="nameInputRules"
@update:error="isInvalidName = !isInvalidName"
@keyup.enter="createDirectoryAction"></v-text-field>
</v-card-text>
<v-card-actions>
@ -342,7 +348,7 @@
<v-btn color="" text @click="dialogCreateDirectory.show = false">
{{ $t('Machine.ConfigFilesPanel.Cancel') }}
</v-btn>
<v-btn color="primary" text @click="createDirectoryAction">
<v-btn :disabled="isInvalidName" color="primary" text @click="createDirectoryAction">
{{ $t('Machine.ConfigFilesPanel.Create') }}
</v-btn>
</v-card-actions>
@ -364,6 +370,8 @@
v-model="dialogRenameDirectory.newName"
:label="$t('Machine.ConfigFilesPanel.Name')"
required
:rules="nameInputRules"
@update:error="isInvalidName = !isInvalidName"
@keyup.enter="renameDirectoryAction"></v-text-field>
</v-card-text>
<v-card-actions>
@ -371,7 +379,7 @@
<v-btn color="" text @click="dialogRenameDirectory.show = false">
{{ $t('Machine.ConfigFilesPanel.Cancel') }}
</v-btn>
<v-btn color="primary" text @click="renameDirectoryAction">
<v-btn :disabled="isInvalidName" color="primary" text @click="renameDirectoryAction">
{{ $t('Machine.ConfigFilesPanel.Rename') }}
</v-btn>
</v-card-actions>
@ -639,6 +647,16 @@ export default class ConfigFilesPanel extends Mixins(BaseMixin) {
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() {
return this.$store.state.gui.view.blockFileUpload ?? false
}

View File

@ -237,12 +237,16 @@
v-model="dialogRenameFile.newName"
:label="$t('Timelapse.Name')"
required
:rules="nameInputRules"
@update:error="isInvalidName = !isInvalidName"
@keypress.enter="renameFileAction"></v-text-field>
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<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>
</panel>
</v-dialog>
@ -261,8 +265,9 @@
ref="inputFieldCreateDirectory"
v-model="dialogCreateDirectory.name"
:label="$t('Timelapse.Name')"
:rules="input_rules"
required
:rules="nameInputRules"
@update:error="isInvalidName = !isInvalidName"
@keypress.enter="createDirectoryAction"></v-text-field>
</v-card-text>
<v-card-actions>
@ -270,7 +275,9 @@
<v-btn color="" text @click="dialogCreateDirectory.show = false">
{{ $t('Timelapse.Cancel') }}
</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>
</panel>
</v-dialog>
@ -290,6 +297,8 @@
v-model="dialogRenameDirectory.newName"
:label="$t('Timelapse.Name')"
required
:rules="nameInputRules"
@update:error="isInvalidName = !isInvalidName"
@keyup.enter="renameDirectoryAction"></v-text-field>
</v-card-text>
<v-card-actions>
@ -297,7 +306,9 @@
<v-btn color="" text @click="dialogRenameDirectory.show = false">
{{ $t('Timelapse.Cancel') }}
</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>
</panel>
</v-dialog>
@ -496,7 +507,15 @@ export default class TimelapseFilesPanel extends Mixins(BaseMixin) {
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() {
return [
@ -593,14 +612,15 @@ export default class TimelapseFilesPanel extends Mixins(BaseMixin) {
}
createDirectoryAction() {
if (this.dialogCreateDirectory.name.length && this.dialogCreateDirectory.name.indexOf(' ') === -1) {
this.dialogCreateDirectory.show = false
this.$socket.emit(
'server.files.post_directory',
{ path: this.currentPath + '/' + this.dialogCreateDirectory.name },
{ action: 'files/getCreateDir' }
)
}
this.dialogCreateDirectory.show = false
this.$socket.emit(
'server.files.post_directory',
{
path: this.currentPath + '/' + this.dialogCreateDirectory.name,
},
{ action: 'files/getCreateDir' }
)
}
refreshFileList() {

View File

@ -181,6 +181,8 @@
"GCodeFiles": "G-Code Dateien",
"GcodesRootDirectoryDoesntExists": "Keinen G-Code Ordner gefunden. Bitte überprüfe die Option \"path\" im Abschnitt [virtual_sdcard] in der Klipper Konfiguration.",
"HiddenFiles": "Versteckte Dateien",
"InvalidNameEmpty": "Feld darf nicht leer sein!",
"InvalidNameAlreadyExists": "Name existiert bereits, bitte wähle einen anderen Namen.",
"LastEndTime": "Letzte Endzeit",
"LastFilamentUsed": "Letzter Filamentverbrauch",
"LastModified": "Zuletzt geändert",

View File

@ -181,6 +181,8 @@
"GCodeFiles": "G-Code Files",
"GcodesRootDirectoryDoesntExists": "No G-Code directory found. Please check option \"path\" in the [virtual_sdcard] section of the Klipper configuration.",
"HiddenFiles": "Hidden files",
"InvalidNameEmpty": "Input must not be empty!",
"InvalidNameAlreadyExists": "Name already exists, please choose another name.",
"LastEndTime": "Last End Time",
"LastFilamentUsed": "Last Filament Used",
"LastModified": "Last modified",