fix(msteams): use manual delegated oauth setup

This commit is contained in:
Vincent Koc
2026-05-02 16:35:19 -07:00
parent eb907508e8
commit 366f1ea706
2 changed files with 4 additions and 44 deletions

View File

@@ -1,10 +1,7 @@
import { EventEmitter } from "node:events";
import { DEFAULT_ACCOUNT_ID } from "openclaw/plugin-sdk/setup";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { createMSTeamsSetupWizardBase, msteamsSetupAdapter } from "./setup-core.js";
import { openDelegatedOAuthUrl } from "./setup-surface.js";
const spawn = vi.hoisted(() => vi.fn());
const resolveMSTeamsUserAllowlist = vi.hoisted(() => vi.fn());
const resolveMSTeamsChannelAllowlist = vi.hoisted(() => vi.fn());
const normalizeSecretInputString = vi.hoisted(() =>
@@ -28,19 +25,10 @@ vi.mock("./token.js", () => ({
resolveMSTeamsCredentials,
}));
vi.mock("node:child_process", async (importOriginal) => {
const actual = await importOriginal<typeof import("node:child_process")>();
return {
...actual,
spawn,
};
});
describe("msteams setup surface", () => {
const msteamsSetupWizard = createMSTeamsSetupWizardBase();
beforeEach(() => {
spawn.mockReset();
resolveMSTeamsUserAllowlist.mockReset();
resolveMSTeamsChannelAllowlist.mockReset();
normalizeSecretInputString.mockClear();
@@ -58,21 +46,6 @@ describe("msteams setup surface", () => {
);
});
it("opens delegated OAuth URLs without invoking a shell", async () => {
const url = "https://login.microsoftonline.com/auth?state=$(touch pwned)";
const child = new EventEmitter();
spawn.mockReturnValue(child);
const result = openDelegatedOAuthUrl(url);
child.emit("exit", 0, null);
await expect(result).resolves.toBeUndefined();
expect(spawn).toHaveBeenCalledWith(process.platform === "darwin" ? "open" : "xdg-open", [url], {
stdio: "ignore",
shell: false,
});
});
it("enables the msteams channel without dropping existing config", () => {
expect(
msteamsSetupAdapter.applyAccountConfig?.({

View File

@@ -1,4 +1,3 @@
import { spawn } from "node:child_process";
import {
createTopLevelChannelAllowFromSetter,
createTopLevelChannelDmPolicy,
@@ -30,19 +29,9 @@ const setMSTeamsGroupPolicy = createTopLevelChannelGroupPolicySetter({
});
export function openDelegatedOAuthUrl(url: string): Promise<void> {
return new Promise<void>((resolve, reject) => {
const cmd = process.platform === "darwin" ? "open" : "xdg-open";
const child = spawn(cmd, [url], { stdio: "ignore", shell: false });
child.once("error", reject);
child.once("exit", (code, signal) => {
if (code === 0) {
resolve();
return;
}
const reason = signal ? `signal ${signal}` : `code ${code ?? "unknown"}`;
reject(new Error(`${cmd} failed with ${reason}`));
});
});
return Promise.reject(
new Error(`Automatic browser launch is not available. Open this URL manually: ${url}`),
);
}
function looksLikeGuid(value: string): boolean {
@@ -277,12 +266,10 @@ export const msteamsSetupWizard: ChannelSetupWizard = {
};
try {
const { loginMSTeamsDelegated } = await import("./oauth.js");
const { shouldUseManualOAuthFlow } = await import("./oauth.flow.js");
const isRemote = Boolean(process.env.SSH_TTY || process.env.SSH_CONNECTION);
const progress = params.prompter.progress("MSTeams Delegated OAuth");
const tokens = await loginMSTeamsDelegated(
{
isRemote: shouldUseManualOAuthFlow(isRemote),
isRemote: true,
openUrl: openDelegatedOAuthUrl,
log: (msg) => params.prompter.note(msg),
note: (msg, title) => params.prompter.note(msg, title),