sqlite
This commit is contained in:
@@ -1,48 +1,18 @@
|
||||
import { createHash } from 'node:crypto';
|
||||
import sharp from 'sharp';
|
||||
import generateDocumentThumb from '../../util/generateDocumentThumb.js';
|
||||
import {
|
||||
CREATE_FILE,
|
||||
CREATE_ATTACHMENT,
|
||||
GET_NEXT_SORT,
|
||||
} from '../../providers/mssql/queries/manifestattachment.js';
|
||||
import * as mssqlQueries from '../../providers/mssql/queries/manifestattachment.js';
|
||||
import * as sqliteQueries from '../../providers/sqlite3/queries/manifestattachment.js';
|
||||
import resolveSelectedCompanyAccess from '../companyuser/resolveSelectedCompanyAccess.js';
|
||||
import resolveManifestAccess from './resolveManifestAccess.js';
|
||||
import request from '../request.js';
|
||||
import makeRunner from '../runner.js';
|
||||
|
||||
export default function add(pool) {
|
||||
const access = resolveSelectedCompanyAccess(pool);
|
||||
const manifestAccess = resolveManifestAccess(pool);
|
||||
export default function add(provider) {
|
||||
const access = resolveSelectedCompanyAccess(provider);
|
||||
const manifestAccess = resolveManifestAccess(provider);
|
||||
const isSqlite = provider?.dialect === 'sqlite3';
|
||||
const queries = isSqlite ? sqliteQueries : mssqlQueries;
|
||||
|
||||
/**
|
||||
* Attaches a file to an existing manifest.
|
||||
*
|
||||
* @param {number} googleAuthId - The id of the Google auth user.
|
||||
* @param {number} manifestId - The id of the manifest.
|
||||
* @param {object} input - The file data.
|
||||
* @param {string} input.mimetype - The MIME type of the file (e.g. `'application/pdf'`).
|
||||
* @param {string} input.name - The file name.
|
||||
* @param {Buffer} input.content - The file content.
|
||||
* @param {number} [input.sort] - Optional display sort order.
|
||||
* @param {number} [input.size] - Optional file size in bytes (defaults to content length).
|
||||
* @param {Date|string} [input.created] - Optional creation timestamp (defaults to current date).
|
||||
* @param {Date|string} [input.modified] - Optional modified timestamp (defaults to created date).
|
||||
* @param {string} [input.hash] - The file hash (auto-computed SHA-256 if omitted).
|
||||
* @param {Buffer} [input.thumbavif] - Optional AVIF thumbnail buffer.
|
||||
* @param {number} [input.thumbx] - Optional thumbnail width.
|
||||
* @param {number} [input.thumby] - Optional thumbnail height.
|
||||
* @param {object} [input.meta] - Optional string key/value metadata stored on the file row.
|
||||
* @returns {Promise<{id: number, manifestId: number, fileId: number, sort: number, hash: string, mimetype: string, name: string, size: number, created: Date, modified: Date, thumbavif: Buffer|null, thumbx: number|null, thumby: number|null, meta: object|null}>} The created attachment record.
|
||||
* @throws {Error} If the manifest is not found or file input is invalid.
|
||||
*
|
||||
* @example
|
||||
* const attachment = await store.manifestattachment.add(42, 1, {
|
||||
* mimetype: 'application/pdf',
|
||||
* name: 'invoice.pdf',
|
||||
* content: fileBuffer,
|
||||
* });
|
||||
* // => { id, manifestId, fileId, sort, hash, mimetype, name, size, created, modified, thumbavif, thumbx, thumby }
|
||||
*/
|
||||
return async (googleAuthId, manifestId, input, ...rest) => {
|
||||
let rawMimetype, rawName, rawContent, rawHash, rawThumbavif, rawThumbx, rawThumby, rawSort, rawSize, rawCreated, rawModified, rawMeta;
|
||||
if (typeof input === 'object' && input !== null && !Buffer.isBuffer(input)) {
|
||||
@@ -166,43 +136,46 @@ export default function add(pool) {
|
||||
const { companyId } = await access(googleAuthId);
|
||||
await manifestAccess(companyId, manifestId);
|
||||
|
||||
const tx = pool.transaction();
|
||||
await tx.begin();
|
||||
|
||||
try {
|
||||
const run = async (runner) => {
|
||||
let sort = rawSort;
|
||||
if (sort === undefined || sort === null) {
|
||||
const sortRes = await request(pool, tx)
|
||||
.input('manifestId', manifestId)
|
||||
.query(GET_NEXT_SORT);
|
||||
sort = sortRes.recordset[0].sort;
|
||||
const sortRes = await runner(queries.GET_NEXT_SORT, { manifestId });
|
||||
sort = sortRes.rows[0].sort;
|
||||
}
|
||||
|
||||
const fileRes = await request(pool, tx)
|
||||
.input('hash', hash)
|
||||
.input('mimetype', mimetype)
|
||||
.input('name', name)
|
||||
.input('size', size)
|
||||
.input('created', created)
|
||||
.input('modified', modified)
|
||||
.input('content', content)
|
||||
.input('thumbavif', thumbavif)
|
||||
.input('thumbx', thumbx)
|
||||
.input('thumby', thumby)
|
||||
.input('meta', meta === null ? null : JSON.stringify(meta))
|
||||
.query(CREATE_FILE);
|
||||
if (isSqlite) {
|
||||
if (runner.writeFileContent) {
|
||||
await runner.writeFileContent(hash, content, mimetype);
|
||||
if (thumbavif) await runner.writeThumbAvif(hash, thumbavif);
|
||||
} else if (provider?.writeFileContent) {
|
||||
await provider.writeFileContent(hash, content, mimetype);
|
||||
if (thumbavif) await provider.writeThumbAvif(hash, thumbavif);
|
||||
}
|
||||
}
|
||||
|
||||
const fileId = fileRes.recordset[0].id;
|
||||
const fileRes = await runner(queries.CREATE_FILE, {
|
||||
hash,
|
||||
mimetype,
|
||||
name,
|
||||
size,
|
||||
created,
|
||||
modified,
|
||||
content,
|
||||
thumbavif,
|
||||
thumbx,
|
||||
thumby,
|
||||
meta: meta === null ? null : JSON.stringify(meta),
|
||||
});
|
||||
|
||||
const attachmentRes = await request(pool, tx)
|
||||
.input('manifestId', manifestId)
|
||||
.input('fileId', fileId)
|
||||
.input('sort', sort)
|
||||
.query(CREATE_ATTACHMENT);
|
||||
const fileId = fileRes.rows[0]?.id ?? fileRes.insertId;
|
||||
|
||||
const attachmentId = attachmentRes.recordset[0].id;
|
||||
const attachmentRes = await runner(queries.CREATE_ATTACHMENT, {
|
||||
manifestId,
|
||||
fileId,
|
||||
sort,
|
||||
});
|
||||
|
||||
await tx.commit();
|
||||
const attachmentId = attachmentRes.rows[0]?.id ?? attachmentRes.insertId;
|
||||
|
||||
return {
|
||||
id: attachmentId,
|
||||
@@ -220,13 +193,11 @@ export default function add(pool) {
|
||||
thumby,
|
||||
meta,
|
||||
};
|
||||
} catch (err) {
|
||||
try {
|
||||
await tx.rollback();
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
throw err;
|
||||
};
|
||||
|
||||
if (typeof provider?.transaction === 'function') {
|
||||
return provider.transaction(run);
|
||||
}
|
||||
return run(makeRunner(provider));
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
import { GET_BY_ID } from '../../providers/mssql/queries/manifestattachment.js';
|
||||
import { GET_BY_ID as MSSQL_GET_BY_ID } from '../../providers/mssql/queries/manifestattachment.js';
|
||||
import { GET_BY_ID as SQLITE_GET_BY_ID } from '../../providers/sqlite3/queries/manifestattachment.js';
|
||||
import resolveSelectedCompanyAccess from '../companyuser/resolveSelectedCompanyAccess.js';
|
||||
import resolveManifestAccess from './resolveManifestAccess.js';
|
||||
import { parseMeta } from './listByManifestId.js';
|
||||
import request from '../request.js';
|
||||
import makeRunner from '../runner.js';
|
||||
|
||||
export default function getById(pool) {
|
||||
const access = resolveSelectedCompanyAccess(pool);
|
||||
const manifestAccess = resolveManifestAccess(pool);
|
||||
export default function getById(provider) {
|
||||
const access = resolveSelectedCompanyAccess(provider);
|
||||
const manifestAccess = resolveManifestAccess(provider);
|
||||
const isSqlite = provider?.dialect === 'sqlite3';
|
||||
const sql = isSqlite ? SQLITE_GET_BY_ID : MSSQL_GET_BY_ID;
|
||||
|
||||
/**
|
||||
* Gets an attachment for a manifest by its attachment ID or file ID, including full file content.
|
||||
@@ -14,6 +17,7 @@ export default function getById(pool) {
|
||||
* @param {number} googleAuthId - The id of the Google auth user.
|
||||
* @param {number} manifestId - The manifest ID.
|
||||
* @param {number} id - The attachment ID or file ID.
|
||||
* @param {object} [tx] - Optional transaction.
|
||||
* @returns {Promise<{id: number, manifestId: number, fileId: number, sort: number, hash: string, mimetype: string, name: string, size: number, created: Date, modified: Date, content: Buffer, thumbavif: Buffer|null, thumbx: number|null, thumby: number|null, meta: object|null}>} The attachment record with binary content.
|
||||
* @throws {Error} If the manifest or attachment is not found, or user is not authorized.
|
||||
*
|
||||
@@ -21,24 +25,32 @@ export default function getById(pool) {
|
||||
* const attachment = await store.manifestattachment.getById(42, 1, 5);
|
||||
* // => { id, manifestId, fileId, sort, hash, mimetype, name, size, created, modified, content, thumbavif, thumbx, thumby }
|
||||
*/
|
||||
return async (googleAuthId, manifestId, id) => {
|
||||
return async (googleAuthId, manifestId, id, tx) => {
|
||||
if (!Number.isFinite(id)) {
|
||||
throw new Error('Attachment not found');
|
||||
}
|
||||
|
||||
const { companyId } = await access(googleAuthId);
|
||||
await manifestAccess(companyId, manifestId);
|
||||
const runner = makeRunner(provider, tx);
|
||||
const { companyId } = await access(googleAuthId, runner);
|
||||
await manifestAccess(companyId, manifestId, runner);
|
||||
|
||||
const res = await request(pool)
|
||||
.input('manifestId', manifestId)
|
||||
.input('id', id)
|
||||
.query(GET_BY_ID);
|
||||
const res = await runner.query(sql, {
|
||||
manifestId,
|
||||
id,
|
||||
});
|
||||
|
||||
const row = res.recordset[0];
|
||||
const row = res.rows[0];
|
||||
if (!row) {
|
||||
throw new Error('Attachment not found');
|
||||
}
|
||||
|
||||
let content = row.content;
|
||||
let thumbavif = row.thumbavif ?? null;
|
||||
if (isSqlite) {
|
||||
content = await (runner.readFileContent ? runner.readFileContent(row.hash, row.mimetype) : provider.readFileContent?.(row.hash, row.mimetype));
|
||||
thumbavif = await (runner.readThumbAvif ? runner.readThumbAvif(row.hash) : provider.readThumbAvif?.(row.hash));
|
||||
}
|
||||
|
||||
return {
|
||||
id: row.id,
|
||||
manifestId: row.manifestId,
|
||||
@@ -50,11 +62,12 @@ export default function getById(pool) {
|
||||
size: Number(row.size),
|
||||
created: row.created,
|
||||
modified: row.modified,
|
||||
content: row.content,
|
||||
thumbavif: row.thumbavif ?? null,
|
||||
content,
|
||||
thumbavif,
|
||||
thumbx: row.thumbx ?? null,
|
||||
thumby: row.thumby ?? null,
|
||||
meta: parseMeta(row.meta),
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { LIST_BY_MANIFEST } from '../../providers/mssql/queries/manifestattachment.js';
|
||||
import { LIST_BY_MANIFEST as MSSQL_LIST } from '../../providers/mssql/queries/manifestattachment.js';
|
||||
import { LIST_BY_MANIFEST as SQLITE_LIST } from '../../providers/sqlite3/queries/manifestattachment.js';
|
||||
import resolveSelectedCompanyAccess from '../companyuser/resolveSelectedCompanyAccess.js';
|
||||
import resolveManifestAccess from './resolveManifestAccess.js';
|
||||
import request from '../request.js';
|
||||
import makeRunner from '../runner.js';
|
||||
|
||||
/** Parse the file.meta JSON text column into an object (string key/value). */
|
||||
export function parseMeta(raw) {
|
||||
@@ -34,15 +35,18 @@ function shape(row) {
|
||||
};
|
||||
}
|
||||
|
||||
export default function listByManifestId(pool) {
|
||||
const access = resolveSelectedCompanyAccess(pool);
|
||||
const manifestAccess = resolveManifestAccess(pool);
|
||||
export default function listByManifestId(provider) {
|
||||
const access = resolveSelectedCompanyAccess(provider);
|
||||
const manifestAccess = resolveManifestAccess(provider);
|
||||
const isSqlite = provider?.dialect === 'sqlite3';
|
||||
const sql = isSqlite ? SQLITE_LIST : MSSQL_LIST;
|
||||
|
||||
/**
|
||||
* Lists all attachments for a given manifest, without loading their full binary content.
|
||||
*
|
||||
* @param {number} googleAuthId - The id of the Google auth user.
|
||||
* @param {number} manifestId - The manifest ID.
|
||||
* @param {object} [tx] - Optional transaction.
|
||||
* @returns {Promise<Array<{id: number, manifestId: number, fileId: number, sort: number, hash: string, mimetype: string, name: string, size: number, created: Date, modified: Date, thumbavif: Buffer|null, thumbx: number|null, thumby: number|null, meta: object|null}>>} A list of attachment metadata objects.
|
||||
* @throws {Error} If the manifest is not found or the user is not authorized.
|
||||
*
|
||||
@@ -50,14 +54,29 @@ export default function listByManifestId(pool) {
|
||||
* const attachments = await store.manifestattachment.listByManifestId(42, 1);
|
||||
* // => [{ id, manifestId, fileId, sort, hash, mimetype, name, size, created, modified, thumbavif, thumbx, thumby }]
|
||||
*/
|
||||
return async (googleAuthId, manifestId) => {
|
||||
const { companyId } = await access(googleAuthId);
|
||||
await manifestAccess(companyId, manifestId);
|
||||
return async (googleAuthId, manifestId, tx) => {
|
||||
const runner = makeRunner(provider, tx);
|
||||
const { companyId } = await access(googleAuthId, runner);
|
||||
await manifestAccess(companyId, manifestId, runner);
|
||||
|
||||
const res = await request(pool)
|
||||
.input('manifestId', manifestId)
|
||||
.query(LIST_BY_MANIFEST);
|
||||
const res = await runner.query(sql, {
|
||||
manifestId,
|
||||
});
|
||||
|
||||
return res.recordset.map(shape);
|
||||
const rows = await Promise.all(
|
||||
res.rows.map(async (row) => {
|
||||
let thumbavif = row.thumbavif ?? null;
|
||||
if (isSqlite) {
|
||||
thumbavif = await (runner.readThumbAvif ? runner.readThumbAvif(row.hash) : provider.readThumbAvif?.(row.hash));
|
||||
}
|
||||
return shape({
|
||||
...row,
|
||||
thumbavif,
|
||||
});
|
||||
}),
|
||||
);
|
||||
|
||||
return rows;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -1,15 +1,25 @@
|
||||
import {
|
||||
LIST_IDS_BY_MANIFEST,
|
||||
SET_TEMP_SORTS,
|
||||
UPDATE_SORT,
|
||||
LIST_IDS_BY_MANIFEST as MSSQL_LIST_IDS,
|
||||
SET_TEMP_SORTS as MSSQL_SET_TEMP_SORTS,
|
||||
UPDATE_SORT as MSSQL_UPDATE_SORT,
|
||||
} from '../../providers/mssql/queries/manifestattachment.js';
|
||||
import {
|
||||
LIST_IDS_BY_MANIFEST as SQLITE_LIST_IDS,
|
||||
SET_TEMP_SORTS as SQLITE_SET_TEMP_SORTS,
|
||||
UPDATE_SORT as SQLITE_UPDATE_SORT,
|
||||
} from '../../providers/sqlite3/queries/manifestattachment.js';
|
||||
import resolveSelectedCompanyAccess from '../companyuser/resolveSelectedCompanyAccess.js';
|
||||
import resolveManifestAccess from './resolveManifestAccess.js';
|
||||
import request from '../request.js';
|
||||
import makeRunner from '../runner.js';
|
||||
|
||||
export default function order(pool) {
|
||||
const access = resolveSelectedCompanyAccess(pool);
|
||||
const manifestAccess = resolveManifestAccess(pool);
|
||||
export default function order(provider) {
|
||||
const access = resolveSelectedCompanyAccess(provider);
|
||||
const manifestAccess = resolveManifestAccess(provider);
|
||||
const isSqlite = provider?.dialect === 'sqlite3';
|
||||
|
||||
const listIdsSql = isSqlite ? SQLITE_LIST_IDS : MSSQL_LIST_IDS;
|
||||
const setTempSortsSql = isSqlite ? SQLITE_SET_TEMP_SORTS : MSSQL_SET_TEMP_SORTS;
|
||||
const updateSortSql = isSqlite ? SQLITE_UPDATE_SORT : MSSQL_UPDATE_SORT;
|
||||
|
||||
/**
|
||||
* Reorders the attachments of a manifest.
|
||||
@@ -18,6 +28,7 @@ export default function order(pool) {
|
||||
* @param {number} manifestId - The manifest ID.
|
||||
* @param {object|Array<number>} input - The reorder input or array of IDs.
|
||||
* @param {Array<number>} [input.ids] - The attachment ids in their new order.
|
||||
* @param {object} [tx] - Optional transaction to run within.
|
||||
* @returns {Promise<{ids: Array<number>}>} The applied order.
|
||||
* @throws {Error} If the order is invalid.
|
||||
*
|
||||
@@ -25,64 +36,60 @@ export default function order(pool) {
|
||||
* const result = await store.manifestattachment.order(42, 1, { ids: [12, 10, 15] });
|
||||
* // => { ids: [12, 10, 15] }
|
||||
*/
|
||||
return async (googleAuthId, manifestId, input) => {
|
||||
return async (googleAuthId, manifestId, input, tx) => {
|
||||
const rawIds = Array.isArray(input) ? input : input?.ids;
|
||||
if (!Array.isArray(rawIds)) {
|
||||
throw new Error('Invalid attachment order');
|
||||
}
|
||||
|
||||
const { companyId } = await access(googleAuthId);
|
||||
await manifestAccess(companyId, manifestId);
|
||||
const runOrder = async (runner) => {
|
||||
const { companyId } = await access(googleAuthId, runner);
|
||||
await manifestAccess(companyId, manifestId, runner);
|
||||
|
||||
const current = await pool
|
||||
.request()
|
||||
.input('manifestId', manifestId)
|
||||
.query(LIST_IDS_BY_MANIFEST);
|
||||
const current = await runner.query(listIdsSql, {
|
||||
manifestId,
|
||||
});
|
||||
|
||||
const existing = new Set(current.recordset.map((r) => r.id));
|
||||
const existing = new Set(current.rows.map((r) => r.id));
|
||||
|
||||
if (rawIds.length !== existing.size) {
|
||||
throw new Error('Invalid attachment order');
|
||||
}
|
||||
|
||||
const seen = new Set();
|
||||
for (const id of rawIds) {
|
||||
if (!Number.isFinite(id) || !existing.has(id) || seen.has(id)) {
|
||||
if (rawIds.length !== existing.size) {
|
||||
throw new Error('Invalid attachment order');
|
||||
}
|
||||
seen.add(id);
|
||||
}
|
||||
|
||||
const tx = pool.transaction();
|
||||
await tx.begin();
|
||||
const seen = new Set();
|
||||
for (const id of rawIds) {
|
||||
if (!Number.isFinite(id) || !existing.has(id) || seen.has(id)) {
|
||||
throw new Error('Invalid attachment order');
|
||||
}
|
||||
seen.add(id);
|
||||
}
|
||||
|
||||
try {
|
||||
await request(pool, tx)
|
||||
.input('manifestId', manifestId)
|
||||
.query(SET_TEMP_SORTS);
|
||||
await runner.query(setTempSortsSql, {
|
||||
manifestId,
|
||||
});
|
||||
|
||||
for (let sort = 0; sort < rawIds.length; sort++) {
|
||||
const updateRes = await request(pool, tx)
|
||||
.input('id', rawIds[sort])
|
||||
.input('manifestId', manifestId)
|
||||
.input('sort', sort)
|
||||
.query(UPDATE_SORT);
|
||||
const updateRes = await runner.query(updateSortSql, {
|
||||
id: rawIds[sort],
|
||||
manifestId,
|
||||
sort,
|
||||
});
|
||||
|
||||
if (!updateRes.rowsAffected[0]) {
|
||||
if (!updateRes.rowsAffected) {
|
||||
throw new Error('Invalid attachment order');
|
||||
}
|
||||
}
|
||||
|
||||
await tx.commit();
|
||||
|
||||
return { ids: rawIds };
|
||||
} catch (err) {
|
||||
try {
|
||||
await tx.rollback();
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
throw err;
|
||||
};
|
||||
|
||||
if (tx) {
|
||||
return runOrder(makeRunner(provider, tx));
|
||||
}
|
||||
if (typeof provider?.transaction === 'function') {
|
||||
return provider.transaction(runOrder);
|
||||
}
|
||||
return runOrder(makeRunner(provider));
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +1,21 @@
|
||||
import { FIND_ATTACHMENT, DELETE_FILE } from '../../providers/mssql/queries/manifestattachment.js';
|
||||
import {
|
||||
FIND_ATTACHMENT as MSSQL_FIND,
|
||||
DELETE_FILE as MSSQL_DELETE,
|
||||
} from '../../providers/mssql/queries/manifestattachment.js';
|
||||
import {
|
||||
FIND_ATTACHMENT as SQLITE_FIND,
|
||||
DELETE_FILE as SQLITE_DELETE,
|
||||
} from '../../providers/sqlite3/queries/manifestattachment.js';
|
||||
import resolveSelectedCompanyAccess from '../companyuser/resolveSelectedCompanyAccess.js';
|
||||
import resolveManifestAccess from './resolveManifestAccess.js';
|
||||
import request from '../request.js';
|
||||
import makeRunner from '../runner.js';
|
||||
|
||||
export default function remove(pool) {
|
||||
const access = resolveSelectedCompanyAccess(pool);
|
||||
const manifestAccess = resolveManifestAccess(pool);
|
||||
export default function remove(provider) {
|
||||
const access = resolveSelectedCompanyAccess(provider);
|
||||
const manifestAccess = resolveManifestAccess(provider);
|
||||
const isSqlite = provider?.dialect === 'sqlite3';
|
||||
const findSql = isSqlite ? SQLITE_FIND : MSSQL_FIND;
|
||||
const deleteSql = isSqlite ? SQLITE_DELETE : MSSQL_DELETE;
|
||||
|
||||
/**
|
||||
* Removes a file attachment from a manifest and deletes the underlying file.
|
||||
@@ -13,32 +23,43 @@ export default function remove(pool) {
|
||||
* @param {number} googleAuthId - The id of the Google auth user.
|
||||
* @param {number} manifestId - The manifest ID.
|
||||
* @param {number} id - The attachment ID or file ID to remove.
|
||||
* @param {object} [tx] - Optional transaction.
|
||||
* @returns {Promise<void>}
|
||||
* @throws {Error} If the manifest or attachment is not found, or user is not authorized.
|
||||
*
|
||||
* @example
|
||||
* await store.manifestattachment.remove(42, 1, 5);
|
||||
*/
|
||||
return async (googleAuthId, manifestId, id) => {
|
||||
return async (googleAuthId, manifestId, id, tx) => {
|
||||
if (!Number.isFinite(id)) {
|
||||
throw new Error('Attachment not found');
|
||||
}
|
||||
|
||||
const { companyId } = await access(googleAuthId);
|
||||
await manifestAccess(companyId, manifestId);
|
||||
const runner = makeRunner(provider, tx);
|
||||
const { companyId } = await access(googleAuthId, runner);
|
||||
await manifestAccess(companyId, manifestId, runner);
|
||||
|
||||
const findRes = await request(pool)
|
||||
.input('manifestId', manifestId)
|
||||
.input('id', id)
|
||||
.query(FIND_ATTACHMENT);
|
||||
const findRes = await runner.query(findSql, {
|
||||
manifestId,
|
||||
id,
|
||||
});
|
||||
|
||||
const row = findRes.recordset[0];
|
||||
const row = findRes.rows[0];
|
||||
if (!row) {
|
||||
throw new Error('Attachment not found');
|
||||
}
|
||||
|
||||
await request(pool)
|
||||
.input('fileId', row.fileId)
|
||||
.query(DELETE_FILE);
|
||||
await runner.query(deleteSql, {
|
||||
fileId: row.fileId,
|
||||
});
|
||||
|
||||
if (isSqlite && row.hash) {
|
||||
if (runner.deleteFile) {
|
||||
await runner.deleteFile(row.hash);
|
||||
} else if (provider?.deleteFile) {
|
||||
await provider.deleteFile(row.hash);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -1,22 +1,27 @@
|
||||
import { CHECK_MANIFEST_ACCESS } from '../../providers/mssql/queries/manifestattachment.js';
|
||||
import request from '../request.js';
|
||||
import { CHECK_MANIFEST_ACCESS as MSSQL_CHECK } from '../../providers/mssql/queries/manifestattachment.js';
|
||||
import { CHECK_MANIFEST_ACCESS as SQLITE_CHECK } from '../../providers/sqlite3/queries/manifestattachment.js';
|
||||
import makeRunner from '../runner.js';
|
||||
|
||||
/** Ensure manifest belongs to company. Throws Manifest not found. */
|
||||
export default function resolveManifestAccess(pool) {
|
||||
export default function resolveManifestAccess(provider) {
|
||||
const sql = provider?.dialect === 'sqlite3' ? SQLITE_CHECK : MSSQL_CHECK;
|
||||
|
||||
return async (companyId, manifestId, tx) => {
|
||||
if (!Number.isFinite(manifestId)) {
|
||||
throw new Error('Manifest not found');
|
||||
}
|
||||
|
||||
const result = await request(pool, tx)
|
||||
.input('manifestId', manifestId)
|
||||
.input('companyId', companyId)
|
||||
.query(CHECK_MANIFEST_ACCESS);
|
||||
const runner = makeRunner(provider, tx);
|
||||
const result = await runner.query(sql, {
|
||||
manifestId,
|
||||
companyId,
|
||||
});
|
||||
|
||||
const row = result.recordset[0];
|
||||
const row = result.rows[0];
|
||||
if (!row) {
|
||||
throw new Error('Manifest not found');
|
||||
}
|
||||
return row;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user