feat(api): redirect desktop downloads to pkgs (#2853)

This commit is contained in:
Hampus authored and GitHub committed 2026-09-20 01:20:30 +02:00
1 parent 487febac8e
commit e2abfd476a
47 files changed
+679 -3940

No files matched your search

-7
View File
@@ -92,7 +92,6 @@ function defaultConfig(): MasterConfig {
buckets: {
cdn: 'fluxer',
uploads: 'fluxer-uploads',
downloads: 'fluxer-downloads',
reports: 'fluxer-reports',
harvests: 'fluxer-harvests',
},
@@ -105,9 +104,7 @@ function defaultConfig(): MasterConfig {
max_inflight_requests: 512,
ip_ban_exempt_ips: [],
donation_proxy_key: '',
desktop_github_redirect_countries: [],
presigned_attachment_uploads_enabled: false,
presigned_downloads_enabled: false,
presigned_harvest_downloads_enabled: true,
unfurl_ignored_hosts: [],
embeds: {
@@ -646,10 +643,6 @@ function applyPublicPort(config: MasterConfig, endpoints: DerivedEndpoints): Mas
},
endpoints: normalizedEndpoints,
s3: config.s3 && {...config.s3, presigned_url_base: normalizeOptional(config.s3.presigned_url_base)},
s3_downloads: config.s3_downloads && {
...config.s3_downloads,
presigned_url_base: normalizeOptional(config.s3_downloads.presigned_url_base),
},
services: {
...config.services,
media_proxy: {
-11
View File
@@ -79,19 +79,10 @@ export interface MasterConfig {
buckets: {
cdn: string;
uploads: string;
downloads: string;
reports: string;
harvests: string;
};
};
s3_downloads?: {
endpoint: string;
presigned_url_base?: string;
force_path_style?: boolean;
region?: string;
access_key_id?: string;
secret_access_key?: string;
};
services: {
api: {
port: number;
@@ -100,9 +91,7 @@ export interface MasterConfig {
max_inflight_requests: number;
ip_ban_exempt_ips: Array<string>;
donation_proxy_key: string;
desktop_github_redirect_countries: Array<string>;
presigned_attachment_uploads_enabled: boolean;
presigned_downloads_enabled: boolean;
presigned_harvest_downloads_enabled: boolean;
unfurl_ignored_hosts: Array<string>;
embeds: {
@@ -1,47 +0,0 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import type {MasterConfig} from '@fluxer/config/src/MasterConfig';
export interface S3ProviderSettings {
endpoint: string;
presignedUrlBase?: string;
forcePathStyle: boolean;
region: string;
accessKeyId: string;
secretAccessKey: string;
}
export interface ResolvedDownloadsProvider {
settings: S3ProviderSettings;
isOverridden: boolean;
}
export function resolveDownloadsProvider(master: Pick<MasterConfig, 's3' | 's3_downloads'>): ResolvedDownloadsProvider {
const base = master.s3;
if (!base) {
throw new Error('S3 configuration is required to resolve the downloads provider');
}
const baseSettings: S3ProviderSettings = {
endpoint: base.endpoint,
presignedUrlBase: base.presigned_url_base,
forcePathStyle: base.force_path_style,
region: base.region,
accessKeyId: base.access_key_id,
secretAccessKey: base.secret_access_key,
};
const override = master.s3_downloads;
if (!override?.endpoint) {
return {settings: baseSettings, isOverridden: false};
}
return {
settings: {
endpoint: override.endpoint,
presignedUrlBase: override.presigned_url_base ?? undefined,
forcePathStyle: override.force_path_style ?? baseSettings.forcePathStyle,
region: override.region ?? baseSettings.region,
accessKeyId: override.access_key_id ?? baseSettings.accessKeyId,
secretAccessKey: override.secret_access_key ?? baseSettings.secretAccessKey,
},
isOverridden: true,
};
}
+10
View File
@@ -0,0 +1,10 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
export interface S3ProviderSettings {
endpoint: string;
presignedUrlBase?: string;
forcePathStyle: boolean;
region: string;
accessKeyId: string;
secretAccessKey: string;
}
@@ -1,63 +0,0 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import type {MasterConfig} from '@fluxer/config/src/MasterConfig';
import {resolveDownloadsProvider} from '@fluxer/config/src/S3DownloadsProvider';
import {describe, expect, test} from 'vitest';
const base: Pick<MasterConfig, 's3' | 's3_downloads'>['s3'] = {
endpoint: 'https://main.example.com',
presigned_url_base: 'https://public.example.com',
force_path_style: true,
region: 'us-east-1',
access_key_id: 'MAIN_KEY',
secret_access_key: 'MAIN_SECRET',
buckets: {cdn: 'cdn', uploads: 'uploads', downloads: 'downloads', reports: 'r', harvests: 'h'},
};
describe('resolveDownloadsProvider', () => {
test('falls back to the main provider when no override is set', () => {
const resolved = resolveDownloadsProvider({s3: base});
expect(resolved.isOverridden).toBe(false);
expect(resolved.settings.endpoint).toBe('https://main.example.com');
expect(resolved.settings.accessKeyId).toBe('MAIN_KEY');
expect(resolved.settings.secretAccessKey).toBe('MAIN_SECRET');
expect(resolved.settings.region).toBe('us-east-1');
expect(resolved.settings.presignedUrlBase).toBe('https://public.example.com');
});
test('ignores a partial override that does not set an endpoint', () => {
const resolved = resolveDownloadsProvider({s3: base, s3_downloads: {endpoint: '', access_key_id: 'OTHER'}});
expect(resolved.isOverridden).toBe(false);
expect(resolved.settings.accessKeyId).toBe('MAIN_KEY');
});
test('uses the override provider when an endpoint is set', () => {
const resolved = resolveDownloadsProvider({
s3: base,
s3_downloads: {
endpoint: 'https://downloads.example.net',
region: 'eu-central-1',
access_key_id: 'DL_KEY',
secret_access_key: 'DL_SECRET',
},
});
expect(resolved.isOverridden).toBe(true);
expect(resolved.settings.endpoint).toBe('https://downloads.example.net');
expect(resolved.settings.region).toBe('eu-central-1');
expect(resolved.settings.accessKeyId).toBe('DL_KEY');
});
test('inherits unspecified fields from the main provider', () => {
const resolved = resolveDownloadsProvider({s3: base, s3_downloads: {endpoint: 'https://downloads.example.net'}});
expect(resolved.isOverridden).toBe(true);
expect(resolved.settings.endpoint).toBe('https://downloads.example.net');
expect(resolved.settings.region).toBe('us-east-1');
expect(resolved.settings.accessKeyId).toBe('MAIN_KEY');
expect(resolved.settings.forcePathStyle).toBe(true);
});
test('does not inherit the main presigned base for an override provider', () => {
const resolved = resolveDownloadsProvider({s3: base, s3_downloads: {endpoint: 'https://downloads.example.net'}});
expect(resolved.settings.presignedUrlBase).toBeUndefined();
});
});
@@ -67,15 +67,8 @@ const NAMED_FLUXER_ENV_OVERRIDES: Record<string, NamedEnvOverride> = {
FLUXER_S3_SECRET_ACCESS_KEY: {path: ['s3', 'secret_access_key']},
FLUXER_S3_BUCKET_CDN: {path: ['s3', 'buckets', 'cdn']},
FLUXER_S3_BUCKET_UPLOADS: {path: ['s3', 'buckets', 'uploads']},
FLUXER_S3_BUCKET_DOWNLOADS: {path: ['s3', 'buckets', 'downloads']},
FLUXER_S3_BUCKET_REPORTS: {path: ['s3', 'buckets', 'reports']},
FLUXER_S3_BUCKET_HARVESTS: {path: ['s3', 'buckets', 'harvests']},
FLUXER_S3_DOWNLOADS_ENDPOINT: {path: ['s3_downloads', 'endpoint']},
FLUXER_S3_DOWNLOADS_PUBLIC_ENDPOINT: {path: ['s3_downloads', 'presigned_url_base']},
FLUXER_S3_DOWNLOADS_FORCE_PATH_STYLE: {path: ['s3_downloads', 'force_path_style'], parse: parseBoolean},
FLUXER_S3_DOWNLOADS_REGION: {path: ['s3_downloads', 'region']},
FLUXER_S3_DOWNLOADS_ACCESS_KEY_ID: {path: ['s3_downloads', 'access_key_id']},
FLUXER_S3_DOWNLOADS_SECRET_ACCESS_KEY: {path: ['s3_downloads', 'secret_access_key']},
FLUXER_NATS_URL: {path: ['services', 'nats', 'core_url']},
FLUXER_NATS_JETSTREAM_URL: {path: ['services', 'nats', 'jetstream_url']},
FLUXER_NATS_AUTH_TOKEN: {path: ['services', 'nats', 'auth_token']},
@@ -85,18 +78,10 @@ const NAMED_FLUXER_ENV_OVERRIDES: Record<string, NamedEnvOverride> = {
FLUXER_API_MAX_INFLIGHT_REQUESTS: {path: ['services', 'api', 'max_inflight_requests'], parse: parseInteger},
FLUXER_API_IP_BAN_EXEMPT_IPS: {path: ['services', 'api', 'ip_ban_exempt_ips'], parse: parseCsv},
FLUXER_API_DONATION_PROXY_KEY: {path: ['services', 'api', 'donation_proxy_key']},
FLUXER_API_DESKTOP_GITHUB_REDIRECT_COUNTRIES: {
path: ['services', 'api', 'desktop_github_redirect_countries'],
parse: parseCsv,
},
FLUXER_API_PRESIGNED_ATTACHMENT_UPLOADS_ENABLED: {
path: ['services', 'api', 'presigned_attachment_uploads_enabled'],
parse: parseBoolean,
},
FLUXER_API_PRESIGNED_DOWNLOADS_ENABLED: {
path: ['services', 'api', 'presigned_downloads_enabled'],
parse: parseBoolean,
},
FLUXER_API_PRESIGNED_HARVEST_DOWNLOADS_ENABLED: {
path: ['services', 'api', 'presigned_harvest_downloads_enabled'],
parse: parseBoolean,