fix: route Teams sign-in invokes to OAuth dialog + use UserTokenClient for sign-out
All checks were successful
Build and Deploy Teams Planner Bot / build-and-run (push) Successful in 30s
All checks were successful
Build and Deploy Teams Planner Bot / build-and-run (push) Successful in 30s
This commit is contained in:
parent
fd504738eb
commit
e42b3d7c43
BIN
appPackage/color.png
Normal file
BIN
appPackage/color.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 20 KiB |
@ -1,8 +1,8 @@
|
||||
{
|
||||
"$schema": "https://developer.microsoft.com/en-us/json-schemas/teams/v1.16/MicrosoftTeams.schema.json",
|
||||
"manifestVersion": "1.16",
|
||||
"version": "0.1.0",
|
||||
"id": "REPLACE_WITH_YOUR_BOT_APP_ID",
|
||||
"version": "1.0.0",
|
||||
"id": "1d0c2212-0bae-46af-babd-6c5223d2ee4c",
|
||||
"packageName": "com.example.teamsplannerbot",
|
||||
"developer": {
|
||||
"name": "Internal",
|
||||
@ -25,7 +25,7 @@
|
||||
"accentColor": "#4F6BED",
|
||||
"bots": [
|
||||
{
|
||||
"botId": "REPLACE_WITH_YOUR_BOT_APP_ID",
|
||||
"botId": "1d0c2212-0bae-46af-babd-6c5223d2ee4c",
|
||||
"scopes": ["personal", "team", "groupchat"],
|
||||
"supportsFiles": false,
|
||||
"isNotificationOnly": false,
|
||||
@ -42,7 +42,7 @@
|
||||
"permissions": ["identity", "messageTeamMembers"],
|
||||
"validDomains": ["token.botframework.com"],
|
||||
"webApplicationInfo": {
|
||||
"id": "REPLACE_WITH_YOUR_BOT_APP_ID",
|
||||
"id": "1d0c2212-0bae-46af-babd-6c5223d2ee4c",
|
||||
"resource": "https://graph.microsoft.com/"
|
||||
}
|
||||
}
|
||||
|
||||
BIN
appPackage/outline.png
Normal file
BIN
appPackage/outline.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.0 KiB |
@ -1,17 +1,34 @@
|
||||
import {
|
||||
ActivityHandler,
|
||||
CardFactory,
|
||||
CloudAdapter,
|
||||
ConversationState,
|
||||
StatePropertyAccessor,
|
||||
TeamsActivityHandler,
|
||||
TurnContext,
|
||||
UserState,
|
||||
} from "botbuilder";
|
||||
import { UserTokenClient } from "botframework-connector";
|
||||
import { OAuthPrompt, DialogSet, DialogTurnStatus, WaterfallDialog } from "botbuilder-dialogs";
|
||||
import { createGraphClient } from "../graph/graphClientFactory";
|
||||
import { PlannerClient } from "../graph/plannerClient";
|
||||
import { LlmClassifier } from "../llm/types";
|
||||
import { buildResultCard } from "../cards/confirmationCard";
|
||||
|
||||
async function signOutUser(context: TurnContext, connectionName: string): Promise<void> {
|
||||
const adapter = context.adapter as CloudAdapter;
|
||||
const userTokenClient = context.turnState.get<UserTokenClient>(
|
||||
(adapter as unknown as { UserTokenClientKey: symbol }).UserTokenClientKey,
|
||||
);
|
||||
if (!userTokenClient) {
|
||||
throw new Error("UserTokenClient not available on this adapter");
|
||||
}
|
||||
await userTokenClient.signOutUser(
|
||||
context.activity.from.id,
|
||||
connectionName,
|
||||
context.activity.channelId,
|
||||
);
|
||||
}
|
||||
|
||||
const OAUTH_PROMPT = "graphOAuthPrompt";
|
||||
const MAIN_DIALOG = "mainDialog";
|
||||
|
||||
@ -22,12 +39,13 @@ export interface PlannerBotDeps {
|
||||
connectionName: string; // Azure Bot OAuth connection name
|
||||
}
|
||||
|
||||
export class PlannerBot extends ActivityHandler {
|
||||
export class PlannerBot extends TeamsActivityHandler {
|
||||
private readonly conversationState: ConversationState;
|
||||
private readonly userState: UserState;
|
||||
private readonly classifier: LlmClassifier;
|
||||
private readonly dialogs: DialogSet;
|
||||
private readonly dialogStateAccessor: StatePropertyAccessor;
|
||||
private readonly connectionName: string;
|
||||
|
||||
constructor(deps: PlannerBotDeps) {
|
||||
super();
|
||||
@ -35,6 +53,7 @@ export class PlannerBot extends ActivityHandler {
|
||||
this.userState = deps.userState;
|
||||
this.classifier = deps.classifier;
|
||||
|
||||
this.connectionName = deps.connectionName;
|
||||
this.dialogStateAccessor = this.conversationState.createProperty("DialogState");
|
||||
this.dialogs = new DialogSet(this.dialogStateAccessor);
|
||||
|
||||
@ -67,10 +86,7 @@ export class PlannerBot extends ActivityHandler {
|
||||
const text = (context.activity.text ?? "").trim();
|
||||
|
||||
if (text.toLowerCase() === "logout") {
|
||||
const adapter = context.adapter as unknown as {
|
||||
signOutUser: (ctx: TurnContext, connName: string) => Promise<void>;
|
||||
};
|
||||
await adapter.signOutUser(context, deps.connectionName);
|
||||
await signOutUser(context, this.connectionName);
|
||||
await context.sendActivity("로그아웃 완료.");
|
||||
await next();
|
||||
return;
|
||||
@ -89,6 +105,15 @@ export class PlannerBot extends ActivityHandler {
|
||||
await next();
|
||||
});
|
||||
|
||||
// Teams sends an invoke activity ("signin/verifyState" or "signin/tokenExchange")
|
||||
// after the user completes the OAuth flow. We must route it back into the
|
||||
// active dialog so OAuthPrompt can finish.
|
||||
this.onTokenResponseEvent(async (context, next) => {
|
||||
const dialogContext = await this.dialogs.createContext(context);
|
||||
await dialogContext.continueDialog();
|
||||
await next();
|
||||
});
|
||||
|
||||
this.onMembersAdded(async (context, next) => {
|
||||
const greeting =
|
||||
"안녕하세요! 작업 진행 상황을 평소 말로 알려주시면 Planner에 자동으로 정리해 드릴게요.\n" +
|
||||
@ -108,6 +133,16 @@ export class PlannerBot extends ActivityHandler {
|
||||
await this.userState.saveChanges(context, false);
|
||||
}
|
||||
|
||||
protected async handleTeamsSigninVerifyState(context: TurnContext): Promise<void> {
|
||||
const dialogContext = await this.dialogs.createContext(context);
|
||||
await dialogContext.continueDialog();
|
||||
}
|
||||
|
||||
protected async handleTeamsSigninTokenExchange(context: TurnContext): Promise<void> {
|
||||
const dialogContext = await this.dialogs.createContext(context);
|
||||
await dialogContext.continueDialog();
|
||||
}
|
||||
|
||||
private async handleUtterance(
|
||||
context: TurnContext,
|
||||
token: string,
|
||||
|
||||
BIN
teams-planner-bot.zip
Normal file
BIN
teams-planner-bot.zip
Normal file
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user