mirror of
https://github.com/fluxerapp/fluxer
synced 2026-10-17 13:05:32 +09:00
feat(api): redirect desktop downloads to pkgs (#2853)
This commit is contained in:
1 parent
487febac8e
commit
e2abfd476a
47 files changed
+679
-3940
No files matched your search
@@ -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: {
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
}
|
||||
@@ -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,
|
||||
|
||||
Reference in new issue
Block a user