mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 19:50:43 +00:00
refactor(config): dedupe redacted snapshot array/object restore paths
This commit is contained in:
@@ -384,6 +384,89 @@ function restoreOriginalValueOrThrow(params: {
|
|||||||
throw new RedactionError(params.path);
|
throw new RedactionError(params.path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function mapRedactedArray(params: {
|
||||||
|
incoming: unknown[];
|
||||||
|
original: unknown;
|
||||||
|
path: string;
|
||||||
|
mapItem: (item: unknown, index: number, originalArray: unknown[]) => unknown;
|
||||||
|
}): unknown[] {
|
||||||
|
const originalArray = Array.isArray(params.original) ? params.original : [];
|
||||||
|
if (params.incoming.length < originalArray.length) {
|
||||||
|
log.warn(`Redacted config array key ${params.path} has been truncated`);
|
||||||
|
}
|
||||||
|
return params.incoming.map((item, index) => params.mapItem(item, index, originalArray));
|
||||||
|
}
|
||||||
|
|
||||||
|
function toObjectRecord(value: unknown): Record<string, unknown> {
|
||||||
|
if (value && typeof value === "object" && !Array.isArray(value)) {
|
||||||
|
return value as Record<string, unknown>;
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
function restoreArrayItemWithLookup(params: {
|
||||||
|
item: unknown;
|
||||||
|
index: number;
|
||||||
|
originalArray: unknown[];
|
||||||
|
lookup: Set<string>;
|
||||||
|
path: string;
|
||||||
|
hints: ConfigUiHints;
|
||||||
|
}): unknown {
|
||||||
|
if (params.item === REDACTED_SENTINEL) {
|
||||||
|
return params.originalArray[params.index];
|
||||||
|
}
|
||||||
|
return restoreRedactedValuesWithLookup(
|
||||||
|
params.item,
|
||||||
|
params.originalArray[params.index],
|
||||||
|
params.lookup,
|
||||||
|
params.path,
|
||||||
|
params.hints,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function restoreArrayItemWithGuessing(params: {
|
||||||
|
item: unknown;
|
||||||
|
index: number;
|
||||||
|
originalArray: unknown[];
|
||||||
|
path: string;
|
||||||
|
hints?: ConfigUiHints;
|
||||||
|
}): unknown {
|
||||||
|
if (
|
||||||
|
!isExplicitlyNonSensitivePath(params.hints, [params.path]) &&
|
||||||
|
isSensitivePath(params.path) &&
|
||||||
|
params.item === REDACTED_SENTINEL
|
||||||
|
) {
|
||||||
|
return params.originalArray[params.index];
|
||||||
|
}
|
||||||
|
return restoreRedactedValuesGuessing(
|
||||||
|
params.item,
|
||||||
|
params.originalArray[params.index],
|
||||||
|
params.path,
|
||||||
|
params.hints,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function restoreGuessingArray(
|
||||||
|
incoming: unknown[],
|
||||||
|
original: unknown,
|
||||||
|
path: string,
|
||||||
|
hints?: ConfigUiHints,
|
||||||
|
): unknown[] {
|
||||||
|
return mapRedactedArray({
|
||||||
|
incoming,
|
||||||
|
original,
|
||||||
|
path,
|
||||||
|
mapItem: (item, index, originalArray) =>
|
||||||
|
restoreArrayItemWithGuessing({
|
||||||
|
item,
|
||||||
|
index,
|
||||||
|
originalArray,
|
||||||
|
path,
|
||||||
|
hints,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Worker for restoreRedactedValues().
|
* Worker for restoreRedactedValues().
|
||||||
* Used when there are ConfigUiHints available.
|
* Used when there are ConfigUiHints available.
|
||||||
@@ -413,21 +496,22 @@ function restoreRedactedValuesWithLookup(
|
|||||||
}
|
}
|
||||||
return restoreRedactedValuesGuessing(incoming, original, prefix, hints);
|
return restoreRedactedValuesGuessing(incoming, original, prefix, hints);
|
||||||
}
|
}
|
||||||
const origArr = Array.isArray(original) ? original : [];
|
return mapRedactedArray({
|
||||||
if (incoming.length < origArr.length) {
|
incoming,
|
||||||
log.warn(`Redacted config array key ${path} has been truncated`);
|
original,
|
||||||
}
|
path,
|
||||||
return incoming.map((item, i) => {
|
mapItem: (item, index, originalArray) =>
|
||||||
if (item === REDACTED_SENTINEL) {
|
restoreArrayItemWithLookup({
|
||||||
return origArr[i];
|
item,
|
||||||
}
|
index,
|
||||||
return restoreRedactedValuesWithLookup(item, origArr[i], lookup, path, hints);
|
originalArray,
|
||||||
|
lookup,
|
||||||
|
path,
|
||||||
|
hints,
|
||||||
|
}),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
const orig =
|
const orig = toObjectRecord(original);
|
||||||
original && typeof original === "object" && !Array.isArray(original)
|
|
||||||
? (original as Record<string, unknown>)
|
|
||||||
: {};
|
|
||||||
const result: Record<string, unknown> = {};
|
const result: Record<string, unknown> = {};
|
||||||
for (const [key, value] of Object.entries(incoming as Record<string, unknown>)) {
|
for (const [key, value] of Object.entries(incoming as Record<string, unknown>)) {
|
||||||
result[key] = value;
|
result[key] = value;
|
||||||
@@ -478,26 +562,10 @@ function restoreRedactedValuesGuessing(
|
|||||||
// we have no way of knowing which one. In this case, the last
|
// we have no way of knowing which one. In this case, the last
|
||||||
// element(s) get(s) chopped off. Not good, so please don't put
|
// element(s) get(s) chopped off. Not good, so please don't put
|
||||||
// sensitive string array in the config...
|
// sensitive string array in the config...
|
||||||
const origArr = Array.isArray(original) ? original : [];
|
const path = `${prefix}[]`;
|
||||||
return incoming.map((item, i) => {
|
return restoreGuessingArray(incoming, original, path, hints);
|
||||||
const path = `${prefix}[]`;
|
|
||||||
if (incoming.length < origArr.length) {
|
|
||||||
log.warn(`Redacted config array key ${path} has been truncated`);
|
|
||||||
}
|
|
||||||
if (
|
|
||||||
!isExplicitlyNonSensitivePath(hints, [path]) &&
|
|
||||||
isSensitivePath(path) &&
|
|
||||||
item === REDACTED_SENTINEL
|
|
||||||
) {
|
|
||||||
return origArr[i];
|
|
||||||
}
|
|
||||||
return restoreRedactedValuesGuessing(item, origArr[i], path, hints);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
const orig =
|
const orig = toObjectRecord(original);
|
||||||
original && typeof original === "object" && !Array.isArray(original)
|
|
||||||
? (original as Record<string, unknown>)
|
|
||||||
: {};
|
|
||||||
const result: Record<string, unknown> = {};
|
const result: Record<string, unknown> = {};
|
||||||
for (const [key, value] of Object.entries(incoming as Record<string, unknown>)) {
|
for (const [key, value] of Object.entries(incoming as Record<string, unknown>)) {
|
||||||
const path = prefix ? `${prefix}.${key}` : key;
|
const path = prefix ? `${prefix}.${key}` : key;
|
||||||
|
|||||||
Reference in New Issue
Block a user