mirror of
https://github.com/fluxerapp/fluxer
synced 2026-10-17 13:05:32 +09:00
fix(selfhost): branding image origins and theme colour (#3389)
This commit is contained in:
1 parent
cca8227ca6
commit
edc913096a
27 files changed
+724
-49
No files matched your search
@@ -362,4 +362,17 @@ describe('instance config billing on a hosted instance', () => {
|
||||
}).execute();
|
||||
expect(updated.app_public.branding.theme_color).toBe('#123456');
|
||||
});
|
||||
|
||||
it('rejects a theme colour that is not hex', async () => {
|
||||
const admin = await createAdmin(context.harness);
|
||||
for (const theme_color of ['rgb(123, 44, 228)', 'rebeccapurple', '#12345']) {
|
||||
await patchConfig(context.harness, admin, {app_public: {branding: {theme_color}}})
|
||||
.expect(HTTP_STATUS.BAD_REQUEST, APIErrorCodes.INVALID_FORM_BODY)
|
||||
.execute();
|
||||
}
|
||||
const cleared = await patchConfig(context.harness, admin, {
|
||||
app_public: {branding: {theme_color: null}},
|
||||
}).execute();
|
||||
expect(cleared.app_public.branding.theme_color).toBeNull();
|
||||
});
|
||||
});
|
||||
@@ -219,6 +219,33 @@ describe('InstanceConfigRepository', () => {
|
||||
expect(config.branding.product_name).toBe('Kept');
|
||||
});
|
||||
|
||||
it('serves the theme colour as six-digit hex and drops a stored value that is not hex', async () => {
|
||||
setCassandraQueryExecutorForTesting(new InMemoryCassandraQueryExecutor());
|
||||
const repository = createRepository(new MockKVProvider());
|
||||
|
||||
expect((await repository.setAppPublicConfig({branding: {theme_color: '7B2CE4'}})).branding.theme_color).toBe(
|
||||
'#7b2ce4',
|
||||
);
|
||||
expect((await repository.setAppPublicConfig({branding: {theme_color: '#AbC'}})).branding.theme_color).toBe(
|
||||
'#aabbcc',
|
||||
);
|
||||
|
||||
await repository.setConfig(APP_PUBLIC_CONFIG_KEY, JSON.stringify({branding: {theme_color: 'rgb(123, 44, 228)'}}));
|
||||
expect((await repository.getAppPublicConfig()).branding.theme_color).toBeNull();
|
||||
});
|
||||
|
||||
it('treats the black theme colour the setup wizard used to store as unset', async () => {
|
||||
setCassandraQueryExecutorForTesting(new InMemoryCassandraQueryExecutor());
|
||||
const repository = createRepository(new MockKVProvider());
|
||||
|
||||
await repository.setConfig(APP_PUBLIC_CONFIG_KEY, JSON.stringify({branding: {theme_color: '#000000'}}));
|
||||
expect((await repository.getAppPublicConfig()).branding.theme_color).toBeNull();
|
||||
expect((await repository.setAppPublicConfig({branding: {theme_color: '#000'}})).branding.theme_color).toBeNull();
|
||||
expect((await repository.setAppPublicConfig({branding: {theme_color: '#000001'}})).branding.theme_color).toBe(
|
||||
'#000001',
|
||||
);
|
||||
});
|
||||
|
||||
it('stores uploaded branding assets as references and resolves them against the current media endpoint', async () => {
|
||||
setCassandraQueryExecutorForTesting(new CountingInMemoryCassandraQueryExecutor());
|
||||
const repository = createRepository(new MockKVProvider());
|
||||
|
||||
@@ -410,6 +410,14 @@ function normalizeOptionalPublicString(value: string | null | undefined, fallbac
|
||||
return value === undefined ? fallback : normalizeOptionalString(value);
|
||||
}
|
||||
|
||||
function normalizeThemeColor(value: unknown): string | null {
|
||||
const match = /^#?([0-9a-f]{3}|[0-9a-f]{6})$/i.exec(normalizeOptionalString(value) ?? '');
|
||||
if (match === null) return null;
|
||||
const digits = match[1].toLowerCase();
|
||||
const color = `#${digits.length === 3 ? digits.replace(/./g, '$&$&') : digits}`;
|
||||
return color === '#000000' ? null : color;
|
||||
}
|
||||
|
||||
function getDefaultPremiumProductName(): string {
|
||||
return Config.instance.selfHosted ? 'Premium' : 'Plutonium';
|
||||
}
|
||||
@@ -423,7 +431,7 @@ function getDefaultAppPublicConfig(): InstanceAppPublicConfig {
|
||||
logo_url: normalizeOptionalString(Config.instance.branding.logoUrl),
|
||||
wordmark_url: normalizeOptionalString(Config.instance.branding.wordmarkUrl),
|
||||
favicon_url: normalizeOptionalString(Config.instance.branding.faviconUrl),
|
||||
theme_color: normalizeOptionalString(Config.instance.branding.themeColor),
|
||||
theme_color: normalizeThemeColor(Config.instance.branding.themeColor),
|
||||
status_page_url: normalizeOptionalString(Config.instance.branding.statusPageUrl),
|
||||
status_page_incident_history_url: normalizeOptionalString(Config.instance.branding.statusPageIncidentHistoryUrl),
|
||||
premium_product_name: getDefaultPremiumProductName(),
|
||||
@@ -740,7 +748,8 @@ function buildAppPublicConfig(config: z.infer<typeof StoredInstanceAppPublicSche
|
||||
logo_url: normalizeOptionalPublicString(branding.logo_url, defaults.branding.logo_url),
|
||||
wordmark_url: normalizeOptionalPublicString(branding.wordmark_url, defaults.branding.wordmark_url),
|
||||
favicon_url: normalizeOptionalPublicString(branding.favicon_url, defaults.branding.favicon_url),
|
||||
theme_color: normalizeOptionalPublicString(branding.theme_color, defaults.branding.theme_color),
|
||||
theme_color:
|
||||
branding.theme_color === undefined ? defaults.branding.theme_color : normalizeThemeColor(branding.theme_color),
|
||||
status_page_url: normalizeOptionalPublicString(branding.status_page_url, defaults.branding.status_page_url),
|
||||
status_page_incident_history_url: normalizeOptionalPublicString(
|
||||
branding.status_page_incident_history_url,
|
||||
|
||||
Reference in new issue
Block a user