Skip to content

Commit b847d2f

Browse files
committed
fix(files_sharing): restore state when updating share failed
We need to save the previous state - here the password - so that if the update fails we can revert the shown state. This happens e.g. if you have the password policy app and try to add an unsecure password. To reproduce (with password policy): 1. Create new link share 2. enable password protection 3. use insecure password like `1234` 4. save share Now you see that the update failed, but the password protection is still enabled. This happened because `password` and `newPassword` were misused. `password` was already set when `newPassword` was not saved so we could not know to what we need to reset when the update failed. Signed-off-by: Ferdinand Thiessen <[email protected]>
1 parent 224f80e commit b847d2f

File tree

3 files changed

+37
-27
lines changed

3 files changed

+37
-27
lines changed

apps/files_sharing/src/components/SharingEntryLink.vue

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -68,10 +68,10 @@
6868
{{ config.enforcePasswordForPublicLink ? t('files_sharing', 'Password protection (enforced)') : t('files_sharing', 'Password protection') }}
6969
</NcActionCheckbox>
7070

71-
<NcActionInput v-if="pendingEnforcedPassword || share.password"
71+
<NcActionInput v-if="pendingEnforcedPassword || isPasswordProtected"
7272
class="share-link-password"
7373
:label="t('files_sharing', 'Enter a password')"
74-
:value.sync="share.password"
74+
:value.sync="share.newPassword"
7575
:disabled="saving"
7676
:required="config.enableLinkPasswordByDefault || config.enforcePasswordForPublicLink"
7777
:minlength="isPasswordPolicyEnabled && config.passwordPolicy.minLength"
@@ -109,7 +109,8 @@
109109
</template>
110110
</NcActionInput>
111111

