feat(teamsbot): per-user settings API, system bot admin API, credentials removed from settings UI

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
ValueOn AG 2026-02-16 00:16:03 +01:00
parent dffebc8d73
commit 7366da06ac
2 changed files with 60 additions and 36 deletions

View file

@ -180,7 +180,7 @@ export async function deleteSession(instanceId: string, sessionId: string): Prom
}
/**
* Get teamsbot configuration.
* Get teamsbot configuration (instance-level defaults).
*/
export async function getConfig(instanceId: string): Promise<{ config: TeamsbotConfig }> {
const response = await api.get(`/api/teamsbot/${instanceId}/config`);
@ -188,13 +188,54 @@ export async function getConfig(instanceId: string): Promise<{ config: TeamsbotC
}
/**
* Update teamsbot configuration.
* Update teamsbot configuration (instance-level defaults).
*/
export async function updateConfig(instanceId: string, updates: ConfigUpdateRequest): Promise<{ config: TeamsbotConfig }> {
const response = await api.put(`/api/teamsbot/${instanceId}/config`, updates);
return response.data;
}
/**
* Get per-user settings merged with instance defaults.
*/
export async function getUserSettings(instanceId: string): Promise<{ settings: any; effectiveConfig: TeamsbotConfig }> {
const response = await api.get(`/api/teamsbot/${instanceId}/settings`);
return response.data;
}
/**
* Update per-user settings.
*/
export async function updateUserSettings(instanceId: string, updates: ConfigUpdateRequest): Promise<{ settings: any; effectiveConfig: TeamsbotConfig }> {
const response = await api.put(`/api/teamsbot/${instanceId}/settings`, updates);
return response.data;
}
/**
* Reset per-user settings to instance defaults.
*/
export async function resetUserSettings(instanceId: string): Promise<{ settings: null; effectiveConfig: TeamsbotConfig }> {
const response = await api.delete(`/api/teamsbot/${instanceId}/settings`);
return response.data;
}
export interface SystemBot {
id: string;
mandateId: string;
name: string;
email: string;
isActive: boolean;
creationDate?: string;
}
/**
* List system bot accounts for this mandate.
*/
export async function listSystemBots(instanceId: string): Promise<{ bots: SystemBot[] }> {
const response = await api.get(`/api/teamsbot/${instanceId}/system-bots`);
return response.data;
}
/**
* Test TTS voice with AI-generated sample text. Returns base64-encoded audio.
*/

View file

@ -41,15 +41,17 @@ export const TeamsbotSettingsView: React.FC = () => {
if (!instanceId) return;
try {
setLoading(true);
const [configResult, languagesResult] = await Promise.all([
teamsbotApi.getConfig(instanceId),
// Load per-user settings (merged with instance defaults)
const [settingsResult, languagesResult] = await Promise.all([
teamsbotApi.getUserSettings(instanceId),
teamsbotApi.fetchLanguages(),
]);
setConfig(configResult.config);
setFormData(configResult.config);
const effectiveConfig = settingsResult.effectiveConfig;
setConfig(effectiveConfig);
setFormData(effectiveConfig);
setLanguages(languagesResult);
// Load voices for the current language
const lang = configResult.config.language || 'de-DE';
const lang = effectiveConfig.language || 'de-DE';
const voicesResult = await teamsbotApi.fetchVoices(lang);
setVoices(voicesResult);
setError(null);
@ -71,10 +73,11 @@ export const TeamsbotSettingsView: React.FC = () => {
setSuccessMsg(null);
try {
const result = await teamsbotApi.updateConfig(instanceId, formData);
setConfig(result.config);
setFormData(result.config);
setSuccessMsg('Konfiguration gespeichert');
// Save as per-user settings (not instance config)
const result = await teamsbotApi.updateUserSettings(instanceId, formData);
setConfig(result.effectiveConfig);
setFormData(result.effectiveConfig);
setSuccessMsg('Einstellungen gespeichert');
setTimeout(() => setSuccessMsg(null), 3000);
} catch (err: any) {
setError(err.message || 'Fehler beim Speichern');
@ -282,33 +285,13 @@ export const TeamsbotSettingsView: React.FC = () => {
</div>
</div>
{/* Bot Account */}
{/* Bot Account - managed by admin, read-only display */}
<div className={styles.settingsSection}>
<h4 className={styles.sectionTitle}>Bot-Account (Microsoft)</h4>
<div className={styles.formGroup}>
<label className={styles.label}>E-Mail</label>
<input
type="email"
className={styles.input}
value={formData.botAccountEmail || ''}
onChange={(e) => _updateField('botAccountEmail', e.target.value)}
placeholder="bot@ihrefirma.ch"
/>
<span className={styles.hint}>Dedizierter Microsoft-Account fuer authentifizierten Bot-Zugang. Leer = anonymer Gast.</span>
</div>
<div className={styles.formGroup}>
<label className={styles.label}>Passwort</label>
<input
type="password"
className={styles.input}
value={formData.botAccountPassword || ''}
onChange={(e) => _updateField('botAccountPassword', e.target.value)}
placeholder="••••••••"
/>
<span className={styles.hint}>MFA muss fuer diesen Account deaktiviert sein. Passwort wird verschluesselt gespeichert.</span>
</div>
<span className={styles.hint}>
System-Bot-Accounts werden vom Administrator verwaltet und sind nicht direkt editierbar.
Waehle beim Session-Start den gewuenschten Join-Modus.
</span>
</div>
{/* Advanced Settings */}