mirror of
https://github.com/bitwarden/browser.git
synced 2024-11-08 09:43:42 +01:00
raw attachment saves with node form data
This commit is contained in:
parent
ed89dfaba7
commit
a421f6e64a
21
package-lock.json
generated
21
package-lock.json
generated
@ -84,6 +84,15 @@
|
|||||||
"tslib": "1.9.0"
|
"tslib": "1.9.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@types/form-data": {
|
||||||
|
"version": "2.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/form-data/-/form-data-2.2.1.tgz",
|
||||||
|
"integrity": "sha512-JAMFhOaHIciYVh8fb5/83nmuO/AHwmto+Hq7a9y8FzLDcC1KCU344XDOMEmahnrTFlHjgh4L0WJFczNIX2GxnQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@types/node": "8.0.19"
|
||||||
|
}
|
||||||
|
},
|
||||||
"@types/jasmine": {
|
"@types/jasmine": {
|
||||||
"version": "2.8.6",
|
"version": "2.8.6",
|
||||||
"resolved": "https://registry.npmjs.org/@types/jasmine/-/jasmine-2.8.6.tgz",
|
"resolved": "https://registry.npmjs.org/@types/jasmine/-/jasmine-2.8.6.tgz",
|
||||||
@ -383,8 +392,7 @@
|
|||||||
"asynckit": {
|
"asynckit": {
|
||||||
"version": "0.4.0",
|
"version": "0.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
||||||
"integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=",
|
"integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"atob": {
|
"atob": {
|
||||||
"version": "2.1.0",
|
"version": "2.1.0",
|
||||||
@ -1249,7 +1257,6 @@
|
|||||||
"version": "1.0.6",
|
"version": "1.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz",
|
||||||
"integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=",
|
"integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"delayed-stream": "1.0.0"
|
"delayed-stream": "1.0.0"
|
||||||
}
|
}
|
||||||
@ -1759,8 +1766,7 @@
|
|||||||
"delayed-stream": {
|
"delayed-stream": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||||
"integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=",
|
"integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"depd": {
|
"depd": {
|
||||||
"version": "1.1.2",
|
"version": "1.1.2",
|
||||||
@ -2575,7 +2581,6 @@
|
|||||||
"version": "2.3.2",
|
"version": "2.3.2",
|
||||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz",
|
"resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz",
|
||||||
"integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=",
|
"integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"asynckit": "0.4.0",
|
"asynckit": "0.4.0",
|
||||||
"combined-stream": "1.0.6",
|
"combined-stream": "1.0.6",
|
||||||
@ -5642,14 +5647,12 @@
|
|||||||
"mime-db": {
|
"mime-db": {
|
||||||
"version": "1.33.0",
|
"version": "1.33.0",
|
||||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz",
|
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz",
|
||||||
"integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==",
|
"integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"mime-types": {
|
"mime-types": {
|
||||||
"version": "2.1.18",
|
"version": "2.1.18",
|
||||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz",
|
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz",
|
||||||
"integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==",
|
"integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"mime-db": "1.33.0"
|
"mime-db": "1.33.0"
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
"test:node:watch": "concurrently -k -n TSC,Node -c yellow,cyan \"npm run build:watch\" \"nodemon -w ./dist --delay 500ms --exec jasmine\""
|
"test:node:watch": "concurrently -k -n TSC,Node -c yellow,cyan \"npm run build:watch\" \"nodemon -w ./dist --delay 500ms --exec jasmine\""
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@types/form-data": "^2.2.1",
|
||||||
"@types/jasmine": "^2.8.2",
|
"@types/jasmine": "^2.8.2",
|
||||||
"@types/keytar": "^4.0.1",
|
"@types/keytar": "^4.0.1",
|
||||||
"@types/lunr": "2.1.5",
|
"@types/lunr": "2.1.5",
|
||||||
@ -72,6 +73,7 @@
|
|||||||
"electron-log": "2.2.14",
|
"electron-log": "2.2.14",
|
||||||
"electron-store": "1.3.0",
|
"electron-store": "1.3.0",
|
||||||
"electron-updater": "2.21.4",
|
"electron-updater": "2.21.4",
|
||||||
|
"form-data": "2.3.2",
|
||||||
"keytar": "4.1.0",
|
"keytar": "4.1.0",
|
||||||
"lunr": "2.1.6",
|
"lunr": "2.1.6",
|
||||||
"node-fetch": "2.1.2",
|
"node-fetch": "2.1.2",
|
||||||
|
@ -25,7 +25,8 @@ export abstract class CipherService {
|
|||||||
updateLastUsedDate: (id: string) => Promise<void>;
|
updateLastUsedDate: (id: string) => Promise<void>;
|
||||||
saveNeverDomain: (domain: string) => Promise<void>;
|
saveNeverDomain: (domain: string) => Promise<void>;
|
||||||
saveWithServer: (cipher: Cipher) => Promise<any>;
|
saveWithServer: (cipher: Cipher) => Promise<any>;
|
||||||
saveAttachmentWithServer: (cipher: Cipher, unencryptedFile: any) => Promise<any>;
|
saveAttachmentWithServer: (cipher: Cipher, unencryptedFile: any) => Promise<Cipher>;
|
||||||
|
saveAttachmentRawWithServer: (cipher: Cipher, filename: string, data: ArrayBuffer) => Promise<Cipher>;
|
||||||
upsert: (cipher: CipherData | CipherData[]) => Promise<any>;
|
upsert: (cipher: CipherData | CipherData[]) => Promise<any>;
|
||||||
replace: (ciphers: { [id: string]: CipherData; }) => Promise<any>;
|
replace: (ciphers: { [id: string]: CipherData; }) => Promise<any>;
|
||||||
clear: (userId: string) => Promise<any>;
|
clear: (userId: string) => Promise<any>;
|
||||||
|
@ -322,43 +322,58 @@ export class CipherService implements CipherServiceAbstraction {
|
|||||||
await this.upsert(data);
|
await this.upsert(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
saveAttachmentWithServer(cipher: Cipher, unencryptedFile: any): Promise<any> {
|
saveAttachmentWithServer(cipher: Cipher, unencryptedFile: any): Promise<Cipher> {
|
||||||
const self = this;
|
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const reader = new FileReader();
|
const reader = new FileReader();
|
||||||
reader.readAsArrayBuffer(unencryptedFile);
|
reader.readAsArrayBuffer(unencryptedFile);
|
||||||
|
|
||||||
reader.onload = async (evt: any) => {
|
reader.onload = async (evt: any) => {
|
||||||
const key = await self.cryptoService.getOrgKey(cipher.organizationId);
|
|
||||||
const encFileName = await self.cryptoService.encrypt(unencryptedFile.name, key);
|
|
||||||
const encData = await self.cryptoService.encryptToBytes(evt.target.result, key);
|
|
||||||
|
|
||||||
const fd = new FormData();
|
|
||||||
const blob = new Blob([encData], { type: 'application/octet-stream' });
|
|
||||||
fd.append('data', blob, encFileName.encryptedString);
|
|
||||||
|
|
||||||
let response: CipherResponse;
|
|
||||||
try {
|
try {
|
||||||
response = await self.apiService.postCipherAttachment(cipher.id, fd);
|
const cData = await this.saveAttachmentRawWithServer(cipher,
|
||||||
|
unencryptedFile.name, evt.target.result);
|
||||||
|
resolve(cData);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
reject((e as ErrorResponse).getSingleMessage());
|
reject(e);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const userId = await self.userService.getUserId();
|
|
||||||
const data = new CipherData(response, userId, cipher.collectionIds);
|
|
||||||
this.upsert(data);
|
|
||||||
resolve(new Cipher(data));
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
reader.onerror = (evt) => {
|
reader.onerror = (evt) => {
|
||||||
reject('Error reading file.');
|
reject('Error reading file.');
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async saveAttachmentRawWithServer(cipher: Cipher, filename: string, data: ArrayBuffer): Promise<Cipher> {
|
||||||
|
const key = await this.cryptoService.getOrgKey(cipher.organizationId);
|
||||||
|
const encFileName = await this.cryptoService.encrypt(filename, key);
|
||||||
|
const encData = await this.cryptoService.encryptToBytes(data, key);
|
||||||
|
|
||||||
|
const fd = new FormData();
|
||||||
|
try {
|
||||||
|
const blob = new Blob([encData], { type: 'application/octet-stream' });
|
||||||
|
fd.append('data', blob, encFileName.encryptedString);
|
||||||
|
} catch (e) {
|
||||||
|
if (Utils.isNode) {
|
||||||
|
fd.append('data', new Buffer(encData) as any, {
|
||||||
|
filename: encFileName.encryptedString,
|
||||||
|
contentType: 'application/octet-stream',
|
||||||
|
} as any);
|
||||||
|
} else {
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let response: CipherResponse;
|
||||||
|
try {
|
||||||
|
response = await this.apiService.postCipherAttachment(cipher.id, fd);
|
||||||
|
} catch (e) {
|
||||||
|
throw new Error((e as ErrorResponse).getSingleMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
const userId = await this.userService.getUserId();
|
||||||
|
const cData = new CipherData(response, userId, cipher.collectionIds);
|
||||||
|
this.upsert(cData);
|
||||||
|
return new Cipher(cData);
|
||||||
|
}
|
||||||
|
|
||||||
async upsert(cipher: CipherData | CipherData[]): Promise<any> {
|
async upsert(cipher: CipherData | CipherData[]): Promise<any> {
|
||||||
const userId = await this.userService.getUserId();
|
const userId = await this.userService.getUserId();
|
||||||
let ciphers = await this.storageService.get<{ [id: string]: CipherData; }>(
|
let ciphers = await this.storageService.get<{ [id: string]: CipherData; }>(
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import * as FormData from 'form-data';
|
||||||
import * as fe from 'node-fetch';
|
import * as fe from 'node-fetch';
|
||||||
|
|
||||||
import { ApiService } from './api.service';
|
import { ApiService } from './api.service';
|
||||||
@ -9,6 +10,7 @@ import { TokenService } from '../abstractions/token.service';
|
|||||||
(global as any).Request = fe.Request;
|
(global as any).Request = fe.Request;
|
||||||
(global as any).Response = fe.Response;
|
(global as any).Response = fe.Response;
|
||||||
(global as any).Headers = fe.Headers;
|
(global as any).Headers = fe.Headers;
|
||||||
|
(global as any).FormData = FormData;
|
||||||
|
|
||||||
export class NodeApiService extends ApiService {
|
export class NodeApiService extends ApiService {
|
||||||
constructor(tokenService: TokenService, platformUtilsService: PlatformUtilsService,
|
constructor(tokenService: TokenService, platformUtilsService: PlatformUtilsService,
|
||||||
|
Loading…
Reference in New Issue
Block a user