112-
<NcActionButton @click.prevent.stop="onNewLinkShare(true)">
112+
<NcActionButton :disabled="pendingEnforcedPassword && !share.newPassword"
113+
@click.prevent.stop="onNewLinkShare(true)">
113114
<template #icon>
114115
<CheckIcon :size="20" />
115116
</template>
@@ -638,6 +639,7 @@ export default {
638639
639640
// create share & close menu
640641
const share = new Share(shareDefaults)
642+
share.newPassword = share.password
641643
const component = await new Promise(resolve => {
642644
this.$emit('add:share', share, resolve)
643645
})
@@ -830,7 +832,7 @@ export default {
830832
*/
831833
onPasswordSubmit() {
832834
if (this.hasUnsavedPassword) {
833-
this.share.password = this.share.newPassword.trim()
835+
this.share.newPassword = this.share.newPassword.trim()
834836
this.queueUpdate('password')
835837
}
836838
},
@@ -845,7 +847,7 @@ export default {
845847
*/
846848
onPasswordProtectedByTalkChange() {
847849
if (this.hasUnsavedPassword) {
848-
this.share.password = this.share.newPassword.trim()
850+
this.share.newPassword = this.share.newPassword.trim()
849851
}
850852
851853
this.queueUpdate('sendPasswordByTalk', 'password')

apps/files_sharing/src/mixins/SharesMixin.js

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -165,12 +165,12 @@ export default {
165165
isPasswordProtected: {
166166
get() {
167167
return this.config.enforcePasswordForPublicLink
168-
|| !!this.share.password
168+
|| this.share.password !== ''
169+
|| this.share.newPassword !== undefined
169170
},
170171
async set(enabled) {
171172
if (enabled) {
172-
this.share.password = await GeneratePassword(true)
173-
this.$set(this.share, 'newPassword', this.share.password)
173+
this.$set(this.share, 'newPassword', await GeneratePassword(true))
174174
} else {
175175
this.share.password = ''
176176
this.$delete(this.share, 'newPassword')
@@ -272,7 +272,7 @@ export default {
272272
this.loading = true
273273
this.open = false
274274
await this.deleteShare(this.share.id)
275-
console.debug('Share deleted', this.share.id)
275+
logger.debug('Share deleted', { shareId: this.share.id })
276276
const message = this.share.itemType === 'file'
277277
? t('files_sharing', 'File "{path}" has been unshared', { path: this.share.path })
278278
: t('files_sharing', 'Folder "{path}" has been unshared', { path: this.share.path })
@@ -303,39 +303,49 @@ export default {
303303
const properties = {}
304304
// force value to string because that is what our
305305
// share api controller accepts
306-
propertyNames.forEach(name => {
306+
for (const name of propertyNames) {
307+
if (name === 'password') {
308+
properties[name] = this.share.newPassword ?? this.share.password
309+
continue
310+
}
311+
307312
if (this.share[name] === null || this.share[name] === undefined) {
308313
properties[name] = ''
309314
} else if ((typeof this.share[name]) === 'object') {
310315
properties[name] = JSON.stringify(this.share[name])
311316
} else {
312317
properties[name] = this.share[name].toString()
313318
}
314-
})
319+
}
315320

316321
return this.updateQueue.add(async () => {
317322
this.saving = true
318323
this.errors = {}
319324
try {
320325
const updatedShare = await this.updateShare(this.share.id, properties)
321326

322-
if (propertyNames.indexOf('password') >= 0) {
327+
if (propertyNames.includes('password')) {
323328
// reset password state after sync
329+
this.share.password = this.share.newPassword ?? ''
324330
this.$delete(this.share, 'newPassword')
325331

326332
// updates password expiration time after sync
327333
this.share.passwordExpirationTime = updatedShare.password_expiration_time
328334
}
329335

330336
// clear any previous errors
331-
this.$delete(this.errors, propertyNames[0])
337+
for (const property of propertyNames) {
338+
this.$delete(this.errors, property)
339+
}
332340
showSuccess(this.updateSuccessMessage(propertyNames))
333341
} catch (error) {
334342
logger.error('Could not update share', { error, share: this.share, propertyNames })
335343

336344
const { message } = error
337345
if (message && message !== '') {
338-
this.onSyncError(propertyNames[0], message)
346+
for (const property of propertyNames) {
347+
this.onSyncError(property, message)
348+
}
339349
showError(message)
340350
} else {
341351
// We do not have information what happened, but we should still inform the user
@@ -384,6 +394,13 @@ export default {
384394
* @param {string} message the error message
385395
*/
386396
onSyncError(property, message) {
397+
if (property === 'password' && this.share.newPassword) {
398+
if (this.share.newPassword === this.share.password) {
399+
this.share.password = ''
400+
}
401+
this.$delete(this.share, 'newPassword')
402+
}
403+
387404
// re-open menu if closed
388405
this.open = true
389406
switch (property) {

apps/files_sharing/src/views/SharingDetailsTab.vue

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@
128128
</NcCheckboxRadioSwitch>
129129
<NcPasswordField v-if="isPasswordProtected"
130130
autocomplete="new-password"
131-
:value="hasUnsavedPassword ? share.newPassword : ''"
131+
:value="share.newPassword ?? ''"
132132
:error="passwordError"
133133
:helper-text="errorPasswordLabel || passwordHint"
134134
:required="isPasswordEnforced && isNewShare"
@@ -872,7 +872,6 @@ export default {
872872
if (this.isNewShare) {
873873
if ((this.config.enableLinkPasswordByDefault || this.isPasswordEnforced) && this.isPublicShare) {
874874
this.$set(this.share, 'newPassword', await GeneratePassword(true))
875-
this.$set(this.share, 'password', this.share.newPassword)
876875
this.advancedSectionAccordionExpanded = true
877876
}
878877
/* Set default expiration dates if configured */
@@ -973,10 +972,7 @@ export default {
973972
this.share.note = ''
974973
}
975974
if (this.isPasswordProtected) {
976-
if (this.hasUnsavedPassword && this.isValidShareAttribute(this.share.newPassword)) {
977-
this.share.password = this.share.newPassword
978-
this.$delete(this.share, 'newPassword')
979-
} else if (this.isPasswordEnforced && this.isNewShare && !this.isValidShareAttribute(this.share.password)) {
975+
if (this.isPasswordEnforced && this.isNewShare && !this.isValidShareAttribute(this.share.password)) {
980976
this.passwordError = true
981977
}
982978
} else {
@@ -1000,7 +996,7 @@ export default {
1000996
incomingShare.expireDate = this.hasExpirationDate ? this.share.expireDate : ''
1001997
1002998
if (this.isPasswordProtected) {
1003-
incomingShare.password = this.share.password
999+
incomingShare.password = this.share.newPassword
10041000
}
10051001
10061002
let share
@@ -1032,9 +1028,8 @@ export default {
10321028
this.$emit('add:share', this.share)
10331029
} else {
10341030
// Let's update after creation as some attrs are only available after creation
1031+
await this.queueUpdate(...permissionsAndAttributes)
10351032
this.$emit('update:share', this.share)
1036-
emit('update:share', this.share)
1037-
this.queueUpdate(...permissionsAndAttributes)
10381033
}
10391034
10401035
await this.getNode()
@@ -1111,10 +1106,6 @@ export default {
11111106
* "sendPasswordByTalk".
11121107
*/
11131108
onPasswordProtectedByTalkChange() {
1114-
if (this.hasUnsavedPassword) {
1115-
this.share.password = this.share.newPassword.trim()
1116-
}
1117-
11181109
this.queueUpdate('sendPasswordByTalk', 'password')
11191110
},
11201111
isValidShareAttribute(value) {

0 commit comments

Comments
 (0)