fix old attachments by reuploading them

This commit is contained in:
Kyle Spearrin 2018-11-14 15:20:17 -05:00
parent 9d4d64c95a
commit 8232a4c9c8
9 changed files with 62 additions and 7 deletions

2
jslib

@ -1 +1 @@
Subproject commit 17e7ee4838071ea836867b06863a71ab047ed443 Subproject commit f485fbb6870203b60ac27bcbc2e12bb45f24b538

View File

@ -11,6 +11,8 @@ import { CipherData } from 'jslib/models/data/cipherData';
import { Cipher } from 'jslib/models/domain/cipher'; import { Cipher } from 'jslib/models/domain/cipher';
import { Organization } from 'jslib/models/domain/organization'; import { Organization } from 'jslib/models/domain/organization';
import { AttachmentView } from 'jslib/models/view/attachmentView';
import { AttachmentsComponent as BaseAttachmentsComponent } from '../../vault/attachments.component'; import { AttachmentsComponent as BaseAttachmentsComponent } from '../../vault/attachments.component';
@Component({ @Component({
@ -26,6 +28,12 @@ export class AttachmentsComponent extends BaseAttachmentsComponent {
super(cipherService, i18nService, cryptoService, userService, platformUtilsService); super(cipherService, i18nService, cryptoService, userService, platformUtilsService);
} }
protected async reupload(attachment: AttachmentView) {
if (this.organization.isAdmin && this.showFixOldAttachments(attachment)) {
await super.reuploadCipherAttachment(attachment, true);
}
}
protected async loadCipher() { protected async loadCipher() {
if (!this.organization.isAdmin) { if (!this.organization.isAdmin) {
return await super.loadCipher(); return await super.loadCipher();
@ -44,4 +52,8 @@ export class AttachmentsComponent extends BaseAttachmentsComponent {
} }
return this.apiService.deleteCipherAttachmentAdmin(this.cipherId, attachmentId); return this.apiService.deleteCipherAttachmentAdmin(this.cipherId, attachmentId);
} }
protected showFixOldAttachments(attachment: AttachmentView) {
return attachment.key == null && this.organization.isAdmin;
}
} }

View File

@ -103,4 +103,8 @@ export class CiphersComponent extends BaseCiphersComponent {
} }
return this.apiService.deleteCipherAdmin(id); return this.apiService.deleteCipherAdmin(id);
} }
protected showFixOldAttachments(c: CipherView) {
return this.organization.isAdmin && c.hasOldAttachments;
}
} }

View File

@ -19,13 +19,21 @@
<i class="fa fa-spinner fa-lg fa-fw fa-spin" *ngIf="a.downloading"></i> <i class="fa fa-spinner fa-lg fa-fw fa-spin" *ngIf="a.downloading"></i>
</td> </td>
<td> <td>
<div class="d-flex">
<a href="#" appStopClick (click)="download(a)">{{a.fileName}}</a> <a href="#" appStopClick (click)="download(a)">{{a.fileName}}</a>
<br> <div *ngIf="showFixOldAttachments(a)" class="ml-2">
<a href="https://help.bitwarden.com/article/attachments/" target="_blank" rel="noopener">
<i class="fa fa-exclamation-triangle text-warning" title="{{'attachmentFixDesc' | i18n}}"></i></a>
<button type="button" class="btn btn-outline-primary btn-sm m-0 py-0 px-2"
(click)="reupload(a)" #reuploadBtn [appApiAction]="reuploadPromises[a.id]"
[disabled]="reuploadBtn.loading">{{'fix' | i18n}}</button>
</div>
</div>
<small>{{a.sizeName}}</small> <small>{{a.sizeName}}</small>
</td> </td>
<td class="table-list-options"> <td class="table-list-options">
<button class="btn btn-outline-danger" type="button" appStopClick title="{{'delete' | i18n}}" (click)="delete(a)" #deleteBtn <button class="btn btn-outline-danger" type="button" appStopClick title="{{'delete' | i18n}}"
[appApiAction]="deletePromises[a.id]" [disabled]="deleteBtn.loading"> (click)="delete(a)" #deleteBtn [appApiAction]="deletePromises[a.id]" [disabled]="deleteBtn.loading">
<i class="fa fa-trash-o fa-lg fa-fw" [hidden]="deleteBtn.loading"></i> <i class="fa fa-trash-o fa-lg fa-fw" [hidden]="deleteBtn.loading"></i>
<i class="fa fa-spinner fa-spin fa-lg fa-fw" [hidden]="!deleteBtn.loading" title="{{'loading' | i18n}}"></i> <i class="fa fa-spinner fa-spin fa-lg fa-fw" [hidden]="!deleteBtn.loading" title="{{'loading' | i18n}}"></i>
</button> </button>
@ -43,7 +51,8 @@
<i class="fa fa-spinner fa-spin" title="{{'loading' | i18n}}"></i> <i class="fa fa-spinner fa-spin" title="{{'loading' | i18n}}"></i>
<span>{{'save' | i18n}}</span> <span>{{'save' | i18n}}</span>
</button> </button>
<button type="button" class="btn btn-outline-secondary" data-dismiss="modal" title="{{'close' | i18n}}">{{'close' | i18n}}</button> <button type="button" class="btn btn-outline-secondary" data-dismiss="modal" title="{{'close' | i18n}}">{{'close'
| i18n}}</button>
</div> </div>
</form> </form>
</div> </div>

