diff --git a/sci-log-db/src/__tests__/unit/service.export-snippet.unit.ts b/sci-log-db/src/__tests__/unit/service.export-snippet.unit.ts
index bb2a5f6a..53239557 100644
--- a/sci-log-db/src/__tests__/unit/service.export-snippet.unit.ts
+++ b/sci-log-db/src/__tests__/unit/service.export-snippet.unit.ts
@@ -240,9 +240,13 @@ describe('Export service unit', function (this: Suite) {
const exportFile = await exportService['exportToPdf'](
paragraphs,
{exportFile: 'dir/file.pdf', exportDir: 'dir'},
+ {authorization: 'Bearer XXXX'},
'aTitle',
);
expect(addTitle.callCount).to.be.eql(1);
+ expect(exportService.authorizationHeader).to.be.eql({
+ authorization: 'Bearer XXXX',
+ });
expect(htmlToPDF.callCount).to.be.eql(o);
expect(exportFile).to.be.eql('dir/file.pdf');
});
@@ -341,6 +345,26 @@ describe('Export service unit', function (this: Suite) {
[['someFile_>_.pdf', 'accessHash2']],
],
},
+ {
+ input: [
+ {files: []},
+ '
someFile.pdf
',
+ ],
+ expected: [
+ 'attachments/someFile.pdf',
+ [['someFile.pdf', '111fd07c4f1f010a51e32b36']],
+ ],
+ },
+ {
+ input: [
+ {files: []},
+ 'someFile.pdf
',
+ ],
+ expected: [
+ 'someFile.pdf
',
+ [],
+ ],
+ },
].forEach((t, i) => {
it(`attachment ${i}`, async () => {
const element = textContentToHTML({textcontent: t.input[1]} as Paragraph);
@@ -357,12 +381,15 @@ describe('Export service unit', function (this: Suite) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
.resolves({arrayBuffer: async () => '' as any} as Response);
sandbox.stub(Buffer, 'from');
+ exportService.authorizationHeader = {authorization: 'Bearer XXXX'};
const writeFileSpy = sandbox.stub(fspromise, 'writeFile');
await exportService['downloadAttachment']('someDir', ['a', 'b']);
expect(writeFileSpy.calledWith('someDir/a', match.any)).to.be.eql(true);
- expect(responseSpy.calledWith('http://localhost:3000/images/b')).to.be.eql(
- true,
- );
+ expect(
+ responseSpy.calledWith('http://localhost:3000/images/b', {
+ headers: {authorization: 'Bearer XXXX'},
+ }),
+ ).to.be.eql(true);
});
[
@@ -394,4 +421,34 @@ describe('Export service unit', function (this: Suite) {
).to.eql(t.expected[2]);
});
});
+
+ [
+ {input: [null], expected: undefined},
+ {input: ['some'], expected: undefined},
+ {input: ['https://abc'], expected: undefined},
+ {input: ['http://abc'], expected: undefined},
+ {input: ['http://abc/download'], expected: undefined},
+ {input: ['http://abc/download/123'], expected: undefined},
+ {
+ input: ['http://abc/download/111fd07c4f1f010a51e32b36'],
+ expected: '111fd07c4f1f010a51e32b36',
+ },
+ {input: ['file:somefile', []], expected: undefined},
+ {
+ input: [
+ 'file:somefile',
+ [{fileHash: 'somefile', accessHash: 'accessHash'}],
+ ],
+ expected: 'accessHash',
+ },
+ ].forEach((t, i) => {
+ it(`attachmentDownloadUrl ${i}`, async () => {
+ expect(
+ exportService['attachmentDownloadUrl'](
+ t.input[0] as string | null,
+ t.input[1] as {fileHash?: string; accessHash?: string}[] | undefined,
+ ),
+ ).to.eql(t.expected);
+ });
+ });
});
diff --git a/sci-log-db/src/mixins/basesnippet.repository-mixin.ts b/sci-log-db/src/mixins/basesnippet.repository-mixin.ts
index af45535e..7d44d808 100644
--- a/sci-log-db/src/mixins/basesnippet.repository-mixin.ts
+++ b/sci-log-db/src/mixins/basesnippet.repository-mixin.ts
@@ -452,6 +452,7 @@ function ExportRepositoryMixin<
const outFile = await exportService.exportToPdf(
snippets as unknown as Paragraph[],
{exportFile, exportDir},
+ _.pick(response?.req?.headers, 'authorization'),
parentName,
);
response.download(outFile, (err, path = exportDir) => {
diff --git a/sci-log-db/src/services/export-snippets.service.ts b/sci-log-db/src/services/export-snippets.service.ts
index fa252122..dd58e202 100644
--- a/sci-log-db/src/services/export-snippets.service.ts
+++ b/sci-log-db/src/services/export-snippets.service.ts
@@ -36,6 +36,7 @@ export class ExportService {
subsnippetCounter: number;
attachments: string[][] = [];
attachmentsFolder = 'attachments';
+ authorizationHeader: {authorization?: string};
constructor(
@inject(RestBindings.SERVER)
@@ -228,20 +229,40 @@ export class ExportService {
};
private attachment = (snippet: Paragraph, element: Element) => {
- snippet.files?.map(fileSnippet => {
- const fileLinkElement = element.querySelector(
- `.fileLink[href='file:${fileSnippet.fileHash}']`,
- );
- if (!fileLinkElement) return;
+ element.querySelectorAll('.fileLink').forEach(fileLinkElement => {
+ const href = fileLinkElement.getAttribute('href');
+ const downloadUrl = this.attachmentDownloadUrl(href, snippet.files);
+ if (!downloadUrl) return;
const attachment = fileLinkElement.textContent ?? '';
const attachmentElement = this.document.createElement('fileLink');
attachmentElement.innerHTML = `${this.attachmentsFolder}/${fileLinkElement.innerHTML}`;
fileLinkElement.replaceWith(attachmentElement);
- this.attachments.push([attachment, fileSnippet.accessHash as string]);
+ this.attachments.push([attachment, downloadUrl]);
});
return element;
};
+ private attachmentDownloadUrl(
+ href: string | null,
+ files: {fileHash?: string; accessHash?: string}[] | undefined,
+ ) {
+ let accessHash: string | undefined;
+ if (href?.startsWith('https://') || href?.startsWith('http://')) {
+ const objectId = require('mongodb').ObjectId;
+ const hrefParts = href.split('/');
+ const fileId = hrefParts.pop();
+ if (objectId.isValid(fileId) && hrefParts.pop() === 'download')
+ return fileId;
+ return;
+ } else if (
+ files?.some(
+ f => `file:${f.fileHash}` === href && (accessHash = f.accessHash),
+ )
+ )
+ return accessHash;
+ return;
+ }
+
private countSnippets(linkType?: LinkType) {
let counter: number | string = '';
if (linkType === 'paragraph') {
@@ -264,8 +285,10 @@ export class ExportService {
async exportToPdf(
snippets: Paragraph[],
exportPath: {exportFile: string; exportDir: string},
+ authorizationHeader: {authorization?: string},
title?: string,
) {
+ this.authorizationHeader = authorizationHeader;
const browser = await puppeteerLaunc({
executablePath: process.env.CHROME_BIN,
args: ['--no-sandbox'],
@@ -320,7 +343,9 @@ export class ExportService {
attachmentDir: string,
attachment: string[],
) {
- const response = await fetch(`${this.server.url}/images/${attachment[1]}`);
+ const response = await fetch(`${this.server.url}/images/${attachment[1]}`, {
+ headers: this.authorizationHeader,
+ });
const buffer = Buffer.from(await response.arrayBuffer());
const destinationFile = `${attachmentDir}/${attachment[0]}`;
await writeFile(destinationFile, buffer);