Skip to content

Commit 41b5e02

Browse files
fix[frontend](socai): setted customHeaders as password key type
1 parent 03c163d commit 41b5e02

1 file changed

Lines changed: 48 additions & 16 deletions

File tree

frontend/src/app/app-module/guides/guide-soc-ai/guide-soc-ai.component.ts

Lines changed: 48 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,10 @@ export class GuideSocAiComponent implements OnInit {
5353
private rawConfigs: UtmModuleGroupConfType[] = [];
5454
private groupId: number;
5555

56+
// Original masked customHeaders value (if backend returned an opaque mask like "*****")
57+
private originalMaskedCustomHeaders: string | null = null;
58+
private readonly maskedDisplay = '***';
59+
5660
providers: ProviderConfig[] = [
5761
{
5862
id: 'openai',
@@ -350,6 +354,7 @@ export class GuideSocAiComponent implements OnInit {
350354
'changeAlertStatus': changeStatus ? changeStatus.confValue : 'false',
351355
};
352356
this.customModelValue = '';
357+
this.originalMaskedCustomHeaders = null;
353358

354359
// Only load provider-specific values if viewing the saved provider
355360
if (isCurrentSavedProvider) {
@@ -379,16 +384,25 @@ export class GuideSocAiComponent implements OnInit {
379384
// Check if API key exists in custom headers — show masked if so
380385
const customHeaders = this.getConf('utmstack.socai.customHeaders');
381386
if (customHeaders && customHeaders.confValue && customHeaders.confValue !== '{}') {
382-
try {
383-
const headers = JSON.parse(customHeaders.confValue);
384-
const authConfig = this.providerAuthHeaders[this.activeProvider];
385-
if (authConfig && headers[authConfig.headerName]) {
386-
// API key exists — show masked, don't expose the real value
387-
this.formValues['apiKey'] = '*****';
388-
}
389-
} catch (e) {}
390-
this.formValues['customHeaders'] = customHeaders.confValue;
391-
this.parseHeadersFromJson(customHeaders.confValue);
387+
const raw = customHeaders.confValue;
388+
if (this.isMaskedValue(raw)) {
389+
// Backend returned the whole confValue masked — preserve original for save
390+
this.originalMaskedCustomHeaders = raw;
391+
this.formValues['customHeaders'] = raw;
392+
this.formValues['apiKey'] = this.maskedDisplay;
393+
this.headerRows = [{key: this.maskedDisplay, value: this.maskedDisplay}];
394+
} else {
395+
try {
396+
const headers = JSON.parse(raw);
397+
const authConfig = this.providerAuthHeaders[this.activeProvider];
398+
if (authConfig && headers[authConfig.headerName]) {
399+
// API key exists — show masked, don't expose the real value
400+
this.formValues['apiKey'] = this.maskedDisplay;
401+
}
402+
} catch (e) {}
403+
this.formValues['customHeaders'] = raw;
404+
this.parseHeadersFromJson(raw);
405+
}
392406
}
393407

394408
const maxTokensConf = this.getConf('utmstack.socai.maxTokens');
@@ -452,22 +466,32 @@ export class GuideSocAiComponent implements OnInit {
452466
if (this.activeProvider === 'custom') {
453467
// Custom provider: user manages auth type and headers directly
454468
this.pushChange(changes, 'utmstack.socai.authType', this.formValues['authType'] || 'custom-headers', 'text');
455-
this.pushChange(changes, 'utmstack.socai.customHeaders', this.formValues['customHeaders'] || '{}', 'text');
469+
if (this.originalMaskedCustomHeaders && this.hasMaskedHeaderRows()) {
470+
// User didn't replace the masked rows — preserve original masked value
471+
this.pushChange(changes, 'utmstack.socai.customHeaders', this.originalMaskedCustomHeaders, 'password');
472+
} else {
473+
this.pushChange(changes, 'utmstack.socai.customHeaders', this.formValues['customHeaders'] || '{}', 'password');
474+
}
456475
} else if (this.activeProvider === 'ollama') {
457476
// Ollama: no auth needed
458477
this.pushChange(changes, 'utmstack.socai.authType', 'none', 'text');
459-
this.pushChange(changes, 'utmstack.socai.customHeaders', '{}', 'text');
478+
this.pushChange(changes, 'utmstack.socai.customHeaders', '{}', 'password');
460479
} else {
461480
// Known providers: build auth header from API key
462481
const authConfig = this.providerAuthHeaders[this.activeProvider];
463-
if (authConfig && this.formValues['apiKey'] && this.formValues['apiKey'] !== '*****') {
482+
const apiKey = this.formValues['apiKey'];
483+
if (authConfig && apiKey && !this.isMaskedValue(apiKey)) {
464484
// User entered a new API key — build auth headers
465485
const headers: {[k: string]: string} = {};
466-
headers[authConfig.headerName] = authConfig.headerValuePrefix + this.formValues['apiKey'];
486+
headers[authConfig.headerName] = authConfig.headerValuePrefix + apiKey;
467487
this.pushChange(changes, 'utmstack.socai.authType', 'custom-headers', 'text');
468-
this.pushChange(changes, 'utmstack.socai.customHeaders', JSON.stringify(headers), 'text');
488+
this.pushChange(changes, 'utmstack.socai.customHeaders', JSON.stringify(headers), 'password');
489+
} else if (this.originalMaskedCustomHeaders && apiKey && this.isMaskedValue(apiKey)) {
490+
// User didn't change the masked API key — preserve original masked value
491+
this.pushChange(changes, 'utmstack.socai.authType', 'custom-headers', 'text');
492+
this.pushChange(changes, 'utmstack.socai.customHeaders', this.originalMaskedCustomHeaders, 'password');
469493
}
470-
// If apiKey is '*****', don't touch customHeaders — keep existing value in DB
494+
// Otherwise: don't touch customHeaders — keep existing value in DB
471495
}
472496

473497
this.moduleGroupConfService.update({
@@ -567,6 +591,14 @@ export class GuideSocAiComponent implements OnInit {
567591
this.formValues['customHeaders'] = JSON.stringify(obj);
568592
}
569593

594+
private isMaskedValue(value: string): boolean {
595+
return !!value && /^\*+$/.test(value);
596+
}
597+
598+
private hasMaskedHeaderRows(): boolean {
599+
return this.headerRows.some(r => this.isMaskedValue(r.key) || this.isMaskedValue(r.value));
600+
}
601+
570602
private parseHeadersFromJson(json: string) {
571603
this.headerRows = [];
572604
try {

0 commit comments

Comments
 (0)