@microsoft/teams.apps 2.0.0-preview.8 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/app.d.ts +6 -5
- package/dist/app.embed.js +2 -2
- package/dist/app.js +19 -11
- package/dist/app.oauth.d.ts +3 -2
- package/dist/app.oauth.js +5 -3
- package/dist/app.process.js +21 -7
- package/dist/app.routing.d.ts +8 -4
- package/dist/app.routing.js +2 -1
- package/dist/contexts/activity-signin.d.ts +1 -1
- package/dist/contexts/activity.d.ts +23 -9
- package/dist/contexts/activity.js +15 -17
- package/dist/middleware/index.d.ts +2 -2
- package/dist/middleware/index.js +6 -5
- package/dist/middleware/jwt-validation-middleware.js +6 -6
- package/dist/middleware/strip-mentions-text.d.ts +1 -1
- package/dist/middleware/strip-mentions-text.js +1 -1
- package/dist/middleware/with-remote-function-jwt-validation.d.ts +16 -0
- package/dist/middleware/with-remote-function-jwt-validation.js +47 -0
- package/dist/plugins/http/plugin.d.ts +3 -3
- package/dist/plugins/http/plugin.js +2 -2
- package/dist/plugins/http/stream.d.ts +7 -4
- package/dist/plugins/http/stream.js +72 -33
- package/dist/router/index.d.ts +1 -0
- package/dist/router/index.js +18 -0
- package/dist/router/route.d.ts +9 -0
- package/dist/router/route.js +3 -0
- package/dist/router/router.d.ts +29 -0
- package/dist/router/router.js +101 -0
- package/dist/routes/activity.d.ts +2 -2
- package/dist/routes/conversation-update.d.ts +2 -2
- package/dist/routes/event.d.ts +2 -2
- package/dist/routes/index.d.ts +7 -6
- package/dist/routes/index.js +4 -4
- package/dist/routes/install.d.ts +2 -2
- package/dist/routes/invoke/index.d.ts +2 -2
- package/dist/routes/message-delete.d.ts +2 -2
- package/dist/routes/message-update.d.ts +2 -2
- package/dist/types/app-events.d.ts +1 -1
- package/dist/types/app-routing.d.ts +11 -0
- package/dist/types/app-routing.js +3 -0
- package/dist/types/plugin/plugin-start-event.d.ts +1 -1
- package/dist/types/plugin/plugin.d.ts +2 -2
- package/dist/types/route-handler.d.ts +1 -1
- package/dist/types/streamer.d.ts +5 -0
- package/package.json +5 -5
- package/dist/middleware/entra-token-validator.d.ts +0 -75
- package/dist/middleware/entra-token-validator.js +0 -169
- package/dist/middleware/with-client-auth.d.ts +0 -13
- package/dist/middleware/with-client-auth.js +0 -45
- package/dist/router.d.ts +0 -34
- package/dist/router.js +0 -91
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.withClientAuth = withClientAuth;
|
|
4
|
-
function withClientAuth(params) {
|
|
5
|
-
const entraTokenValidator = params.entraTokenValidator;
|
|
6
|
-
const log = params.logger;
|
|
7
|
-
return async (req, res, next) => {
|
|
8
|
-
const appSessionId = req.header('X-Teams-App-Session-Id');
|
|
9
|
-
const pageId = req.header('X-Teams-Page-Id');
|
|
10
|
-
const authorization = req.header('Authorization')?.split(' ');
|
|
11
|
-
const authToken = authorization?.length === 2 && authorization[0].toLowerCase() === 'bearer'
|
|
12
|
-
? authorization[1]
|
|
13
|
-
: '';
|
|
14
|
-
const validatedToken = !entraTokenValidator
|
|
15
|
-
? null
|
|
16
|
-
: await entraTokenValidator.validateAccessToken(log, authToken);
|
|
17
|
-
const tokenPayload = validatedToken && entraTokenValidator?.getTokenPayload(validatedToken);
|
|
18
|
-
if (!pageId ||
|
|
19
|
-
!appSessionId ||
|
|
20
|
-
!validatedToken ||
|
|
21
|
-
!entraTokenValidator ||
|
|
22
|
-
!tokenPayload) {
|
|
23
|
-
log.debug('unauthorized');
|
|
24
|
-
res.status(401).send('unauthorized');
|
|
25
|
-
return;
|
|
26
|
-
}
|
|
27
|
-
req.context = {
|
|
28
|
-
appId: tokenPayload?.['appId'],
|
|
29
|
-
appSessionId,
|
|
30
|
-
authToken,
|
|
31
|
-
channelId: req.header('X-Teams-Channel-Id'),
|
|
32
|
-
chatId: req.header('X-Teams-Chat-Id'),
|
|
33
|
-
meetingId: req.header('X-Teams-Meeting-Id'),
|
|
34
|
-
messageId: req.header('X-Teams-Message-Id'),
|
|
35
|
-
pageId,
|
|
36
|
-
subPageId: req.header('X-Teams-Sub-Page-Id'),
|
|
37
|
-
teamId: req.header('X-Teams-Team-Id'),
|
|
38
|
-
tenantId: tokenPayload['tid'],
|
|
39
|
-
userId: tokenPayload['oid'],
|
|
40
|
-
userName: tokenPayload['name'],
|
|
41
|
-
};
|
|
42
|
-
next();
|
|
43
|
-
};
|
|
44
|
-
}
|
|
45
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid2l0aC1jbGllbnQtYXV0aC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9taWRkbGV3YXJlL3dpdGgtY2xpZW50LWF1dGgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFxQkEsd0NBcURDO0FBckRELFNBQWdCLGNBQWMsQ0FBQyxNQUE0QjtJQUN6RCxNQUFNLG1CQUFtQixHQUFHLE1BQU0sQ0FBQyxtQkFBbUIsQ0FBQztJQUN2RCxNQUFNLEdBQUcsR0FBRyxNQUFNLENBQUMsTUFBTSxDQUFDO0lBRTFCLE9BQU8sS0FBSyxFQUNWLEdBQXNCLEVBQ3RCLEdBQXFCLEVBQ3JCLElBQTBCLEVBQzFCLEVBQUU7UUFDRixNQUFNLFlBQVksR0FBRyxHQUFHLENBQUMsTUFBTSxDQUFDLHdCQUF3QixDQUFDLENBQUM7UUFDMUQsTUFBTSxNQUFNLEdBQUcsR0FBRyxDQUFDLE1BQU0sQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO1FBQzdDLE1BQU0sYUFBYSxHQUFHLEdBQUcsQ0FBQyxNQUFNLENBQUMsZUFBZSxDQUFDLEVBQUUsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQzlELE1BQU0sU0FBUyxHQUNiLGFBQWEsRUFBRSxNQUFNLEtBQUssQ0FBQyxJQUFJLGFBQWEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxXQUFXLEVBQUUsS0FBSyxRQUFRO1lBQ3hFLENBQUMsQ0FBQyxhQUFhLENBQUMsQ0FBQyxDQUFDO1lBQ2xCLENBQUMsQ0FBQyxFQUFFLENBQUM7UUFFVCxNQUFNLGNBQWMsR0FBRyxDQUFDLG1CQUFtQjtZQUN6QyxDQUFDLENBQUMsSUFBSTtZQUNOLENBQUMsQ0FBQyxNQUFNLG1CQUFtQixDQUFDLG1CQUFtQixDQUFDLEdBQUcsRUFBRSxTQUFTLENBQUMsQ0FBQztRQUNsRSxNQUFNLFlBQVksR0FDaEIsY0FBYyxJQUFJLG1CQUFtQixFQUFFLGVBQWUsQ0FBQyxjQUFjLENBQUMsQ0FBQztRQUV6RSxJQUNFLENBQUMsTUFBTTtZQUNQLENBQUMsWUFBWTtZQUNiLENBQUMsY0FBYztZQUNmLENBQUMsbUJBQW1CO1lBQ3BCLENBQUMsWUFBWSxFQUNiLENBQUM7WUFDRCxHQUFHLENBQUMsS0FBSyxDQUFDLGNBQWMsQ0FBQyxDQUFDO1lBQzFCLEdBQUcsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxDQUFDO1lBQ3JDLE9BQU87UUFDVCxDQUFDO1FBRUQsR0FBRyxDQUFDLE9BQU8sR0FBRztZQUNaLEtBQUssRUFBRSxZQUFZLEVBQUUsQ0FBQyxPQUFPLENBQUM7WUFDOUIsWUFBWTtZQUNaLFNBQVM7WUFDVCxTQUFTLEVBQUUsR0FBRyxDQUFDLE1BQU0sQ0FBQyxvQkFBb0IsQ0FBQztZQUMzQyxNQUFNLEVBQUUsR0FBRyxDQUFDLE1BQU0sQ0FBQyxpQkFBaUIsQ0FBQztZQUNyQyxTQUFTLEVBQUUsR0FBRyxDQUFDLE1BQU0sQ0FBQyxvQkFBb0IsQ0FBQztZQUMzQyxTQUFTLEVBQUUsR0FBRyxDQUFDLE1BQU0sQ0FBQyxvQkFBb0IsQ0FBQztZQUMzQyxNQUFNO1lBQ04sU0FBUyxFQUFFLEdBQUcsQ0FBQyxNQUFNLENBQUMscUJBQXFCLENBQUM7WUFDNUMsTUFBTSxFQUFFLEdBQUcsQ0FBQyxNQUFNLENBQUMsaUJBQWlCLENBQUM7WUFDckMsUUFBUSxFQUFFLFlBQVksQ0FBQyxLQUFLLENBQUM7WUFDN0IsTUFBTSxFQUFFLFlBQVksQ0FBQyxLQUFLLENBQUM7WUFDM0IsUUFBUSxFQUFFLFlBQVksQ0FBQyxNQUFNLENBQUM7U0FDL0IsQ0FBQztRQUVGLElBQUksRUFBRSxDQUFDO0lBQ1QsQ0FBQyxDQUFDO0FBQ0osQ0FBQyJ9
|
package/dist/router.d.ts
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import { Activity } from '@microsoft/teams.api';
|
|
2
|
-
import { IActivityContext } from './contexts';
|
|
3
|
-
import { IRoutes } from './routes';
|
|
4
|
-
import { RouteHandler } from './types';
|
|
5
|
-
type Route<Name extends keyof IRoutes = keyof IRoutes> = {
|
|
6
|
-
readonly name?: Name;
|
|
7
|
-
readonly select: (activity: Activity) => boolean;
|
|
8
|
-
readonly callback: IRoutes[Name];
|
|
9
|
-
};
|
|
10
|
-
export declare class Router {
|
|
11
|
-
protected readonly routes: Route[];
|
|
12
|
-
/**
|
|
13
|
-
* select routes that match the inbound activity
|
|
14
|
-
* @param activity the inbound activity
|
|
15
|
-
*/
|
|
16
|
-
select(activity: Activity): RouteHandler<IActivityContext<Activity>, any>[];
|
|
17
|
-
/**
|
|
18
|
-
* register a new route
|
|
19
|
-
* @param route the route to register
|
|
20
|
-
*/
|
|
21
|
-
register<Name extends keyof IRoutes>(route: Route<Name>): this;
|
|
22
|
-
/**
|
|
23
|
-
* register a middleware
|
|
24
|
-
* @param callback the callback to invoke
|
|
25
|
-
*/
|
|
26
|
-
use(callback: RouteHandler<IActivityContext, any>): this;
|
|
27
|
-
/**
|
|
28
|
-
* register an activity route
|
|
29
|
-
* @param event event to subscribe to
|
|
30
|
-
* @param callback the callback to invoke
|
|
31
|
-
*/
|
|
32
|
-
on<Name extends keyof IRoutes>(event: Name, callback: Exclude<IRoutes[Name], undefined>): this;
|
|
33
|
-
}
|
|
34
|
-
export {};
|
package/dist/router.js
DELETED
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.Router = void 0;
|
|
4
|
-
const routes_1 = require("./routes");
|
|
5
|
-
class Router {
|
|
6
|
-
routes = [];
|
|
7
|
-
/**
|
|
8
|
-
* select routes that match the inbound activity
|
|
9
|
-
* @param activity the inbound activity
|
|
10
|
-
*/
|
|
11
|
-
select(activity) {
|
|
12
|
-
return this.routes
|
|
13
|
-
.filter((r) => r.select(activity))
|
|
14
|
-
.map((r) => r.callback);
|
|
15
|
-
}
|
|
16
|
-
/**
|
|
17
|
-
* register a new route
|
|
18
|
-
* @param route the route to register
|
|
19
|
-
*/
|
|
20
|
-
register(route) {
|
|
21
|
-
this.routes.push(route);
|
|
22
|
-
return this;
|
|
23
|
-
}
|
|
24
|
-
/**
|
|
25
|
-
* register a middleware
|
|
26
|
-
* @param callback the callback to invoke
|
|
27
|
-
*/
|
|
28
|
-
use(callback) {
|
|
29
|
-
this.register({
|
|
30
|
-
select: () => true,
|
|
31
|
-
callback,
|
|
32
|
-
});
|
|
33
|
-
return this;
|
|
34
|
-
}
|
|
35
|
-
/**
|
|
36
|
-
* register an activity route
|
|
37
|
-
* @param event event to subscribe to
|
|
38
|
-
* @param callback the callback to invoke
|
|
39
|
-
*/
|
|
40
|
-
on(event, callback) {
|
|
41
|
-
this.register({
|
|
42
|
-
name: event,
|
|
43
|
-
select: (activity) => {
|
|
44
|
-
if (event === 'activity') {
|
|
45
|
-
return true;
|
|
46
|
-
}
|
|
47
|
-
if (event === activity.type) {
|
|
48
|
-
return true;
|
|
49
|
-
}
|
|
50
|
-
if (activity.type === 'conversationUpdate') {
|
|
51
|
-
return event === activity.channelData?.eventType;
|
|
52
|
-
}
|
|
53
|
-
if (activity.type === 'installationUpdate') {
|
|
54
|
-
return event === `install.${activity.action}`;
|
|
55
|
-
}
|
|
56
|
-
if (activity.type === 'messageDelete') {
|
|
57
|
-
return event === activity.channelData?.eventType;
|
|
58
|
-
}
|
|
59
|
-
if (activity.type === 'messageUpdate') {
|
|
60
|
-
return event === activity.channelData?.eventType;
|
|
61
|
-
}
|
|
62
|
-
if (activity.type === 'event') {
|
|
63
|
-
return event === routes_1.EVENT_ALIASES[activity.name];
|
|
64
|
-
}
|
|
65
|
-
if (activity.type === 'invoke') {
|
|
66
|
-
if (event === routes_1.INVOKE_ALIASES[activity.name]) {
|
|
67
|
-
return true;
|
|
68
|
-
}
|
|
69
|
-
if (activity.name === 'fileConsent/invoke') {
|
|
70
|
-
return event === `file.consent.${activity.value.action}`;
|
|
71
|
-
}
|
|
72
|
-
if (activity.name === 'composeExtension/submitAction') {
|
|
73
|
-
return event === `message.ext.${activity.value.botMessagePreviewAction}`;
|
|
74
|
-
}
|
|
75
|
-
if (activity.name === 'message/submitAction') {
|
|
76
|
-
return event === `message.submit.${activity.value.actionName}`;
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
// custom routes
|
|
80
|
-
if (event === 'mention' && activity.entities?.some((e) => e.type === 'mention')) {
|
|
81
|
-
return (activity.entities?.find((e) => e.type === 'mention' && e.mentioned.id === activity.recipient.id) !== undefined);
|
|
82
|
-
}
|
|
83
|
-
return false;
|
|
84
|
-
},
|
|
85
|
-
callback,
|
|
86
|
-
});
|
|
87
|
-
return this;
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
exports.Router = Router;
|
|
91
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL3JvdXRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFHQSxxQ0FBa0U7QUFTbEUsTUFBYSxNQUFNO0lBQ0UsTUFBTSxHQUFZLEVBQUUsQ0FBQztJQUV4Qzs7O09BR0c7SUFDSCxNQUFNLENBQUMsUUFBa0I7UUFDdkIsT0FBTyxJQUFJLENBQUMsTUFBTTthQUNmLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQzthQUNqQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxRQUErQyxDQUFDLENBQUM7SUFDbkUsQ0FBQztJQUVEOzs7T0FHRztJQUNILFFBQVEsQ0FBNkIsS0FBa0I7UUFDckQsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDeEIsT0FBTyxJQUFJLENBQUM7SUFDZCxDQUFDO0lBRUQ7OztPQUdHO0lBQ0gsR0FBRyxDQUFDLFFBQTZDO1FBQy9DLElBQUksQ0FBQyxRQUFRLENBQUM7WUFDWixNQUFNLEVBQUUsR0FBRyxFQUFFLENBQUMsSUFBSTtZQUNsQixRQUFRO1NBQ1QsQ0FBQyxDQUFDO1FBRUgsT0FBTyxJQUFJLENBQUM7SUFDZCxDQUFDO0lBRUQ7Ozs7T0FJRztJQUNILEVBQUUsQ0FBNkIsS0FBVyxFQUFFLFFBQTJDO1FBQ3JGLElBQUksQ0FBQyxRQUFRLENBQUM7WUFDWixJQUFJLEVBQUUsS0FBSztZQUNYLE1BQU0sRUFBRSxDQUFDLFFBQVEsRUFBRSxFQUFFO2dCQUNuQixJQUFJLEtBQUssS0FBSyxVQUFVLEVBQUUsQ0FBQztvQkFDekIsT0FBTyxJQUFJLENBQUM7Z0JBQ2QsQ0FBQztnQkFFRCxJQUFJLEtBQUssS0FBSyxRQUFRLENBQUMsSUFBSSxFQUFFLENBQUM7b0JBQzVCLE9BQU8sSUFBSSxDQUFD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
|