mirror of
https://github.com/openclaw/openclaw.git
synced 2026-03-31 14:26:30 +02:00
tighten phone-control scope helper extraction
This commit is contained in:
@@ -167,7 +167,7 @@ describe("phone-control plugin", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("blocks non-webchat gateway callers with operator.write from mutating phone control", async () => {
|
||||
it("regression: blocks non-webchat gateway callers with operator.write from arm/disarm", async () => {
|
||||
await withRegisteredPhoneControl(async ({ command, writeConfigFile }) => {
|
||||
const armRes = await command.handler({
|
||||
...createCommandContext("arm writes 30s"),
|
||||
@@ -183,6 +183,7 @@ describe("phone-control plugin", () => {
|
||||
gatewayClientScopes: ["operator.write"],
|
||||
});
|
||||
expect(String(disarmRes?.text ?? "")).toContain("requires operator.admin");
|
||||
expect(writeConfigFile).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@ type ArmStateFile = ArmStateFileV1 | ArmStateFileV2;
|
||||
|
||||
const STATE_VERSION = 2;
|
||||
const STATE_REL_PATH = ["plugins", "phone-control", "armed.json"] as const;
|
||||
const PHONE_ADMIN_SCOPE = "operator.admin";
|
||||
|
||||
const GROUP_COMMANDS: Record<Exclude<ArmGroup, "all">, string[]> = {
|
||||
camera: ["camera.snap", "camera.clip"],
|
||||
@@ -268,6 +269,16 @@ function parseGroup(raw: string | undefined): ArmGroup | null {
|
||||
return null;
|
||||
}
|
||||
|
||||
function requiresAdminToMutatePhoneControl(
|
||||
channel: string,
|
||||
gatewayClientScopes?: readonly string[],
|
||||
): boolean {
|
||||
if (Array.isArray(gatewayClientScopes)) {
|
||||
return !gatewayClientScopes.includes(PHONE_ADMIN_SCOPE);
|
||||
}
|
||||
return channel === "webchat";
|
||||
}
|
||||
|
||||
function formatStatus(state: ArmStateFile | null): string {
|
||||
if (!state) {
|
||||
return "Phone control: disarmed.";
|
||||
@@ -358,10 +369,7 @@ export default definePluginEntry({
|
||||
}
|
||||
|
||||
if (action === "disarm") {
|
||||
if (
|
||||
(ctx.channel === "webchat" || Array.isArray(ctx.gatewayClientScopes)) &&
|
||||
!ctx.gatewayClientScopes?.includes("operator.admin")
|
||||
) {
|
||||
if (requiresAdminToMutatePhoneControl(ctx.channel, ctx.gatewayClientScopes)) {
|
||||
return {
|
||||
text: "⚠️ /phone disarm requires operator.admin.",
|
||||
};
|
||||
@@ -383,10 +391,7 @@ export default definePluginEntry({
|
||||
}
|
||||
|
||||
if (action === "arm") {
|
||||
if (
|
||||
(ctx.channel === "webchat" || Array.isArray(ctx.gatewayClientScopes)) &&
|
||||
!ctx.gatewayClientScopes?.includes("operator.admin")
|
||||
) {
|
||||
if (requiresAdminToMutatePhoneControl(ctx.channel, ctx.gatewayClientScopes)) {
|
||||
return {
|
||||
text: "⚠️ /phone arm requires operator.admin.",
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user