mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 19:50:43 +00:00
fix: skip allowFrom validation at account level (inherits from parent)
Account configs inherit channel-level fields at runtime (e.g., resolveTelegramAccount shallow-merges top-level and account values). An account can set dmPolicy='allowlist' and rely on the parent's allowFrom, so validating allowFrom on the account object alone incorrectly rejects valid multi-account configs. Removes requireAllowlistAllowFrom and requireOpenAllowFrom from all account-level schemas (Telegram, Signal, IRC, iMessage, BlueBubbles). Top-level config schemas still enforce the validation. Addresses Codex review feedback on #27936.
This commit is contained in:
committed by
Peter Steinberger
parent
cbed0e065c
commit
0fdac31383
@@ -87,7 +87,9 @@ describe('dmPolicy="allowlist" requires non-empty allowFrom', () => {
|
|||||||
expect(res.ok).toBe(true);
|
expect(res.ok).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('rejects telegram account dmPolicy="allowlist" without allowFrom', () => {
|
it('accepts telegram account dmPolicy="allowlist" without own allowFrom (inherits from parent)', () => {
|
||||||
|
// Account-level schemas skip allowFrom validation because accounts inherit
|
||||||
|
// allowFrom from the parent channel config at runtime.
|
||||||
const res = validateConfigObject({
|
const res = validateConfigObject({
|
||||||
channels: {
|
channels: {
|
||||||
telegram: {
|
telegram: {
|
||||||
@@ -97,10 +99,7 @@ describe('dmPolicy="allowlist" requires non-empty allowFrom', () => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
expect(res.ok).toBe(false);
|
expect(res.ok).toBe(true);
|
||||||
if (!res.ok) {
|
|
||||||
expect(res.issues.some((i) => i.path.includes("allowFrom"))).toBe(true);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('accepts telegram account dmPolicy="allowlist" with allowFrom entries', () => {
|
it('accepts telegram account dmPolicy="allowlist" with allowFrom entries', () => {
|
||||||
|
|||||||
@@ -220,22 +220,10 @@ export const TelegramAccountSchemaBase = z
|
|||||||
|
|
||||||
export const TelegramAccountSchema = TelegramAccountSchemaBase.superRefine((value, ctx) => {
|
export const TelegramAccountSchema = TelegramAccountSchemaBase.superRefine((value, ctx) => {
|
||||||
normalizeTelegramStreamingConfig(value);
|
normalizeTelegramStreamingConfig(value);
|
||||||
requireOpenAllowFrom({
|
// Account-level schemas skip allowFrom validation because accounts inherit
|
||||||
policy: value.dmPolicy,
|
// allowFrom from the parent channel config at runtime (resolveTelegramAccount
|
||||||
allowFrom: value.allowFrom,
|
// shallow-merges top-level and account values in src/telegram/accounts.ts).
|
||||||
ctx,
|
// Validation is enforced at the top-level TelegramConfigSchema instead.
|
||||||
path: ["allowFrom"],
|
|
||||||
message:
|
|
||||||
'channels.telegram.dmPolicy="open" requires channels.telegram.allowFrom to include "*"',
|
|
||||||
});
|
|
||||||
requireAllowlistAllowFrom({
|
|
||||||
policy: value.dmPolicy,
|
|
||||||
allowFrom: value.allowFrom,
|
|
||||||
ctx,
|
|
||||||
path: ["allowFrom"],
|
|
||||||
message:
|
|
||||||
'channels.telegram.dmPolicy="allowlist" requires channels.telegram.allowFrom to contain at least one sender ID',
|
|
||||||
});
|
|
||||||
validateTelegramCustomCommands(value, ctx);
|
validateTelegramCustomCommands(value, ctx);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -847,23 +835,10 @@ export const SignalAccountSchemaBase = z
|
|||||||
})
|
})
|
||||||
.strict();
|
.strict();
|
||||||
|
|
||||||
export const SignalAccountSchema = SignalAccountSchemaBase.superRefine((value, ctx) => {
|
// Account-level schemas skip allowFrom validation because accounts inherit
|
||||||
requireOpenAllowFrom({
|
// allowFrom from the parent channel config at runtime.
|
||||||
policy: value.dmPolicy,
|
// Validation is enforced at the top-level SignalConfigSchema instead.
|
||||||
allowFrom: value.allowFrom,
|
export const SignalAccountSchema = SignalAccountSchemaBase;
|
||||||
ctx,
|
|
||||||
path: ["allowFrom"],
|
|
||||||
message: 'channels.signal.dmPolicy="open" requires channels.signal.allowFrom to include "*"',
|
|
||||||
});
|
|
||||||
requireAllowlistAllowFrom({
|
|
||||||
policy: value.dmPolicy,
|
|
||||||
allowFrom: value.allowFrom,
|
|
||||||
ctx,
|
|
||||||
path: ["allowFrom"],
|
|
||||||
message:
|
|
||||||
'channels.signal.dmPolicy="allowlist" requires channels.signal.allowFrom to contain at least one sender ID',
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
export const SignalConfigSchema = SignalAccountSchemaBase.extend({
|
export const SignalConfigSchema = SignalAccountSchemaBase.extend({
|
||||||
accounts: z.record(z.string(), SignalAccountSchema.optional()).optional(),
|
accounts: z.record(z.string(), SignalAccountSchema.optional()).optional(),
|
||||||
@@ -972,8 +947,18 @@ function refineIrcAllowFromAndNickserv(value: IrcBaseConfig, ctx: z.RefinementCt
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Account-level schemas skip allowFrom validation because accounts inherit
|
||||||
|
// allowFrom from the parent channel config at runtime.
|
||||||
|
// Validation is enforced at the top-level IrcConfigSchema instead.
|
||||||
export const IrcAccountSchema = IrcAccountSchemaBase.superRefine((value, ctx) => {
|
export const IrcAccountSchema = IrcAccountSchemaBase.superRefine((value, ctx) => {
|
||||||
refineIrcAllowFromAndNickserv(value, ctx);
|
// Only validate nickserv at account level, not allowFrom (inherited from parent).
|
||||||
|
if (value.nickserv?.register && !value.nickserv.registerEmail?.trim()) {
|
||||||
|
ctx.addIssue({
|
||||||
|
code: z.ZodIssueCode.custom,
|
||||||
|
path: ["nickserv", "registerEmail"],
|
||||||
|
message: "channels.irc.nickserv.register=true requires channels.irc.nickserv.registerEmail",
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
export const IrcConfigSchema = IrcAccountSchemaBase.extend({
|
export const IrcConfigSchema = IrcAccountSchemaBase.extend({
|
||||||
@@ -1035,24 +1020,10 @@ export const IMessageAccountSchemaBase = z
|
|||||||
})
|
})
|
||||||
.strict();
|
.strict();
|
||||||
|
|
||||||
export const IMessageAccountSchema = IMessageAccountSchemaBase.superRefine((value, ctx) => {
|
// Account-level schemas skip allowFrom validation because accounts inherit
|
||||||
requireOpenAllowFrom({
|
// allowFrom from the parent channel config at runtime.
|
||||||
policy: value.dmPolicy,
|
// Validation is enforced at the top-level IMessageConfigSchema instead.
|
||||||
allowFrom: value.allowFrom,
|
export const IMessageAccountSchema = IMessageAccountSchemaBase;
|
||||||
ctx,
|
|
||||||
path: ["allowFrom"],
|
|
||||||
message:
|
|
||||||
'channels.imessage.dmPolicy="open" requires channels.imessage.allowFrom to include "*"',
|
|
||||||
});
|
|
||||||
requireAllowlistAllowFrom({
|
|
||||||
policy: value.dmPolicy,
|
|
||||||
allowFrom: value.allowFrom,
|
|
||||||
ctx,
|
|
||||||
path: ["allowFrom"],
|
|
||||||
message:
|
|
||||||
'channels.imessage.dmPolicy="allowlist" requires channels.imessage.allowFrom to contain at least one sender ID',
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
export const IMessageConfigSchema = IMessageAccountSchemaBase.extend({
|
export const IMessageConfigSchema = IMessageAccountSchemaBase.extend({
|
||||||
accounts: z.record(z.string(), IMessageAccountSchema.optional()).optional(),
|
accounts: z.record(z.string(), IMessageAccountSchema.optional()).optional(),
|
||||||
@@ -1132,23 +1103,10 @@ export const BlueBubblesAccountSchemaBase = z
|
|||||||
})
|
})
|
||||||
.strict();
|
.strict();
|
||||||
|
|
||||||
export const BlueBubblesAccountSchema = BlueBubblesAccountSchemaBase.superRefine((value, ctx) => {
|
// Account-level schemas skip allowFrom validation because accounts inherit
|
||||||
requireOpenAllowFrom({
|
// allowFrom from the parent channel config at runtime.
|
||||||
policy: value.dmPolicy,
|
// Validation is enforced at the top-level BlueBubblesConfigSchema instead.
|
||||||
allowFrom: value.allowFrom,
|
export const BlueBubblesAccountSchema = BlueBubblesAccountSchemaBase;
|
||||||
ctx,
|
|
||||||
path: ["allowFrom"],
|
|
||||||
message: 'channels.bluebubbles.accounts.*.dmPolicy="open" requires allowFrom to include "*"',
|
|
||||||
});
|
|
||||||
requireAllowlistAllowFrom({
|
|
||||||
policy: value.dmPolicy,
|
|
||||||
allowFrom: value.allowFrom,
|
|
||||||
ctx,
|
|
||||||
path: ["allowFrom"],
|
|
||||||
message:
|
|
||||||
'channels.bluebubbles.accounts.*.dmPolicy="allowlist" requires allowFrom to contain at least one sender ID',
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
export const BlueBubblesConfigSchema = BlueBubblesAccountSchemaBase.extend({
|
export const BlueBubblesConfigSchema = BlueBubblesAccountSchemaBase.extend({
|
||||||
accounts: z.record(z.string(), BlueBubblesAccountSchema.optional()).optional(),
|
accounts: z.record(z.string(), BlueBubblesAccountSchema.optional()).optional(),
|
||||||
|
|||||||
Reference in New Issue
Block a user