Added ldap and pam authentication
This commit is contained in:
@@ -3,6 +3,8 @@ import { useState, useEffect, useCallback, useRef } from 'preact/hooks';
|
||||
import SignalPicker, { SignalOption } from './SignalPicker';
|
||||
import { VersionTree, DiffViewer } from './VersionHistory';
|
||||
import CueEditor from './CueEditor';
|
||||
import { useAuth } from './lib/auth';
|
||||
import { ScopeFilter, ScopePicker, filterByScope, normalizeScope, type Bucket } from './lib/scope';
|
||||
|
||||
// ── Types (mirror internal/confmgr) ──────────────────────────────────────────
|
||||
|
||||
@@ -32,6 +34,8 @@ interface ConfigSet {
|
||||
version: number;
|
||||
tag?: string;
|
||||
owner?: string;
|
||||
scope?: string;
|
||||
groups?: string[];
|
||||
parameters: Parameter[];
|
||||
}
|
||||
|
||||
@@ -43,10 +47,12 @@ interface ConfigInstance {
|
||||
version: number;
|
||||
tag?: string;
|
||||
owner?: string;
|
||||
scope?: string;
|
||||
groups?: string[];
|
||||
values: Record<string, any>;
|
||||
}
|
||||
|
||||
interface Meta { id: string; name: string; version: number; setId?: string; enabled?: boolean; }
|
||||
interface Meta { id: string; name: string; version: number; setId?: string; enabled?: boolean; owner?: string; scope?: string; groups?: string[]; }
|
||||
|
||||
// ConfigRule mirrors internal/confmgr.ConfigRule: CUE validation/transformation
|
||||
// logic bound to a set, run when instances of that set are saved.
|
||||
@@ -292,7 +298,10 @@ function useUndoKeys(undo: () => void, redo: () => void, canUndo: boolean, canRe
|
||||
// ── Sets manager ──────────────────────────────────────────────────────────────
|
||||
|
||||
function SetsManager({ registerGuard }: { registerGuard: (fn: CloseGuard | null) => void }) {
|
||||
const me = useAuth();
|
||||
const [sets, setSets] = useState<Meta[]>([]);
|
||||
const [bucket, setBucket] = useState<Bucket>('mine');
|
||||
const [scopeGroup, setScopeGroup] = useState('');
|
||||
const [selectedId, setSelectedId] = useState<string | null>(null);
|
||||
const hist = useUndo<ConfigSet>();
|
||||
const working = hist.present;
|
||||
@@ -445,6 +454,8 @@ function SetsManager({ registerGuard }: { registerGuard: (fn: CloseGuard | null)
|
||||
} catch (err) { setError(msg(err)); }
|
||||
}
|
||||
|
||||
const visibleSets = filterByScope(sets, me, bucket, scopeGroup);
|
||||
|
||||
return (
|
||||
<div class="cl-body">
|
||||
<div class="cl-list">
|
||||
@@ -457,8 +468,10 @@ function SetsManager({ registerGuard }: { registerGuard: (fn: CloseGuard | null)
|
||||
<input ref={fileRef} type="file" accept="application/json,.json" style={{ display: 'none' }}
|
||||
onChange={(e) => { const t = e.target as HTMLInputElement; const f = t.files?.[0]; if (f) importSet(f); t.value = ''; }} />
|
||||
</div>
|
||||
<ScopeFilter me={me} value={bucket} onChange={setBucket} group={scopeGroup} onGroupChange={setScopeGroup} />
|
||||
{sets.length === 0 && <div class="hint cl-list-empty">No config sets yet.</div>}
|
||||
{sets.map(s => (
|
||||
{sets.length > 0 && visibleSets.length === 0 && <div class="hint cl-list-empty">No config sets in this view.</div>}
|
||||
{visibleSets.map(s => (
|
||||
<div key={s.id} class={`cl-list-item${selectedId === s.id ? ' cl-list-item-active' : ''}`} onClick={() => select(s.id)}>
|
||||
<span class="cl-list-name" title={s.name}>{s.name || '(unnamed)'}</span>
|
||||
<span class="cfg-badge" title="Current version">v{s.version}</span>
|
||||
@@ -484,6 +497,8 @@ function SetsManager({ registerGuard }: { registerGuard: (fn: CloseGuard | null)
|
||||
</div>
|
||||
<textarea class="prop-input cfg-desc" rows={2} value={working.description ?? ''} placeholder="Description (optional)"
|
||||
onInput={(e) => patch({ description: (e.target as HTMLTextAreaElement).value })} />
|
||||
<ScopePicker me={me} scope={normalizeScope(working.scope)} groups={working.groups ?? []}
|
||||
onChange={(scope, groups) => patch({ scope, groups })} />
|
||||
|
||||
<div class="cfg-section-head">
|
||||
<span>Parameters</span>
|
||||
@@ -802,9 +817,12 @@ function ParamEditor({ param, allOptions, onOpenSignals, signalMeta, onChange, o
|
||||
// ── Instances manager ─────────────────────────────────────────────────────────
|
||||
|
||||
function InstancesManager({ registerGuard }: { registerGuard: (fn: CloseGuard | null) => void }) {
|
||||
const me = useAuth();
|
||||
const [instances, setInstances] = useState<Meta[]>([]);
|
||||
const [sets, setSets] = useState<Meta[]>([]);
|
||||
const [setFilter, setSetFilter] = useState<string>('');
|
||||
const [bucket, setBucket] = useState<Bucket>('mine');
|
||||
const [scopeGroup, setScopeGroup] = useState('');
|
||||
const [selectedId, setSelectedId] = useState<string | null>(null);
|
||||
const hist = useUndo<ConfigInstance>();
|
||||
const working = hist.present;
|
||||
@@ -984,7 +1002,8 @@ function InstancesManager({ registerGuard }: { registerGuard: (fn: CloseGuard |
|
||||
}
|
||||
|
||||
const setName = (id: string) => sets.find(s => s.id === id)?.name ?? id;
|
||||
const visibleInstances = instances.filter(s => !setFilter || s.setId === setFilter);
|
||||
const scopedInstances = filterByScope(instances, me, bucket, scopeGroup);
|
||||
const visibleInstances = scopedInstances.filter(s => !setFilter || s.setId === setFilter);
|
||||
|
||||
return (
|
||||
<div class="cl-body">
|
||||
@@ -994,6 +1013,7 @@ function InstancesManager({ registerGuard }: { registerGuard: (fn: CloseGuard |
|
||||
<button class="panel-btn" disabled={busy || sets.length === 0} title="Snapshot a set's current live signal values into a new instance" onClick={() => setShowSnap(true)}>⎙ Snapshot</button>
|
||||
<button class="panel-btn" disabled={busy || sets.length === 0} onClick={() => setShowNew(true)}>+ New</button>
|
||||
</div>
|
||||
<ScopeFilter me={me} value={bucket} onChange={setBucket} group={scopeGroup} onGroupChange={setScopeGroup} />
|
||||
{sets.length > 1 && (
|
||||
<div class="cl-list-filter">
|
||||
<select class="prop-select" value={setFilter} title="Filter instances by config set"
|
||||
@@ -1032,6 +1052,8 @@ function InstancesManager({ registerGuard }: { registerGuard: (fn: CloseGuard |
|
||||
<button class="panel-btn" disabled={busy} title="Compare stored values against the current live signal values" onClick={liveDiff}>Diff vs current</button>
|
||||
</div>
|
||||
<div class="hint">Based on set <b>{setName(working.setId)}</b>{working.setVersion ? ` (v${working.setVersion})` : ''}.</div>
|
||||
<ScopePicker me={me} scope={normalizeScope(working.scope)} groups={working.groups ?? []}
|
||||
onChange={(scope, groups) => { hist.commit({ ...working, scope, groups }); setDirty(true); }} />
|
||||
|
||||
{!boundSet && <div class="cl-error">Bound set could not be loaded.</div>}
|
||||
{boundSet && (
|
||||
|
||||
Reference in New Issue
Block a user