View File

@ -6,6 +6,8 @@ import { I18nService } from 'jslib/abstractions/i18n.service';
import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service'; import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service';
import { UserService } from 'jslib/abstractions/user.service'; import { UserService } from 'jslib/abstractions/user.service';
import { AttachmentView } from 'jslib/models/view/attachmentView';
import { AttachmentsComponent as BaseAttachmentsComponent } from 'jslib/angular/components/attachments.component'; import { AttachmentsComponent as BaseAttachmentsComponent } from 'jslib/angular/components/attachments.component';
@Component({ @Component({
@ -18,4 +20,14 @@ export class AttachmentsComponent extends BaseAttachmentsComponent {
platformUtilsService: PlatformUtilsService) { platformUtilsService: PlatformUtilsService) {
super(cipherService, i18nService, cryptoService, userService, platformUtilsService, window); super(cipherService, i18nService, cryptoService, userService, platformUtilsService, window);
} }
protected async reupload(attachment: AttachmentView) {
if (this.showFixOldAttachments(attachment)) {
await this.reuploadCipherAttachment(attachment, false);
}
}
protected showFixOldAttachments(attachment: AttachmentView) {
return attachment.key == null && this.cipher.organizationId == null;
}
} }

View File

@ -11,7 +11,11 @@
<td (click)="checkCipher(c)" class="reduced-lh wrap"> <td (click)="checkCipher(c)" class="reduced-lh wrap">
<a href="#" appStopClick appStopProp (click)="selectCipher(c)" title="{{'editItem' | i18n}}">{{c.name}}</a> <a href="#" appStopClick appStopProp (click)="selectCipher(c)" title="{{'editItem' | i18n}}">{{c.name}}</a>
<i class="fa fa-share-alt" appStopProp *ngIf="!organization && c.organizationId" title="{{'shared' | i18n}}"></i> <i class="fa fa-share-alt" appStopProp *ngIf="!organization && c.organizationId" title="{{'shared' | i18n}}"></i>
<i class="fa fa-paperclip" appStopProp *ngIf="c.hasAttachments" title="{{'attachments' | i18n}}"></i> <ng-container *ngIf="c.hasAttachments">
<i class="fa fa-paperclip" appStopProp title="{{'attachments' | i18n}}"></i>
<i class="fa fa-exclamation-triangle text-warning" appStopProp *ngIf="showFixOldAttachments(c)"
title="{{'attachmentsNeedFix' | i18n}}"></i>
</ng-container>
<br> <br>
<small appStopProp>{{c.subTitle}}</small> <small appStopProp>{{c.subTitle}}</small>
</td> </td>

View File

@ -127,4 +127,8 @@ export class CiphersComponent extends BaseCiphersComponent implements OnDestroy
protected deleteCipher(id: string) { protected deleteCipher(id: string) {
return this.cipherService.deleteWithServer(id); return this.cipherService.deleteWithServer(id);
} }
protected showFixOldAttachments(c: CipherView) {
return c.hasOldAttachments && c.organizationId == null;
}
} }

View File

@ -225,6 +225,7 @@ export class VaultComponent implements OnInit, OnDestroy {
let madeAttachmentChanges = false; let madeAttachmentChanges = false;
childComponent.onUploadedAttachment.subscribe(() => madeAttachmentChanges = true); childComponent.onUploadedAttachment.subscribe(() => madeAttachmentChanges = true);
childComponent.onDeletedAttachment.subscribe(() => madeAttachmentChanges = true); childComponent.onDeletedAttachment.subscribe(() => madeAttachmentChanges = true);
childComponent.onReuploadedAttachment.subscribe(() => madeAttachmentChanges = true);
this.modal.onClosed.subscribe(async () => { this.modal.onClosed.subscribe(async () => {
this.modal = null; this.modal = null;

View File

@ -2539,5 +2539,14 @@
}, },
"rotateEncKeyConfirmation": { "rotateEncKeyConfirmation": {
"message": "Are you sure you want to rotate your account's encryption key?" "message": "Are you sure you want to rotate your account's encryption key?"
},
"attachmentsNeedFix": {
"message": "This item has old attachments that need to be fixed."
},
"attachmentFixDesc": {
"message": "This is an old attachment the needs to be fixed. Click to learn more."
},
"fix": {
"message": "Fix"
} }
} }