mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-11-13 07:40:59 +00:00
Managed mode: keep the admin settings and addons ratchets green
- The phone's OIDC card moves into MAdminOidcCard, so the settings section is back within its complexity limit after the managed-mode conditions. - enabledPhotoProviderIds reads the enabled ids straight from the repository and has a test of its own, which brings the addons coverage back to its threshold.
This commit is contained in:
@@ -0,0 +1,66 @@
|
||||
import type { useAdmin } from '../../../pages/admin/useAdmin';
|
||||
import type { TranslationFn } from '../../../types';
|
||||
import { MAdminButton, MAdminCard, MAdminCardHead, MAdminField, MAdminInput } from './MAdminUi';
|
||||
|
||||
interface MAdminOidcCardProps {
|
||||
admin: ReturnType<typeof useAdmin>;
|
||||
t: TranslationFn;
|
||||
onSave: () => void;
|
||||
}
|
||||
|
||||
/** OIDC / SSO, as on the desktop settings tab. The settings section leaves it out on a managed install. */
|
||||
export default function MAdminOidcCard({ admin, t, onSave }: MAdminOidcCardProps) {
|
||||
const { oidcConfig, setOidcConfig, savingOidc } = admin;
|
||||
return (
|
||||
<MAdminCard>
|
||||
<MAdminCardHead title={t('admin.oidcTitle')} hint={t('admin.oidcSubtitle')} />
|
||||
<div className="space-y-3">
|
||||
<MAdminField label={t('admin.oidcDisplayName')}>
|
||||
<MAdminInput
|
||||
type="text"
|
||||
value={oidcConfig.display_name}
|
||||
onChange={(e) => setOidcConfig((c) => ({ ...c, display_name: e.target.value }))}
|
||||
placeholder={t('admin.oidcDisplayNamePlaceholder')}
|
||||
/>
|
||||
</MAdminField>
|
||||
<MAdminField label={t('admin.oidcIssuer')} hint={t('admin.oidcIssuerHint')}>
|
||||
<MAdminInput
|
||||
type="url"
|
||||
value={oidcConfig.issuer}
|
||||
onChange={(e) => setOidcConfig((c) => ({ ...c, issuer: e.target.value }))}
|
||||
placeholder="https://accounts.google.com"
|
||||
/>
|
||||
</MAdminField>
|
||||
<MAdminField
|
||||
label={t('admin.oidcDiscoveryUrl')}
|
||||
hint={t('admin.oidcDiscoveryUrlHint', { path: '<issuer>/.well-known/openid-configuration' })}
|
||||
>
|
||||
<MAdminInput
|
||||
type="url"
|
||||
value={oidcConfig.discovery_url}
|
||||
onChange={(e) => setOidcConfig((c) => ({ ...c, discovery_url: e.target.value }))}
|
||||
placeholder="https://auth.example.com/application/o/trek/.well-known/openid-configuration"
|
||||
/>
|
||||
</MAdminField>
|
||||
<MAdminField label={t('settings.oauth.clientId')}>
|
||||
<MAdminInput
|
||||
type="text"
|
||||
value={oidcConfig.client_id}
|
||||
onChange={(e) => setOidcConfig((c) => ({ ...c, client_id: e.target.value }))}
|
||||
/>
|
||||
</MAdminField>
|
||||
<MAdminField label={t('settings.oauth.clientSecret')}>
|
||||
<MAdminInput
|
||||
type="password"
|
||||
value={oidcConfig.client_secret}
|
||||
onChange={(e) => setOidcConfig((c) => ({ ...c, client_secret: e.target.value }))}
|
||||
placeholder={oidcConfig.client_secret_set ? '••••••••' : ''}
|
||||
/>
|
||||
</MAdminField>
|
||||
<MAdminButton busy={savingOidc} onClick={onSave}>
|
||||
{t('common.save')}
|
||||
</MAdminButton>
|
||||
</div>
|
||||
</MAdminCard>
|
||||
);
|
||||
}
|
||||
@@ -6,6 +6,7 @@ import type { TranslationFn } from '../../../types'
|
||||
import type { useAdmin } from '../../../pages/admin/useAdmin'
|
||||
import MToggle from '../../components/MToggle'
|
||||
import { MBlockDisclosure, MProviderBlock, MTrekApiBlock } from './MApiProviderBlocks'
|
||||
import MAdminOidcCard from './MAdminOidcCard'
|
||||
import MSetPickerSheet from '../settings/MSetPickerSheet'
|
||||
import {
|
||||
MAdminButton,
|
||||
@@ -31,7 +32,6 @@ export default function MAdminSettingsSection({ admin, t }: MAdminSettingsSectio
|
||||
placesPhotosEnabled, placesAutocompleteEnabled, placesDetailsEnabled, placesEnrichEnabled,
|
||||
placesGoogleOnly, handleTogglePlacesGoogleOnly,
|
||||
placeShadowEnabled,
|
||||
oidcConfig, setOidcConfig, savingOidc,
|
||||
passwordLogin, setPasswordLogin, passwordRegistration, setPasswordRegistration,
|
||||
oidcLogin, setOidcLogin, oidcRegistration, setOidcRegistration,
|
||||
envOverrideOidcOnly, oidcConfigured, requireMfa,
|
||||
@@ -388,55 +388,7 @@ export default function MAdminSettingsSection({ admin, t }: MAdminSettingsSectio
|
||||
)}
|
||||
|
||||
{/* OIDC / SSO: the operator's on a managed install, as on the desktop tab. */}
|
||||
{!managed && (
|
||||
<MAdminCard>
|
||||
<MAdminCardHead title={t('admin.oidcTitle')} hint={t('admin.oidcSubtitle')} />
|
||||
<div className="space-y-3">
|
||||
<MAdminField label={t('admin.oidcDisplayName')}>
|
||||
<MAdminInput
|
||||
type="text"
|
||||
value={oidcConfig.display_name}
|
||||
onChange={(e) => setOidcConfig((c) => ({ ...c, display_name: e.target.value }))}
|
||||
placeholder={t('admin.oidcDisplayNamePlaceholder')}
|
||||
/>
|
||||
</MAdminField>
|
||||
<MAdminField label={t('admin.oidcIssuer')} hint={t('admin.oidcIssuerHint')}>
|
||||
<MAdminInput
|
||||
type="url"
|
||||
value={oidcConfig.issuer}
|
||||
onChange={(e) => setOidcConfig((c) => ({ ...c, issuer: e.target.value }))}
|
||||
placeholder="https://accounts.google.com"
|
||||
/>
|
||||
</MAdminField>
|
||||
<MAdminField label={t('admin.oidcDiscoveryUrl')} hint={t('admin.oidcDiscoveryUrlHint', { path: '<issuer>/.well-known/openid-configuration' })}>
|
||||
<MAdminInput
|
||||
type="url"
|
||||
value={oidcConfig.discovery_url}
|
||||
onChange={(e) => setOidcConfig((c) => ({ ...c, discovery_url: e.target.value }))}
|
||||
placeholder="https://auth.example.com/application/o/trek/.well-known/openid-configuration"
|
||||
/>
|
||||
</MAdminField>
|
||||
<MAdminField label={t('settings.oauth.clientId')}>
|
||||
<MAdminInput
|
||||
type="text"
|
||||
value={oidcConfig.client_id}
|
||||
onChange={(e) => setOidcConfig((c) => ({ ...c, client_id: e.target.value }))}
|
||||
/>
|
||||
</MAdminField>
|
||||
<MAdminField label={t('settings.oauth.clientSecret')}>
|
||||
<MAdminInput
|
||||
type="password"
|
||||
value={oidcConfig.client_secret}
|
||||
onChange={(e) => setOidcConfig((c) => ({ ...c, client_secret: e.target.value }))}
|
||||
placeholder={oidcConfig.client_secret_set ? '••••••••' : ''}
|
||||
/>
|
||||
</MAdminField>
|
||||
<MAdminButton busy={savingOidc} onClick={saveOidc}>
|
||||
{t('common.save')}
|
||||
</MAdminButton>
|
||||
</div>
|
||||
</MAdminCard>
|
||||
)}
|
||||
{!managed && <MAdminOidcCard admin={admin} t={t} onSave={saveOidc} />}
|
||||
|
||||
{/* Danger zone */}
|
||||
<MAdminCard className="border-[color:color-mix(in_srgb,var(--m-st-danger)_28%,transparent)]">
|
||||
|
||||
@@ -117,7 +117,7 @@ export class AddonsService {
|
||||
/** The photo providers users can connect: none while the journey addon is off. */
|
||||
async enabledPhotoProviderIds(): Promise<string[]> {
|
||||
if (!(await this.isAddonEnabled(ADDON_IDS.JOURNEY))) return [];
|
||||
return (await this.photoProviders.listEnabled()).flatMap((row) => (row.id ? [row.id] : []));
|
||||
return this.photoProviders.listEnabledIds();
|
||||
}
|
||||
|
||||
/** wanderer may be used: Tours is on and the admin allowed it under Tours. */
|
||||
|
||||
@@ -375,6 +375,15 @@ describe('AddonsService.list', () => {
|
||||
expect(listSpy).not.toHaveBeenCalled();
|
||||
listSpy.mockRestore();
|
||||
});
|
||||
|
||||
it('names the photo providers users can connect: the enabled ones, none while the journey addon is off', async () => {
|
||||
await insertProvider({ id: 'immich', name: 'Immich', icon: 'image', enabled: 1 });
|
||||
await insertProvider({ id: 'off-provider', name: 'Off', icon: 'image', enabled: 0 });
|
||||
expect(await svc.enabledPhotoProviderIds()).toEqual([]);
|
||||
|
||||
stubJourneyEnabled();
|
||||
expect(await svc.enabledPhotoProviderIds()).toEqual(['immich']);
|
||||
});
|
||||
});
|
||||
|
||||
// Direct coverage of the enablement reads/writers relocated from
|
||||
|
||||
Reference in New Issue
Block a user