|
|
@@ -2,8 +2,11 @@ import type { Response } from 'express';
|
|
|
|
|
|
import type { ExpressHttpHeader, IContentHeaders } from '~/server/interfaces/attachment';
|
|
|
import type { IAttachmentDocument } from '~/server/models/attachment';
|
|
|
+import type { ConfigManager } from '~/server/service/config-manager';
|
|
|
|
|
|
-import { INLINE_ALLOWLIST_MIME_TYPES } from './security'; // Adjust path if necessary
|
|
|
+import type { ConfigKey } from '../../config-manager/config-definition';
|
|
|
+
|
|
|
+import { DEFAULT_ALLOWLIST_MIME_TYPES, SAFE_INLINE_CONFIGURABLE_MIME_TYPES } from './security';
|
|
|
|
|
|
|
|
|
export class ContentHeaders implements IContentHeaders {
|
|
|
@@ -18,9 +21,13 @@ export class ContentHeaders implements IContentHeaders {
|
|
|
|
|
|
xContentTypeOptions?: ExpressHttpHeader<'X-Content-Type-Options'>;
|
|
|
|
|
|
+ private configManager: ConfigManager;
|
|
|
+
|
|
|
constructor(attachment: IAttachmentDocument, opts?: {
|
|
|
+ configManager: ConfigManager,
|
|
|
inline?: boolean,
|
|
|
}) {
|
|
|
+
|
|
|
const attachmentContentType = attachment.fileFormat;
|
|
|
const filename = attachment.originalName;
|
|
|
|
|
|
@@ -35,8 +42,24 @@ export class ContentHeaders implements IContentHeaders {
|
|
|
// Determine Content-Disposition based on allowlist and the 'inline' request flag
|
|
|
const requestedInline = opts?.inline ?? false;
|
|
|
|
|
|
- // Should only be inline if it was requested and MIME type is explicitly in the security allowlist.
|
|
|
- const shouldBeInline = requestedInline && INLINE_ALLOWLIST_MIME_TYPES.has(actualContentTypeString);
|
|
|
+ const configKey = `attachments:contentDisposition:${actualContentTypeString}:inline` as ConfigKey;
|
|
|
+
|
|
|
+ // Get current inline setting
|
|
|
+ const rawConfigValue = this.configManager.getConfig(configKey);
|
|
|
+
|
|
|
+ let isConfiguredInline: boolean;
|
|
|
+ if (typeof rawConfigValue === 'boolean') {
|
|
|
+ isConfiguredInline = rawConfigValue;
|
|
|
+ }
|
|
|
+
|
|
|
+ else {
|
|
|
+ isConfiguredInline = DEFAULT_ALLOWLIST_MIME_TYPES.has(actualContentTypeString);
|
|
|
+ }
|
|
|
+
|
|
|
+ // Final decision
|
|
|
+ const shouldBeInline = requestedInline
|
|
|
+ && isConfiguredInline
|
|
|
+ && SAFE_INLINE_CONFIGURABLE_MIME_TYPES.has(actualContentTypeString);
|
|
|
|
|
|
this.contentDisposition = {
|
|
|
field: 'Content-Disposition',
|