feat: add ability to search and select icons from selfh.st (#1807)

This commit is contained in:
Elias Schneider
2026-10-04 20:40:41 +02:00
committed by GitHub
parent e7d77d8a9d
commit 1be9ba9991
30 changed files with 1506 additions and 247 deletions
+10 -2
View File
@@ -8,6 +8,7 @@ import type {
OidcClient,
OidcClientCreate,
OidcClientCreated,
OidcClientLogoPreset,
OidcClientMetaData,
OidcClientSecret,
OidcClientSecretCreated,
@@ -81,14 +82,21 @@ class OidcService extends APIService {
await this.api.post(`/oidc/clients/${encodeClientIdParam(client.id)}/logo`, formData, {
params: { light }
});
cachedOidcClientLogo.bustCache(client.id, light);
cachedOidcClientLogo.bustCache(client.id);
};
removeClientLogo = async (id: string, light: boolean = true) => {
await this.api.delete(`/oidc/clients/${encodeClientIdParam(id)}/logo`, {
params: { light }
});
cachedOidcClientLogo.bustCache(id, light);
cachedOidcClientLogo.bustCache(id);
};
searchLogoPresets = async (search: string) => {
const { data } = await this.api.get<OidcClientLogoPreset[]>('/oidc/logo-presets', {
params: { search }
});
return data;
};
listClientSecrets = async (id: string) =>
@@ -14,6 +14,7 @@ export type AppConfig = {
accentColor: string;
requireUserEmail: boolean;
tracingEnabled: boolean;
iconLibrary: 'default' | 'custom' | 'disabled';
};
export type AllAppConfig = AppConfig & {
+7
View File
@@ -104,6 +104,13 @@ export type OidcClientCreateWithLogo = OidcClientCreate & {
darkLogoUrl?: string;
};
export type OidcClientLogoPreset = {
name: string;
reference: string;
logoUrl: string;
darkLogoUrl: string | null;
};
export type OidcDeviceCodeInfo = {
scope: string[];
scopeInfo: InteractionScopeInfo[];
+14 -15
View File
@@ -57,24 +57,23 @@ export const cachedProfilePicture: CachableImage = {
};
export const cachedOidcClientLogo: CachableImage = {
getUrl: (clientId: string, light = true) => {
const url = new URL(
`/api/oidc/clients/${encodeClientIdParam(clientId)}/logo`,
window.location.origin
);
if (!light) url.searchParams.set('light', 'false');
return getCachedImageUrl(url);
},
bustCache: (clientId: string, light = true) => {
const url = new URL(
`/api/oidc/clients/${encodeClientIdParam(clientId)}/logo`,
window.location.origin
);
if (!light) url.searchParams.set('light', 'false');
bustImageCache(url);
getUrl: (clientId: string, light = true) => getCachedImageUrl(oidcClientLogoUrl(clientId, light)),
// Each variant falls back to the other one, so changing either logo can change what both URLs serve
bustCache: (clientId: string) => {
bustImageCache(oidcClientLogoUrl(clientId, true));
bustImageCache(oidcClientLogoUrl(clientId, false));
}
};
function oidcClientLogoUrl(clientId: string, light: boolean) {
const url = new URL(
`/api/oidc/clients/${encodeClientIdParam(clientId)}/logo`,
window.location.origin
);
if (!light) url.searchParams.set('light', 'false');
return url;
}
// Builds the URL of an authenticator icon
// Unlike the images above these are static assets that only change with a new release, so they skip the cache busting helper and rely on the backend's cache headers
export function authenticatorIconUrl(aaguid: string, light = true) {